From: Patrick McHardy <kaber@trash.net>
To: "David S. Miller" <davem@davemloft.net>
Cc: Maillist netdev <netdev@oss.sgi.com>
Subject: [PATCH PKT_SCHED 4/4]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
Date: Wed, 19 Jan 2005 05:38:58 +0100 [thread overview]
Message-ID: <41EDE462.9040602@trash.net> (raw)
[-- Attachment #1: Type: text/plain, Size: 1 bytes --]
[-- Attachment #2: 04.diff --]
[-- Type: text/x-patch, Size: 12460 bytes --]
# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
# 2005/01/19 05:15:16+01:00 kaber@coreworks.de
# [PKT_SCHED]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
#
# Both HFSC and CBQ leak unclassified skbs with CONFIG_NET_CLS_ACT.
# Move freeing to enqueue where it belongs. Same change for in HTB/prio,
# they just don't leak because they don't have unclassified packets.
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/sched/sch_prio.c
# 2005/01/19 05:15:07+01:00 kaber@coreworks.de +30 -44
# [PKT_SCHED]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
#
# Both HFSC and CBQ leak unclassified skbs with CONFIG_NET_CLS_ACT.
# Move freeing to enqueue where it belongs. Same change for in HTB/prio,
# they just don't leak because they don't have unclassified packets.
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/sched/sch_htb.c
# 2005/01/19 05:15:07+01:00 kaber@coreworks.de +16 -44
# [PKT_SCHED]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
#
# Both HFSC and CBQ leak unclassified skbs with CONFIG_NET_CLS_ACT.
# Move freeing to enqueue where it belongs. Same change for in HTB/prio,
# they just don't leak because they don't have unclassified packets.
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/sched/sch_hfsc.c
# 2005/01/19 05:15:07+01:00 kaber@coreworks.de +11 -34
# [PKT_SCHED]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
#
# Both HFSC and CBQ leak unclassified skbs with CONFIG_NET_CLS_ACT.
# Move freeing to enqueue where it belongs. Same change for in HTB/prio,
# they just don't leak because they don't have unclassified packets.
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
# net/sched/sch_cbq.c
# 2005/01/19 05:15:07+01:00 kaber@coreworks.de +26 -53
# [PKT_SCHED]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ
#
# Both HFSC and CBQ leak unclassified skbs with CONFIG_NET_CLS_ACT.
# Move freeing to enqueue where it belongs. Same change for in HTB/prio,
# they just don't leak because they classify all packets.
#
# Signed-off-by: Patrick McHardy <kaber@trash.net>
#
diff -Nru a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c
--- a/net/sched/sch_cbq.c 2005-01-19 05:30:01 +01:00
+++ b/net/sched/sch_cbq.c 2005-01-19 05:30:01 +01:00
@@ -241,7 +241,7 @@
*/
static struct cbq_class *
-cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
+cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
{
struct cbq_sched_data *q = qdisc_priv(sch);
struct cbq_class *head = &q->link;
@@ -255,13 +255,11 @@
*/
if (TC_H_MAJ(prio^sch->handle) == 0 &&
(cl = cbq_class_lookup(q, prio)) != NULL)
- return cl;
+ return cl;
+ *qerr = NET_XMIT_DROP;
for (;;) {
int result = 0;
-#ifdef CONFIG_NET_CLS_ACT
- int terminal = 0;
-#endif
defmap = head->defaults;
/*
@@ -282,27 +280,13 @@
#ifdef CONFIG_NET_CLS_ACT
switch (result) {
- case TC_ACT_SHOT: /* Stop and kfree */
- *qres = NET_XMIT_DROP;
- terminal = 1;
- break;
case TC_ACT_QUEUED:
case TC_ACT_STOLEN:
- terminal = 1;
- break;
- case TC_ACT_RECLASSIFY: /* Things look good */
- case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
- break;
- }
-
- if (terminal) {
- kfree_skb(skb);
+ *qerr = NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
return NULL;
}
-#else
-#ifdef CONFIG_NET_CLS_POLICE
+#elif defined(CONFIG_NET_CLS_POLICE)
switch (result) {
case TC_POLICE_RECLASSIFY:
return cbq_reclassify(skb, cl);
@@ -312,7 +296,6 @@
break;
}
#endif
-#endif
if (cl->level == 0)
return cl;
@@ -423,45 +406,35 @@
{
struct cbq_sched_data *q = qdisc_priv(sch);
int len = skb->len;
- int ret = NET_XMIT_SUCCESS;
- struct cbq_class *cl = cbq_classify(skb, sch,&ret);
+ int ret;
+ struct cbq_class *cl = cbq_classify(skb, sch, &ret);
#ifdef CONFIG_NET_CLS_POLICE
q->rx_class = cl;
#endif
- if (cl) {
-#ifdef CONFIG_NET_CLS_POLICE
- cl->q->__parent = sch;
-#endif
- if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
- sch->q.qlen++;
- sch->bstats.packets++;
- sch->bstats.bytes+=len;
- cbq_mark_toplevel(q, cl);
- if (!cl->next_alive)
- cbq_activate_class(cl);
- return ret;
- }
- }
-
-#ifndef CONFIG_NET_CLS_ACT
- sch->qstats.drops++;
- if (cl == NULL)
+ if (cl == NULL) {
+ if (ret == NET_XMIT_DROP)
+ sch->qstats.drops++;
kfree_skb(skb);
- else {
- cbq_mark_toplevel(q, cl);
- cl->qstats.drops++;
- }
-#else
- if ( NET_XMIT_DROP == ret) {
- sch->qstats.drops++;
+ return ret;
}
- if (cl != NULL) {
+#ifdef CONFIG_NET_CLS_POLICE
+ cl->q->__parent = sch;
+#endif
+ if ((ret = cl->q->enqueue(skb, cl->q)) == NET_XMIT_SUCCESS) {
+ sch->q.qlen++;
+ sch->bstats.packets++;
+ sch->bstats.bytes+=len;
cbq_mark_toplevel(q, cl);
- cl->qstats.drops++;
+ if (!cl->next_alive)
+ cbq_activate_class(cl);
+ return ret;
}
-#endif
+
+ sch->qstats.drops++;
+ cbq_mark_toplevel(q, cl);
+ cl->qstats.drops++;
return ret;
}
diff -Nru a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c
--- a/net/sched/sch_hfsc.c 2005-01-19 05:30:01 +01:00
+++ b/net/sched/sch_hfsc.c 2005-01-19 05:30:01 +01:00
@@ -1214,7 +1214,7 @@
}
static struct hfsc_class *
-hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
+hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
{
struct hfsc_sched *q = qdisc_priv(sch);
struct hfsc_class *cl;
@@ -1227,36 +1227,21 @@
if (cl->level == 0)
return cl;
+ *qerr = NET_XMIT_DROP;
tcf = q->root.filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
- int terminal = 0;
switch (result) {
- case TC_ACT_SHOT:
- *qres = NET_XMIT_DROP;
- terminal = 1;
- break;
case TC_ACT_QUEUED:
case TC_ACT_STOLEN:
- terminal = 1;
- break;
- case TC_ACT_RECLASSIFY:
- case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
- break;
- }
-
- if (terminal) {
- kfree_skb(skb);
+ *qerr = NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
return NULL;
}
-#else
-#ifdef CONFIG_NET_CLS_POLICE
+#elif defined(CONFIG_NET_CLS_POLICE)
if (result == TC_POLICE_SHOT)
return NULL;
#endif
-#endif
if ((cl = (struct hfsc_class *)res.class) == NULL) {
if ((cl = hfsc_find_class(res.classid, sch)) == NULL)
break; /* filter selected invalid classid */
@@ -1652,27 +1637,19 @@
static int
hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- int ret = NET_XMIT_SUCCESS;
- struct hfsc_class *cl = hfsc_classify(skb, sch, &ret);
- unsigned int len = skb->len;
+ struct hfsc_class *cl;
+ unsigned int len;
int err;
-
-#ifdef CONFIG_NET_CLS_ACT
+ cl = hfsc_classify(skb, sch, &err);
if (cl == NULL) {
- if (NET_XMIT_DROP == ret) {
+ if (err == NET_XMIT_DROP)
sch->qstats.drops++;
- }
- return ret;
- }
-#else
- if (cl == NULL) {
kfree_skb(skb);
- sch->qstats.drops++;
- return NET_XMIT_DROP;
+ return err;
}
-#endif
+ len = skb->len;
err = cl->qdisc->enqueue(skb, cl->qdisc);
if (unlikely(err != NET_XMIT_SUCCESS)) {
cl->qstats.drops++;
diff -Nru a/net/sched/sch_htb.c b/net/sched/sch_htb.c
--- a/net/sched/sch_htb.c 2005-01-19 05:30:01 +01:00
+++ b/net/sched/sch_htb.c 2005-01-19 05:30:01 +01:00
@@ -305,7 +305,7 @@
return (cl && cl != HTB_DIRECT) ? cl->classid : TC_H_UNSPEC;
}
-static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qres)
+static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
{
struct htb_sched *q = qdisc_priv(sch);
struct htb_class *cl;
@@ -321,35 +321,20 @@
if ((cl = htb_find(skb->priority,sch)) != NULL && cl->level == 0)
return cl;
+ *qerr = NET_XMIT_DROP;
tcf = q->filter_list;
while (tcf && (result = tc_classify(skb, tcf, &res)) >= 0) {
#ifdef CONFIG_NET_CLS_ACT
- int terminal = 0;
switch (result) {
- case TC_ACT_SHOT: /* Stop and kfree */
- *qres = NET_XMIT_DROP;
- terminal = 1;
- break;
case TC_ACT_QUEUED:
case TC_ACT_STOLEN:
- terminal = 1;
- break;
- case TC_ACT_RECLASSIFY: /* Things look good */
- case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
- break;
- }
-
- if (terminal) {
- kfree_skb(skb);
+ *qerr = NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
return NULL;
}
-#else
-#ifdef CONFIG_NET_CLS_POLICE
+#elif defined(CONFIG_NET_CLS_POLICE)
if (result == TC_POLICE_SHOT)
- return NULL;
-#endif
+ return HTB_DIRECT;
#endif
if ((cl = (void*)res.class) == NULL) {
if (res.classid == sch->handle)
@@ -723,37 +708,24 @@
static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
- int ret = NET_XMIT_SUCCESS;
+ int ret;
struct htb_sched *q = qdisc_priv(sch);
struct htb_class *cl = htb_classify(skb,sch,&ret);
-
-#ifdef CONFIG_NET_CLS_ACT
- if (cl == HTB_DIRECT ) {
- if (q->direct_queue.qlen < q->direct_qlen ) {
- __skb_queue_tail(&q->direct_queue, skb);
- q->direct_pkts++;
- }
- } else if (!cl) {
- if (NET_XMIT_DROP == ret) {
- sch->qstats.drops++;
- }
- return ret;
- }
-#else
- 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_tail(&q->direct_queue, skb);
q->direct_pkts++;
- } else {
- kfree_skb (skb);
- sch->qstats.drops++;
- return NET_XMIT_DROP;
}
- }
+#ifdef CONFIG_NET_CLS_ACT
+ } else if (!cl) {
+ if (ret == NET_XMIT_DROP)
+ sch->qstats.drops++;
+ kfree_skb (skb);
+ return ret;
#endif
- else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
+ } else if (cl->un.leaf.q->enqueue(skb, cl->un.leaf.q) != NET_XMIT_SUCCESS) {
sch->qstats.drops++;
cl->qstats.drops++;
return NET_XMIT_DROP;
diff -Nru a/net/sched/sch_prio.c b/net/sched/sch_prio.c
--- a/net/sched/sch_prio.c 2005-01-19 05:30:01 +01:00
+++ b/net/sched/sch_prio.c 2005-01-19 05:30:01 +01:00
@@ -47,37 +47,23 @@
};
-static struct Qdisc *prio_classify(struct sk_buff *skb,
- struct Qdisc *sch, int *r)
+static struct Qdisc *
+prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
{
struct prio_sched_data *q = qdisc_priv(sch);
u32 band = skb->priority;
struct tcf_result res;
+ *qerr = NET_XMIT_DROP;
if (TC_H_MAJ(skb->priority) != sch->handle) {
#ifdef CONFIG_NET_CLS_ACT
- int result = 0, terminal = 0;
- result = tc_classify(skb, q->filter_list, &res);
-
- switch (result) {
- case TC_ACT_SHOT:
- *r = NET_XMIT_DROP;
- terminal = 1;
- break;
- case TC_ACT_STOLEN:
- case TC_ACT_QUEUED:
- terminal = 1;
- break;
- case TC_ACT_RECLASSIFY:
- case TC_ACT_OK:
- case TC_ACT_UNSPEC:
- default:
- break;
- };
- if (terminal) {
- kfree_skb(skb);
+ switch (tc_classify(skb, q->filter_list, &res)) {
+ case TC_ACT_STOLEN:
+ case TC_ACT_QUEUED:
+ *qerr = NET_XMIT_SUCCESS;
+ case TC_ACT_SHOT:
return NULL;
- }
+ };
if (!q->filter_list ) {
#else
@@ -97,15 +83,20 @@
}
static int
-prio_enqueue(struct sk_buff *skb, struct Qdisc* sch)
+prio_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct Qdisc *qdisc;
- int ret = NET_XMIT_SUCCESS;
+ int ret;
qdisc = prio_classify(skb, sch, &ret);
-
- if (NULL == qdisc)
- goto dropped;
+#ifdef CONFIG_NET_CLS_ACT
+ if (qdisc == NULL) {
+ if (ret == NET_XMIT_DROP)
+ sch->qstats.drops++;
+ kfree_skb(skb);
+ return ret;
+ }
+#endif
if ((ret = qdisc->enqueue(skb, qdisc)) == NET_XMIT_SUCCESS) {
sch->bstats.bytes += skb->len;
@@ -113,17 +104,7 @@
sch->q.qlen++;
return NET_XMIT_SUCCESS;
}
-
-dropped:
-#ifdef CONFIG_NET_CLS_ACT
- if (NET_XMIT_DROP == ret) {
-#endif
- sch->qstats.drops++;
-#ifdef CONFIG_NET_CLS_ACT
- } else {
- sch->qstats.overlimits++; /* abuse, but noone uses it */
- }
-#endif
+ sch->qstats.drops++;
return ret;
}
@@ -132,18 +113,23 @@
prio_requeue(struct sk_buff *skb, struct Qdisc* sch)
{
struct Qdisc *qdisc;
- int ret = NET_XMIT_DROP;
+ int ret;
qdisc = prio_classify(skb, sch, &ret);
- if (qdisc == NULL)
- goto dropped;
+#ifdef CONFIG_NET_CLS_ACT
+ if (qdisc == NULL) {
+ if (ret == NET_XMIT_DROP)
+ sch->qstats.drops++;
+ kfree_skb(skb);
+ return ret;
+ }
+#endif
- if ((ret = qdisc->ops->requeue(skb, qdisc)) == 0) {
+ if ((ret = qdisc->ops->requeue(skb, qdisc)) == NET_XMIT_SUCCESS) {
sch->q.qlen++;
sch->qstats.requeues++;
return 0;
}
-dropped:
sch->qstats.drops++;
return NET_XMIT_DROP;
}
next reply other threads:[~2005-01-19 4:38 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-01-19 4:38 Patrick McHardy [this message]
2005-01-19 13:26 ` [PATCH PKT_SCHED 4/4]: fix CONFIG_NET_CLS_ACT skb leaks in HFSC/CBQ jamal
2005-01-19 13:33 ` Patrick McHardy
2005-01-19 14:30 ` jamal
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=41EDE462.9040602@trash.net \
--to=kaber@trash.net \
--cc=davem@davemloft.net \
--cc=netdev@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).