Message ID | 1421919662-21066-3-git-send-email-dborkman@redhat.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
On Thu, Jan 22, 2015 at 1:41 AM, Daniel Borkmann <dborkman@redhat.com> wrote: > When creating a bpf classifier in tc with priority collisions and > invoking automatic unique handle assignment, cls_bpf_grab_new_handle() > will return a wrong handle id which in fact is non-unique. Usually > altering of specific filters is being addressed over major id, but > in case of collisions we result in a filter chain, where handle ids > address individual cls_bpf_progs inside the classifier. > > Issue is, in cls_bpf_grab_new_handle() we probe for head->hgen handle > in cls_bpf_get() and in case we found a free handle, we're supposed > to use exactly head->hgen. In case of insufficient numbers of handles, > we bail out later as handle id 0 is not allowed. > > Fixes: 7d1d65cb84e1 ("net: sched: cls_bpf: add BPF-based classifier") > Signed-off-by: Daniel Borkmann <dborkman@redhat.com> > Acked-by: Jiri Pirko <jiri@resnulli.us> Acked-by: Alexei Starovoitov <ast@plumgrid.com> interesting bug. first time I'm looking at this bit and wondering why everyone copy pasting such hgenerator instead of using idr... -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 01/22/2015 07:52 PM, Alexei Starovoitov wrote: ... > interesting bug. first time I'm looking at this bit and wondering > why everyone copy pasting such hgenerator instead of using idr... I think we should abstract these bits into a helper function. ;) Hmm, looking into git history tree, hgenerator came later than idr, so I presume the overhead of idr was not worth it. -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 49e5fa8..f59adf8 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -220,15 +220,21 @@ static u32 cls_bpf_grab_new_handle(struct tcf_proto *tp, struct cls_bpf_head *head) { unsigned int i = 0x80000000; + u32 handle; do { if (++head->hgen == 0x7FFFFFFF) head->hgen = 1; } while (--i > 0 && cls_bpf_get(tp, head->hgen)); - if (i == 0) + + if (unlikely(i == 0)) { pr_err("Insufficient number of handles\n"); + handle = 0; + } else { + handle = head->hgen; + } - return i; + return handle; } static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,