From: Eric Dumazet <eric.duma...@gmail.com>

                   -------------------
    This is a commit scheduled for the next v2.6.34 longterm release.
    http://git.kernel.org/?p=linux/kernel/git/paulg/longterm-queue-2.6.34.git
    If you see a problem with using this for longterm, please comment.
                   -------------------

commit 53b0f08042f04813cd1a7473dacd3edfacb28eb3 upstream.

Ben Pfaff reported a kernel oops and provided a test program to
reproduce it.

https://kerneltrap.org/mailarchive/linux-netdev/2010/5/21/6277805

tc_fill_qdisc() should not be called for builtin qdisc, or it
dereference a NULL pointer to get device ifindex.

Fix is to always use tc_qdisc_dump_ignore() before calling
tc_fill_qdisc().

Reported-by: Ben Pfaff <b...@nicira.com>
Signed-off-by: Eric Dumazet <eric.duma...@gmail.com>
Signed-off-by: David S. Miller <da...@davemloft.net>
Signed-off-by: Paul Gortmaker <paul.gortma...@windriver.com>
---
 net/sched/sch_api.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index 145268c..df1dbf5 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1196,6 +1196,11 @@ nla_put_failure:
        return -1;
 }
 
+static bool tc_qdisc_dump_ignore(struct Qdisc *q)
+{
+       return (q->flags & TCQ_F_BUILTIN) ? true : false;
+}
+
 static int qdisc_notify(struct sk_buff *oskb, struct nlmsghdr *n,
                        u32 clid, struct Qdisc *old, struct Qdisc *new)
 {
@@ -1206,11 +1211,11 @@ static int qdisc_notify(struct sk_buff *oskb, struct 
nlmsghdr *n,
        if (!skb)
                return -ENOBUFS;
 
-       if (old && old->handle) {
+       if (old && !tc_qdisc_dump_ignore(old)) {
                if (tc_fill_qdisc(skb, old, clid, pid, n->nlmsg_seq, 0, 
RTM_DELQDISC) < 0)
                        goto err_out;
        }
-       if (new) {
+       if (new && !tc_qdisc_dump_ignore(new)) {
                if (tc_fill_qdisc(skb, new, clid, pid, n->nlmsg_seq, old ? 
NLM_F_REPLACE : 0, RTM_NEWQDISC) < 0)
                        goto err_out;
        }
@@ -1223,11 +1228,6 @@ err_out:
        return -EINVAL;
 }
 
-static bool tc_qdisc_dump_ignore(struct Qdisc *q)
-{
-       return (q->flags & TCQ_F_BUILTIN) ? true : false;
-}
-
 static int tc_dump_qdisc_root(struct Qdisc *root, struct sk_buff *skb,
                              struct netlink_callback *cb,
                              int *q_idx_p, int s_q_idx)
-- 
1.7.12.rc2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to