Showing error 797

User: Jiri Slaby
Error type: Memory Leak
Error type description: There the code omits to free some allocated memory
File location: net/sched/act_police.c
Line in file: 171
Project: Linux Kernel
Project version: 2.6.28
Tools: Stanse (1.2)
Entered: 2011-11-07 22:26:27 UTC


Source:

  1/*
  2 * net/sched/police.c        Input police filter.
  3 *
  4 *                This program is free software; you can redistribute it and/or
  5 *                modify it under the terms of the GNU General Public License
  6 *                as published by the Free Software Foundation; either version
  7 *                2 of the License, or (at your option) any later version.
  8 *
  9 * Authors:        Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
 10 *                 J Hadi Salim (action changes)
 11 */
 12
 13#include <linux/module.h>
 14#include <linux/types.h>
 15#include <linux/kernel.h>
 16#include <linux/string.h>
 17#include <linux/errno.h>
 18#include <linux/skbuff.h>
 19#include <linux/rtnetlink.h>
 20#include <linux/init.h>
 21#include <net/act_api.h>
 22#include <net/netlink.h>
 23
 24#define L2T(p,L)   qdisc_l2t((p)->tcfp_R_tab, L)
 25#define L2T_P(p,L) qdisc_l2t((p)->tcfp_P_tab, L)
 26
 27#define POL_TAB_MASK     15
 28static struct tcf_common *tcf_police_ht[POL_TAB_MASK + 1];
 29static u32 police_idx_gen;
 30static DEFINE_RWLOCK(police_lock);
 31
 32static struct tcf_hashinfo police_hash_info = {
 33        .htab        =        tcf_police_ht,
 34        .hmask        =        POL_TAB_MASK,
 35        .lock        =        &police_lock,
 36};
 37
 38/* old policer structure from before tc actions */
 39struct tc_police_compat
 40{
 41        u32                        index;
 42        int                        action;
 43        u32                        limit;
 44        u32                        burst;
 45        u32                        mtu;
 46        struct tc_ratespec        rate;
 47        struct tc_ratespec        peakrate;
 48};
 49
 50/* Each policer is serialized by its individual spinlock */
 51
 52static int tcf_act_police_walker(struct sk_buff *skb, struct netlink_callback *cb,
 53                              int type, struct tc_action *a)
 54{
 55        struct tcf_common *p;
 56        int err = 0, index = -1, i = 0, s_i = 0, n_i = 0;
 57        struct nlattr *nest;
 58
 59        read_lock_bh(&police_lock);
 60
 61        s_i = cb->args[0];
 62
 63        for (i = 0; i < (POL_TAB_MASK + 1); i++) {
 64                p = tcf_police_ht[tcf_hash(i, POL_TAB_MASK)];
 65
 66                for (; p; p = p->tcfc_next) {
 67                        index++;
 68                        if (index < s_i)
 69                                continue;
 70                        a->priv = p;
 71                        a->order = index;
 72                        nest = nla_nest_start(skb, a->order);
 73                        if (nest == NULL)
 74                                goto nla_put_failure;
 75                        if (type == RTM_DELACTION)
 76                                err = tcf_action_dump_1(skb, a, 0, 1);
 77                        else
 78                                err = tcf_action_dump_1(skb, a, 0, 0);
 79                        if (err < 0) {
 80                                index--;
 81                                nla_nest_cancel(skb, nest);
 82                                goto done;
 83                        }
 84                        nla_nest_end(skb, nest);
 85                        n_i++;
 86                }
 87        }
 88done:
 89        read_unlock_bh(&police_lock);
 90        if (n_i)
 91                cb->args[0] += n_i;
 92        return n_i;
 93
 94nla_put_failure:
 95        nla_nest_cancel(skb, nest);
 96        goto done;
 97}
 98
 99static void tcf_police_destroy(struct tcf_police *p)
100{
101        unsigned int h = tcf_hash(p->tcf_index, POL_TAB_MASK);
102        struct tcf_common **p1p;
103
104        for (p1p = &tcf_police_ht[h]; *p1p; p1p = &(*p1p)->tcfc_next) {
105                if (*p1p == &p->common) {
106                        write_lock_bh(&police_lock);
107                        *p1p = p->tcf_next;
108                        write_unlock_bh(&police_lock);
109                        gen_kill_estimator(&p->tcf_bstats,
110                                           &p->tcf_rate_est);
111                        if (p->tcfp_R_tab)
112                                qdisc_put_rtab(p->tcfp_R_tab);
113                        if (p->tcfp_P_tab)
114                                qdisc_put_rtab(p->tcfp_P_tab);
115                        kfree(p);
116                        return;
117                }
118        }
119        WARN_ON(1);
120}
121
122static const struct nla_policy police_policy[TCA_POLICE_MAX + 1] = {
123        [TCA_POLICE_RATE]        = { .len = TC_RTAB_SIZE },
124        [TCA_POLICE_PEAKRATE]        = { .len = TC_RTAB_SIZE },
125        [TCA_POLICE_AVRATE]        = { .type = NLA_U32 },
126        [TCA_POLICE_RESULT]        = { .type = NLA_U32 },
127};
128
129static int tcf_act_police_locate(struct nlattr *nla, struct nlattr *est,
130                                 struct tc_action *a, int ovr, int bind)
131{
132        unsigned h;
133        int ret = 0, err;
134        struct nlattr *tb[TCA_POLICE_MAX + 1];
135        struct tc_police *parm;
136        struct tcf_police *police;
137        struct qdisc_rate_table *R_tab = NULL, *P_tab = NULL;
138        int size;
139
140        if (nla == NULL)
141                return -EINVAL;
142
143        err = nla_parse_nested(tb, TCA_POLICE_MAX, nla, police_policy);
144        if (err < 0)
145                return err;
146
147        if (tb[TCA_POLICE_TBF] == NULL)
148                return -EINVAL;
149        size = nla_len(tb[TCA_POLICE_TBF]);
150        if (size != sizeof(*parm) && size != sizeof(struct tc_police_compat))
151                return -EINVAL;
152        parm = nla_data(tb[TCA_POLICE_TBF]);
153
154        if (parm->index) {
155                struct tcf_common *pc;
156
157                pc = tcf_hash_lookup(parm->index, &police_hash_info);
158                if (pc != NULL) {
159                        a->priv = pc;
160                        police = to_police(pc);
161                        if (bind) {
162                                police->tcf_bindcnt += 1;
163                                police->tcf_refcnt += 1;
164                        }
165                        if (ovr)
166                                goto override;
167                        return ret;
168                }
169        }
170
171        police = kzalloc(sizeof(*police), GFP_KERNEL);
172        if (police == NULL)
173                return -ENOMEM;
174        ret = ACT_P_CREATED;
175        police->tcf_refcnt = 1;
176        spin_lock_init(&police->tcf_lock);
177        if (bind)
178                police->tcf_bindcnt = 1;
179override:
180        if (parm->rate.rate) {
181                err = -ENOMEM;
182                R_tab = qdisc_get_rtab(&parm->rate, tb[TCA_POLICE_RATE]);
183                if (R_tab == NULL)
184                        goto failure;
185                if (parm->peakrate.rate) {
186                        P_tab = qdisc_get_rtab(&parm->peakrate,
187                                               tb[TCA_POLICE_PEAKRATE]);
188                        if (P_tab == NULL) {
189                                qdisc_put_rtab(R_tab);
190                                goto failure;
191                        }
192                }
193        }
194        /* No failure allowed after this point */
195        spin_lock_bh(&police->tcf_lock);
196        if (R_tab != NULL) {
197                qdisc_put_rtab(police->tcfp_R_tab);
198                police->tcfp_R_tab = R_tab;
199        }
200        if (P_tab != NULL) {
201                qdisc_put_rtab(police->tcfp_P_tab);
202                police->tcfp_P_tab = P_tab;
203        }
204
205        if (tb[TCA_POLICE_RESULT])
206                police->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
207        police->tcfp_toks = police->tcfp_burst = parm->burst;
208        police->tcfp_mtu = parm->mtu;
209        if (police->tcfp_mtu == 0) {
210                police->tcfp_mtu = ~0;
211                if (police->tcfp_R_tab)
212                        police->tcfp_mtu = 255<<police->tcfp_R_tab->rate.cell_log;
213        }
214        if (police->tcfp_P_tab)
215                police->tcfp_ptoks = L2T_P(police, police->tcfp_mtu);
216        police->tcf_action = parm->action;
217
218        if (tb[TCA_POLICE_AVRATE])
219                police->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
220        if (est)
221                gen_replace_estimator(&police->tcf_bstats,
222                                      &police->tcf_rate_est,
223                                      &police->tcf_lock, est);
224
225        spin_unlock_bh(&police->tcf_lock);
226        if (ret != ACT_P_CREATED)
227                return ret;
228
229        police->tcfp_t_c = psched_get_time();
230        police->tcf_index = parm->index ? parm->index :
231                tcf_hash_new_index(&police_idx_gen, &police_hash_info);
232        h = tcf_hash(police->tcf_index, POL_TAB_MASK);
233        write_lock_bh(&police_lock);
234        police->tcf_next = tcf_police_ht[h];
235        tcf_police_ht[h] = &police->common;
236        write_unlock_bh(&police_lock);
237
238        a->priv = police;
239        return ret;
240
241failure:
242        if (ret == ACT_P_CREATED)
243                kfree(police);
244        return err;
245}
246
247static int tcf_act_police_cleanup(struct tc_action *a, int bind)
248{
249        struct tcf_police *p = a->priv;
250        int ret = 0;
251
252        if (p != NULL) {
253                if (bind)
254                        p->tcf_bindcnt--;
255
256                p->tcf_refcnt--;
257                if (p->tcf_refcnt <= 0 && !p->tcf_bindcnt) {
258                        tcf_police_destroy(p);
259                        ret = 1;
260                }
261        }
262        return ret;
263}
264
265static int tcf_act_police(struct sk_buff *skb, struct tc_action *a,
266                          struct tcf_result *res)
267{
268        struct tcf_police *police = a->priv;
269        psched_time_t now;
270        long toks;
271        long ptoks = 0;
272
273        spin_lock(&police->tcf_lock);
274
275        police->tcf_bstats.bytes += qdisc_pkt_len(skb);
276        police->tcf_bstats.packets++;
277
278        if (police->tcfp_ewma_rate &&
279            police->tcf_rate_est.bps >= police->tcfp_ewma_rate) {
280                police->tcf_qstats.overlimits++;
281                spin_unlock(&police->tcf_lock);
282                return police->tcf_action;
283        }
284
285        if (qdisc_pkt_len(skb) <= police->tcfp_mtu) {
286                if (police->tcfp_R_tab == NULL) {
287                        spin_unlock(&police->tcf_lock);
288                        return police->tcfp_result;
289                }
290
291                now = psched_get_time();
292                toks = psched_tdiff_bounded(now, police->tcfp_t_c,
293                                            police->tcfp_burst);
294                if (police->tcfp_P_tab) {
295                        ptoks = toks + police->tcfp_ptoks;
296                        if (ptoks > (long)L2T_P(police, police->tcfp_mtu))
297                                ptoks = (long)L2T_P(police, police->tcfp_mtu);
298                        ptoks -= L2T_P(police, qdisc_pkt_len(skb));
299                }
300                toks += police->tcfp_toks;
301                if (toks > (long)police->tcfp_burst)
302                        toks = police->tcfp_burst;
303                toks -= L2T(police, qdisc_pkt_len(skb));
304                if ((toks|ptoks) >= 0) {
305                        police->tcfp_t_c = now;
306                        police->tcfp_toks = toks;
307                        police->tcfp_ptoks = ptoks;
308                        spin_unlock(&police->tcf_lock);
309                        return police->tcfp_result;
310                }
311        }
312
313        police->tcf_qstats.overlimits++;
314        spin_unlock(&police->tcf_lock);
315        return police->tcf_action;
316}
317
318static int
319tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
320{
321        unsigned char *b = skb_tail_pointer(skb);
322        struct tcf_police *police = a->priv;
323        struct tc_police opt;
324
325        opt.index = police->tcf_index;
326        opt.action = police->tcf_action;
327        opt.mtu = police->tcfp_mtu;
328        opt.burst = police->tcfp_burst;
329        opt.refcnt = police->tcf_refcnt - ref;
330        opt.bindcnt = police->tcf_bindcnt - bind;
331        if (police->tcfp_R_tab)
332                opt.rate = police->tcfp_R_tab->rate;
333        else
334                memset(&opt.rate, 0, sizeof(opt.rate));
335        if (police->tcfp_P_tab)
336                opt.peakrate = police->tcfp_P_tab->rate;
337        else
338                memset(&opt.peakrate, 0, sizeof(opt.peakrate));
339        NLA_PUT(skb, TCA_POLICE_TBF, sizeof(opt), &opt);
340        if (police->tcfp_result)
341                NLA_PUT_U32(skb, TCA_POLICE_RESULT, police->tcfp_result);
342        if (police->tcfp_ewma_rate)
343                NLA_PUT_U32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate);
344        return skb->len;
345
346nla_put_failure:
347        nlmsg_trim(skb, b);
348        return -1;
349}
350
351MODULE_AUTHOR("Alexey Kuznetsov");
352MODULE_DESCRIPTION("Policing actions");
353MODULE_LICENSE("GPL");
354
355static struct tc_action_ops act_police_ops = {
356        .kind                =        "police",
357        .hinfo                =        &police_hash_info,
358        .type                =        TCA_ID_POLICE,
359        .capab                =        TCA_CAP_NONE,
360        .owner                =        THIS_MODULE,
361        .act                =        tcf_act_police,
362        .dump                =        tcf_act_police_dump,
363        .cleanup        =        tcf_act_police_cleanup,
364        .lookup                =        tcf_hash_search,
365        .init                =        tcf_act_police_locate,
366        .walk                =        tcf_act_police_walker
367};
368
369static int __init
370police_init_module(void)
371{
372        return tcf_register_action(&act_police_ops);
373}
374
375static void __exit
376police_cleanup_module(void)
377{
378        tcf_unregister_action(&act_police_ops);
379}
380
381module_init(police_init_module);
382module_exit(police_cleanup_module);