From 268bcca1e7b0d244afd07ea89cda672e61b0fc4a Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 9 Feb 2008 03:47:19 -0800 Subject: [PKT_SCHED] ematch: oops from uninitialized variable (resend) Setting up a meta match causes a kernel OOPS because of uninitialized elements in tree. [ 37.322381] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 [ 37.322381] IP: [] :em_meta:em_meta_destroy+0x17/0x80 [ 37.322381] Call Trace: [ 37.322381] [] tcf_em_tree_destroy+0x2d/0xa0 [ 37.322381] [] tcf_em_tree_validate+0x2dc/0x4a0 [ 37.322381] [] nla_parse+0x92/0xe0 [ 37.322381] [] :cls_basic:basic_change+0x202/0x3c0 [ 37.322381] [] kmem_cache_alloc+0x67/0xa0 [ 37.322381] [] tc_ctl_tfilter+0x3b1/0x580 [ 37.322381] [] rtnetlink_rcv_msg+0x0/0x260 [ 37.322381] [] netlink_rcv_skb+0x74/0xa0 [ 37.322381] [] rtnetlink_rcv+0x18/0x20 [ 37.322381] [] netlink_unicast+0x263/0x290 [ 37.322381] [] __alloc_skb+0x96/0x160 [ 37.322381] [] netlink_sendmsg+0x274/0x340 [ 37.322381] [] sock_sendmsg+0x12b/0x140 [ 37.322381] [] autoremove_wake_function+0x0/0x30 [ 37.322381] [] autoremove_wake_function+0x0/0x30 [ 37.322381] [] sock_sendmsg+0x12b/0x140 [ 37.322381] [] zone_statistics+0xb1/0xc0 [ 37.322381] [] sys_sendmsg+0x20e/0x360 [ 37.322381] [] sockfd_lookup_light+0x41/0x80 [ 37.322381] [] handle_mm_fault+0x3eb/0x7f0 [ 37.322381] [] system_call_after_swapgs+0x7b/0x80 Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/ematch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'net/sched') diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 74ff918..d421ec7 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -312,10 +312,9 @@ int tcf_em_tree_validate(struct tcf_proto *tp, struct nlattr *nla, struct tcf_ematch_tree_hdr *tree_hdr; struct tcf_ematch *em; - if (!nla) { - memset(tree, 0, sizeof(*tree)); + memset(tree, 0, sizeof(*tree)); + if (!nla) return 0; - } err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, nla, em_policy); if (err < 0) -- cgit v1.1 From ed7af3b3501c8c4e3667c89c2c43347bf29ae237 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 9 Feb 2008 23:26:17 -0800 Subject: [PKT_SCHED]: deinline functions in meta match A couple of functions in meta match don't need to be inline. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/em_meta.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/sched') diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index d417ec8..3da4129 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c @@ -687,8 +687,8 @@ static inline struct meta_type_ops * meta_type_ops(struct meta_value *v) * Core **************************************************************************/ -static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, - struct meta_value *v, struct meta_obj *dst) +static int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, + struct meta_value *v, struct meta_obj *dst) { int err = 0; @@ -733,7 +733,7 @@ static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m, return 0; } -static inline void meta_delete(struct meta_match *meta) +static void meta_delete(struct meta_match *meta) { if (meta) { struct meta_type_ops *ops = meta_type_ops(&meta->lvalue); -- cgit v1.1 From 954415e33ed6cfa932c13e8c2460bd05e50723b5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sat, 9 Feb 2008 23:26:53 -0800 Subject: [PKT_SCHED] ematch: tcf_em_destroy robustness Make the code in tcf_em_tree_destroy more robust and cleaner: * Don't need to cast pointer to kfree() or avoid passing NULL. * After freeing the tree, clear the pointer to avoid possible problems from repeated free. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/sched/ematch.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/sched') diff --git a/net/sched/ematch.c b/net/sched/ematch.c index d421ec7..b29439d 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c @@ -409,14 +409,15 @@ void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree) if (em->ops) { if (em->ops->destroy) em->ops->destroy(tp, em); - else if (!tcf_em_is_simple(em) && em->data) - kfree((void *) em->data); + else if (!tcf_em_is_simple(em)) + kfree(em->data); module_put(em->ops->owner); } } tree->hdr.nmatches = 0; kfree(tree->matches); + tree->matches = NULL; } EXPORT_SYMBOL(tcf_em_tree_destroy); -- cgit v1.1 From 21347456abfbf5bc7fcace7327476736bbb28abe Mon Sep 17 00:00:00 2001 From: Jarek Poplawski Date: Sat, 9 Feb 2008 23:44:00 -0800 Subject: [NET_SCHED] sch_htb: htb_requeue fix htb_requeue() enqueues skbs for which htb_classify() returns NULL. This is wrong because such skbs could be handled by NET_CLS_ACT code, and the decision could be different than earlier in htb_enqueue(). So htb_requeue() is changed to work and look more like htb_enqueue(). Signed-off-by: Jarek Poplawski Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'net/sched') diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index e1a579ef..795c761 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -609,14 +609,14 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* TODO: requeuing packet charges it to policers again !! */ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) { + int ret; struct htb_sched *q = qdisc_priv(sch); - int ret = NET_XMIT_SUCCESS; struct htb_class *cl = htb_classify(skb, sch, &ret); struct sk_buff *tskb; - if (cl == HTB_DIRECT || !cl) { + if (cl == HTB_DIRECT) { /* enqueue to helper queue */ - if (q->direct_queue.qlen < q->direct_qlen && cl) { + if (q->direct_queue.qlen < q->direct_qlen) { __skb_queue_head(&q->direct_queue, skb); } else { __skb_queue_head(&q->direct_queue, skb); @@ -625,6 +625,13 @@ static int htb_requeue(struct sk_buff *skb, struct Qdisc *sch) sch->qstats.drops++; return NET_XMIT_CN; } +#ifdef CONFIG_NET_CLS_ACT + } else if (!cl) { + if (ret == NET_XMIT_BYPASS) + sch->qstats.drops++; + kfree_skb(skb); + return ret; +#endif } else if (cl->un.leaf.q->ops->requeue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) { sch->qstats.drops++; -- cgit v1.1