[net] net: sched: sch_ingress: do not report ingress filter info in egress path
diff mbox series

Message ID 738244fd5863e6228275ee8f71e81d6baafca243.1558442828.git.lorenzo.bianconi@redhat.com
State Rejected
Delegated to: David Miller
Headers show
Series
  • [net] net: sched: sch_ingress: do not report ingress filter info in egress path
Related show

Commit Message

Lorenzo Bianconi May 21, 2019, 12:59 p.m. UTC
Currently if we add a filter to the ingress qdisc (e.g matchall) the
filter data are reported even in the egress path. The issue can be
triggered with the following reproducer:

$tc qdisc add dev lo ingress
$tc filter add dev lo ingress matchall action ok
$tc filter show dev lo ingress
filter protocol all pref 49152 matchall chain 0
filter protocol all pref 49152 matchall chain 0 handle 0x1
  not_in_hw
	action order 1: gact action pass
		 random type none pass val 0
		 	 index 1 ref 1 bind 1

$tc filter show dev lo egress
filter protocol all pref 49152 matchall chain 0
filter protocol all pref 49152 matchall chain 0 handle 0x1
  not_in_hw
	action order 1: gact action pass
		 random type none pass val 0
		 	 index 1 ref 1 bind 1

Fix it reporting NULL for non-ingress filters in ingress_tcf_block
routine

Fixes: 6529eaba33f0 ("net: sched: introduce tcf block infrastructure")
Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
---
 net/sched/sch_ingress.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

Comments

Davide Caratti May 22, 2019, 9:14 a.m. UTC | #1
On Tue, 2019-05-21 at 14:59 +0200, Lorenzo Bianconi wrote:
> Currently if we add a filter to the ingress qdisc (e.g matchall) the
> filter data are reported even in the egress path. The issue can be
> triggered with the following reproducer:
> 
> $tc qdisc add dev lo ingress
> $tc filter add dev lo ingress matchall action ok
> $tc filter show dev lo ingress
> filter protocol all pref 49152 matchall chain 0
> filter protocol all pref 49152 matchall chain 0 handle 0x1
>   not_in_hw
> 	action order 1: gact action pass
> 		 random type none pass val 0
> 		 	 index 1 ref 1 bind 1
> 
> $tc filter show dev lo egress
> filter protocol all pref 49152 matchall chain 0
> filter protocol all pref 49152 matchall chain 0 handle 0x1
>   not_in_hw
> 	action order 1: gact action pass
> 		 random type none pass val 0
> 		 	 index 1 ref 1 bind 1
> 
> Fix it reporting NULL for non-ingress filters in ingress_tcf_block
> routine
> 
> Fixes: 6529eaba33f0 ("net: sched: introduce tcf block infrastructure")
> Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@redhat.com>
> ---
>  net/sched/sch_ingress.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
> index 0bac926b46c7..1825347fed3a 100644
> --- a/net/sched/sch_ingress.c
> +++ b/net/sched/sch_ingress.c
> @@ -31,7 +31,7 @@ static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
>  
>  static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
>  {
> -	return TC_H_MIN(classid) + 1;
> +	return TC_H_MIN(classid);

probably this breaks a command that was wrong before, but it's worth
mentioning. Because of the above hunk, the following command

# tc qdisc add dev test0 ingress
# tc filter add dev test0 parent ffff:fff1 matchall action drop
# tc filter add dev test0 parent ffff: matchall action continue

gave no errors, and dropped packets on unpatched kernel. With this patch,
the kernel refuses to add the 'matchall' rules (and because of that,
traffic passes).

running TDC, it seems that a patched kernel does not pass anymore
some of the test cases belonging to the 'filter' category:

# ./tdc.py -e 901f
Test 901f: Add fw filter with prio at 32-bit maxixum
exit: 2
exit: 0
RTNETLINK answers: Invalid argument
We have an error talking to the kernel, -1

All test results:
1..1
not ok 1 901f - Add fw filter with prio at 32-bit maxixum
        Command exited with 2, expected 0
RTNETLINK answers: Invalid argument
We have an error talking to the kernel, -1

(the same test is passing on a unpatched kernel)

Do you think it's worth fixing those test cases too?

thanks a lot!
Lorenzo Bianconi May 22, 2019, 10:20 a.m. UTC | #2
> On Tue, 2019-05-21 at 14:59 +0200, Lorenzo Bianconi wrote:
> > Currently if we add a filter to the ingress qdisc (e.g matchall) the
> > filter data are reported even in the egress path. The issue can be
> > triggered with the following reproducer:
> > 

[...]

> > diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
> > index 0bac926b46c7..1825347fed3a 100644
> > --- a/net/sched/sch_ingress.c
> > +++ b/net/sched/sch_ingress.c
> > @@ -31,7 +31,7 @@ static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
> >  
> >  static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
> >  {
> > -	return TC_H_MIN(classid) + 1;
> > +	return TC_H_MIN(classid);
> 
> probably this breaks a command that was wrong before, but it's worth
> mentioning. Because of the above hunk, the following command
> 
> # tc qdisc add dev test0 ingress
> # tc filter add dev test0 parent ffff:fff1 matchall action drop
> # tc filter add dev test0 parent ffff: matchall action continue
> 
> gave no errors, and dropped packets on unpatched kernel. With this patch,
> the kernel refuses to add the 'matchall' rules (and because of that,
> traffic passes).
> 
> running TDC, it seems that a patched kernel does not pass anymore
> some of the test cases belonging to the 'filter' category:
> 
> # ./tdc.py -e 901f
> Test 901f: Add fw filter with prio at 32-bit maxixum
> exit: 2
> exit: 0
> RTNETLINK answers: Invalid argument
> We have an error talking to the kernel, -1
> 
> All test results:
> 1..1
> not ok 1 901f - Add fw filter with prio at 32-bit maxixum
>         Command exited with 2, expected 0
> RTNETLINK answers: Invalid argument
> We have an error talking to the kernel, -1
> 
> (the same test is passing on a unpatched kernel)
> 
> Do you think it's worth fixing those test cases too?
> 
> thanks a lot!
> -- 
> davide

Hi Davide,

thx to point this out. Applying this patch the ingress qdisc has the same
behaviour of clsact one.

$tc qdisc add dev lo clsact
$tc filter add dev lo parent ffff:fff1 matchall action drop
Error: Specified class doesn't exist.
We have an error talking to the kernel, -1
$tc filter add dev lo parent ffff:fff2 matchall action drop

$tc qdisc add dev lo ingress
$tc filter add dev lo parent ffff:fff2 matchall action drop

is it acceptable? If so I can fix the tests as well
If not, is there another way to verify the filter is for the ingress path if
parent identifier is not constant? (ingress_find() reports the TC_H_MIN of
parent identifier)

Regards,
Lorenzo

> 
> >  }
> >  
> >  static unsigned long ingress_bind_filter(struct Qdisc *sch,
> > @@ -53,7 +53,12 @@ static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl,
> >  {
> >  	struct ingress_sched_data *q = qdisc_priv(sch);
> >  
> > -	return q->block;
> > +	switch (cl) {
> > +	case TC_H_MIN(TC_H_MIN_INGRESS):
> > +		return q->block;
> > +	default:
> > +		return NULL;
> > +	}
> >  }
> >  
> >  static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
> 
>
Daniel Borkmann May 22, 2019, 10:59 a.m. UTC | #3
On 05/22/2019 12:20 PM, Lorenzo Bianconi wrote:
>> On Tue, 2019-05-21 at 14:59 +0200, Lorenzo Bianconi wrote:
>>> Currently if we add a filter to the ingress qdisc (e.g matchall) the
>>> filter data are reported even in the egress path. The issue can be
>>> triggered with the following reproducer:
> 
> [...]
> 
>>> diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
>>> index 0bac926b46c7..1825347fed3a 100644
>>> --- a/net/sched/sch_ingress.c
>>> +++ b/net/sched/sch_ingress.c
>>> @@ -31,7 +31,7 @@ static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
>>>  
>>>  static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
>>>  {
>>> -	return TC_H_MIN(classid) + 1;
>>> +	return TC_H_MIN(classid);
>>
>> probably this breaks a command that was wrong before, but it's worth
>> mentioning. Because of the above hunk, the following command
>>
>> # tc qdisc add dev test0 ingress
>> # tc filter add dev test0 parent ffff:fff1 matchall action drop
>> # tc filter add dev test0 parent ffff: matchall action continue
>>
>> gave no errors, and dropped packets on unpatched kernel. With this patch,
>> the kernel refuses to add the 'matchall' rules (and because of that,
>> traffic passes).
>>
>> running TDC, it seems that a patched kernel does not pass anymore
>> some of the test cases belonging to the 'filter' category:
>>
>> # ./tdc.py -e 901f
>> Test 901f: Add fw filter with prio at 32-bit maxixum
>> exit: 2
>> exit: 0
>> RTNETLINK answers: Invalid argument
>> We have an error talking to the kernel, -1
>>
>> All test results:
>> 1..1
>> not ok 1 901f - Add fw filter with prio at 32-bit maxixum
>>         Command exited with 2, expected 0
>> RTNETLINK answers: Invalid argument
>> We have an error talking to the kernel, -1
>>
>> (the same test is passing on a unpatched kernel)
>>
>> Do you think it's worth fixing those test cases too?
>>
>> thanks a lot!
>> -- 
>> davide
> 
> Hi Davide,
> 
> thx to point this out. Applying this patch the ingress qdisc has the same
> behaviour of clsact one.
> 
> $tc qdisc add dev lo clsact
> $tc filter add dev lo parent ffff:fff1 matchall action drop
> Error: Specified class doesn't exist.
> We have an error talking to the kernel, -1
> $tc filter add dev lo parent ffff:fff2 matchall action drop
> 
> $tc qdisc add dev lo ingress
> $tc filter add dev lo parent ffff:fff2 matchall action drop
> 
> is it acceptable? If so I can fix the tests as well
> If not, is there another way to verify the filter is for the ingress path if
> parent identifier is not constant? (ingress_find() reports the TC_H_MIN of
> parent identifier)

As far as I know this would break sch_ingress users ... For sch_ingress
any minor should be accepted. For sch_clsact, only 0xFFF2U and 0xFFF3U
are accepted, so it can be extended in future if needed. For old sch_ingress
that ship has sailed, which is why sch_clsact was needed in order to have
such selectors, see also 1f211a1b929c ("net, sched: add clsact qdisc").
Meaning, minors for sch_ingress are a superset of sch_clsact and not
compatible in that sense. If you adapt sch_ingress to the same behavior
as sch_clsact, things might break indeed as Davide pointed out.

> Regards,
> Lorenzo
> 
>>
>>>  }
>>>  
>>>  static unsigned long ingress_bind_filter(struct Qdisc *sch,
>>> @@ -53,7 +53,12 @@ static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl,
>>>  {
>>>  	struct ingress_sched_data *q = qdisc_priv(sch);
>>>  
>>> -	return q->block;
>>> +	switch (cl) {
>>> +	case TC_H_MIN(TC_H_MIN_INGRESS):
>>> +		return q->block;
>>> +	default:
>>> +		return NULL;
>>> +	}
>>>  }
>>>  
>>>  static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
>>
>>
Lorenzo Bianconi May 22, 2019, 12:13 p.m. UTC | #4
> On 05/22/2019 12:20 PM, Lorenzo Bianconi wrote:
> >> On Tue, 2019-05-21 at 14:59 +0200, Lorenzo Bianconi wrote:
> >>> Currently if we add a filter to the ingress qdisc (e.g matchall) the
> >>> filter data are reported even in the egress path. The issue can be
> >>> triggered with the following reproducer:
> > 
> > [...]
> > 
> >>> diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
> >>> index 0bac926b46c7..1825347fed3a 100644
> >>> --- a/net/sched/sch_ingress.c
> >>> +++ b/net/sched/sch_ingress.c
> >>> @@ -31,7 +31,7 @@ static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
> >>>  
> >>>  static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
> >>>  {
> >>> -	return TC_H_MIN(classid) + 1;
> >>> +	return TC_H_MIN(classid);
> >>
> >> probably this breaks a command that was wrong before, but it's worth
> >> mentioning. Because of the above hunk, the following command
> >>
> >> # tc qdisc add dev test0 ingress
> >> # tc filter add dev test0 parent ffff:fff1 matchall action drop
> >> # tc filter add dev test0 parent ffff: matchall action continue
> >>
> >> gave no errors, and dropped packets on unpatched kernel. With this patch,
> >> the kernel refuses to add the 'matchall' rules (and because of that,
> >> traffic passes).
> >>
> >> running TDC, it seems that a patched kernel does not pass anymore
> >> some of the test cases belonging to the 'filter' category:
> >>
> >> # ./tdc.py -e 901f
> >> Test 901f: Add fw filter with prio at 32-bit maxixum
> >> exit: 2
> >> exit: 0
> >> RTNETLINK answers: Invalid argument
> >> We have an error talking to the kernel, -1
> >>
> >> All test results:
> >> 1..1
> >> not ok 1 901f - Add fw filter with prio at 32-bit maxixum
> >>         Command exited with 2, expected 0
> >> RTNETLINK answers: Invalid argument
> >> We have an error talking to the kernel, -1
> >>
> >> (the same test is passing on a unpatched kernel)
> >>
> >> Do you think it's worth fixing those test cases too?
> >>
> >> thanks a lot!
> >> -- 
> >> davide
> > 
> > Hi Davide,
> > 
> > thx to point this out. Applying this patch the ingress qdisc has the same
> > behaviour of clsact one.
> > 
> > $tc qdisc add dev lo clsact
> > $tc filter add dev lo parent ffff:fff1 matchall action drop
> > Error: Specified class doesn't exist.
> > We have an error talking to the kernel, -1
> > $tc filter add dev lo parent ffff:fff2 matchall action drop
> > 
> > $tc qdisc add dev lo ingress
> > $tc filter add dev lo parent ffff:fff2 matchall action drop
> > 
> > is it acceptable? If so I can fix the tests as well
> > If not, is there another way to verify the filter is for the ingress path if
> > parent identifier is not constant? (ingress_find() reports the TC_H_MIN of
> > parent identifier)
> 
> As far as I know this would break sch_ingress users ... For sch_ingress
> any minor should be accepted. For sch_clsact, only 0xFFF2U and 0xFFF3U
> are accepted, so it can be extended in future if needed. For old sch_ingress
> that ship has sailed, which is why sch_clsact was needed in order to have
> such selectors, see also 1f211a1b929c ("net, sched: add clsact qdisc").
> Meaning, minors for sch_ingress are a superset of sch_clsact and not
> compatible in that sense. If you adapt sch_ingress to the same behavior
> as sch_clsact, things might break indeed as Davide pointed out.

Hi Daniel,

right, thx the clarification. So for the moment let's just drop this patch
and I will investigate if it is possible to not dump ingress info on egress
path in a different way.

Regards,
Lorenzo

> 
> > Regards,
> > Lorenzo
> > 
> >>
> >>>  }
> >>>  
> >>>  static unsigned long ingress_bind_filter(struct Qdisc *sch,
> >>> @@ -53,7 +53,12 @@ static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl,
> >>>  {
> >>>  	struct ingress_sched_data *q = qdisc_priv(sch);
> >>>  
> >>> -	return q->block;
> >>> +	switch (cl) {
> >>> +	case TC_H_MIN(TC_H_MIN_INGRESS):
> >>> +		return q->block;
> >>> +	default:
> >>> +		return NULL;
> >>> +	}
> >>>  }
> >>>  
> >>>  static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)
> >>
> >>
>

Patch
diff mbox series

diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c
index 0bac926b46c7..1825347fed3a 100644
--- a/net/sched/sch_ingress.c
+++ b/net/sched/sch_ingress.c
@@ -31,7 +31,7 @@  static struct Qdisc *ingress_leaf(struct Qdisc *sch, unsigned long arg)
 
 static unsigned long ingress_find(struct Qdisc *sch, u32 classid)
 {
-	return TC_H_MIN(classid) + 1;
+	return TC_H_MIN(classid);
 }
 
 static unsigned long ingress_bind_filter(struct Qdisc *sch,
@@ -53,7 +53,12 @@  static struct tcf_block *ingress_tcf_block(struct Qdisc *sch, unsigned long cl,
 {
 	struct ingress_sched_data *q = qdisc_priv(sch);
 
-	return q->block;
+	switch (cl) {
+	case TC_H_MIN(TC_H_MIN_INGRESS):
+		return q->block;
+	default:
+		return NULL;
+	}
 }
 
 static void clsact_chain_head_change(struct tcf_proto *tp_head, void *priv)