aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis V. Lunev <den@openvz.org>2007-11-11 01:12:03 -0500
committerDavid S. Miller <davem@davemloft.net>2007-11-11 01:12:03 -0500
commit2994c63863ac350c4c8c6a65d8110749c2abb95c (patch)
tree5509f71222641098683df1b1e0ff7bdfc2758b2c
parent33d36bb83c5b566c98a441e791736e25dbc35fc3 (diff)
[INET]: Small possible memory leak in FIB rules
This patch fixes a small memory leak. Default fib rules can be deleted by the user if the rule does not carry FIB_RULE_PERMANENT flag, f.e. by ip rule flush Such a rule will not be freed as the ref-counter has 2 on start and becomes clearly unreachable after removal. Signed-off-by: Denis V. Lunev <den@openvz.org> Acked-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/fib_rules.h3
-rw-r--r--net/core/fib_rules.c22
-rw-r--r--net/decnet/dn_rules.c13
-rw-r--r--net/ipv4/fib_rules.c51
-rw-r--r--net/ipv6/fib6_rules.c37
5 files changed, 62 insertions, 64 deletions
diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h
index 017aebd90683..41a301e38643 100644
--- a/include/net/fib_rules.h
+++ b/include/net/fib_rules.h
@@ -107,4 +107,7 @@ extern int fib_rules_unregister(struct fib_rules_ops *);
107extern int fib_rules_lookup(struct fib_rules_ops *, 107extern int fib_rules_lookup(struct fib_rules_ops *,
108 struct flowi *, int flags, 108 struct flowi *, int flags,
109 struct fib_lookup_arg *); 109 struct fib_lookup_arg *);
110extern int fib_default_rule_add(struct fib_rules_ops *,
111 u32 pref, u32 table,
112 u32 flags);
110#endif 113#endif
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 13de6f53f098..848132b6cb73 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -18,6 +18,28 @@
18static LIST_HEAD(rules_ops); 18static LIST_HEAD(rules_ops);
19static DEFINE_SPINLOCK(rules_mod_lock); 19static DEFINE_SPINLOCK(rules_mod_lock);
20 20
21int fib_default_rule_add(struct fib_rules_ops *ops,
22 u32 pref, u32 table, u32 flags)
23{
24 struct fib_rule *r;
25
26 r = kzalloc(ops->rule_size, GFP_KERNEL);
27 if (r == NULL)
28 return -ENOMEM;
29
30 atomic_set(&r->refcnt, 1);
31 r->action = FR_ACT_TO_TBL;
32 r->pref = pref;
33 r->table = table;
34 r->flags = flags;
35
36 /* The lock is not required here, the list in unreacheable
37 * at the moment this function is called */
38 list_add_tail(&r->list, &ops->rules_list);
39 return 0;
40}
41EXPORT_SYMBOL(fib_default_rule_add);
42
21static void notify_rule_change(int event, struct fib_rule *rule, 43static void notify_rule_change(int event, struct fib_rule *rule,
22 struct fib_rules_ops *ops, struct nlmsghdr *nlh, 44 struct fib_rules_ops *ops, struct nlmsghdr *nlh,
23 u32 pid); 45 u32 pid);
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index ddd3f04f0919..ffebea04cc99 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -48,15 +48,6 @@ struct dn_fib_rule
48 u8 flags; 48 u8 flags;
49}; 49};
50 50
51static struct dn_fib_rule default_rule = {
52 .common = {
53 .refcnt = ATOMIC_INIT(2),
54 .pref = 0x7fff,
55 .table = RT_TABLE_MAIN,
56 .action = FR_ACT_TO_TBL,
57 },
58};
59
60 51
61int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res) 52int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
62{ 53{
@@ -262,8 +253,8 @@ static struct fib_rules_ops dn_fib_rules_ops = {
262 253
263void __init dn_fib_rules_init(void) 254void __init dn_fib_rules_init(void)
264{ 255{
265 list_add_tail(&default_rule.common.list, 256 BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff,
266 &dn_fib_rules_ops.rules_list); 257 RT_TABLE_MAIN, 0));
267 fib_rules_register(&dn_fib_rules_ops); 258 fib_rules_register(&dn_fib_rules_ops);
268} 259}
269 260
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index f16839c6a721..a0ada3a8d8dd 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -49,33 +49,6 @@ struct fib4_rule
49#endif 49#endif
50}; 50};
51 51
52static struct fib4_rule default_rule = {
53 .common = {
54 .refcnt = ATOMIC_INIT(2),
55 .pref = 0x7FFF,
56 .table = RT_TABLE_DEFAULT,
57 .action = FR_ACT_TO_TBL,
58 },
59};
60
61static struct fib4_rule main_rule = {
62 .common = {
63 .refcnt = ATOMIC_INIT(2),
64 .pref = 0x7FFE,
65 .table = RT_TABLE_MAIN,
66 .action = FR_ACT_TO_TBL,
67 },
68};
69
70static struct fib4_rule local_rule = {
71 .common = {
72 .refcnt = ATOMIC_INIT(2),
73 .table = RT_TABLE_LOCAL,
74 .action = FR_ACT_TO_TBL,
75 .flags = FIB_RULE_PERMANENT,
76 },
77};
78
79#ifdef CONFIG_NET_CLS_ROUTE 52#ifdef CONFIG_NET_CLS_ROUTE
80u32 fib_rules_tclass(struct fib_result *res) 53u32 fib_rules_tclass(struct fib_result *res)
81{ 54{
@@ -319,11 +292,27 @@ static struct fib_rules_ops fib4_rules_ops = {
319 .owner = THIS_MODULE, 292 .owner = THIS_MODULE,
320}; 293};
321 294
322void __init fib4_rules_init(void) 295static int __init fib_default_rules_init(void)
323{ 296{
324 list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list); 297 int err;
325 list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list); 298
326 list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list); 299 err = fib_default_rule_add(&fib4_rules_ops, 0,
300 RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
301 if (err < 0)
302 return err;
303 err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE,
304 RT_TABLE_MAIN, 0);
305 if (err < 0)
306 return err;
307 err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF,
308 RT_TABLE_DEFAULT, 0);
309 if (err < 0)
310 return err;
311 return 0;
312}
327 313
314void __init fib4_rules_init(void)
315{
316 BUG_ON(fib_default_rules_init());
328 fib_rules_register(&fib4_rules_ops); 317 fib_rules_register(&fib4_rules_ops);
329} 318}
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 706622af206f..428c6b0e26d8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -31,25 +31,6 @@ struct fib6_rule
31 31
32static struct fib_rules_ops fib6_rules_ops; 32static struct fib_rules_ops fib6_rules_ops;
33 33
34static struct fib6_rule main_rule = {
35 .common = {
36 .refcnt = ATOMIC_INIT(2),
37 .pref = 0x7FFE,
38 .action = FR_ACT_TO_TBL,
39 .table = RT6_TABLE_MAIN,
40 },
41};
42
43static struct fib6_rule local_rule = {
44 .common = {
45 .refcnt = ATOMIC_INIT(2),
46 .pref = 0,
47 .action = FR_ACT_TO_TBL,
48 .table = RT6_TABLE_LOCAL,
49 .flags = FIB_RULE_PERMANENT,
50 },
51};
52
53struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, 34struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
54 pol_lookup_t lookup) 35 pol_lookup_t lookup)
55{ 36{
@@ -270,11 +251,23 @@ static struct fib_rules_ops fib6_rules_ops = {
270 .owner = THIS_MODULE, 251 .owner = THIS_MODULE,
271}; 252};
272 253
273void __init fib6_rules_init(void) 254static int __init fib6_default_rules_init(void)
274{ 255{
275 list_add_tail(&local_rule.common.list, &fib6_rules_ops.rules_list); 256 int err;
276 list_add_tail(&main_rule.common.list, &fib6_rules_ops.rules_list); 257
258 err = fib_default_rule_add(&fib6_rules_ops, 0,
259 RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
260 if (err < 0)
261 return err;
262 err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
263 if (err < 0)
264 return err;
265 return 0;
266}
277 267
268void __init fib6_rules_init(void)
269{
270 BUG_ON(fib6_default_rules_init());
278 fib_rules_register(&fib6_rules_ops); 271 fib_rules_register(&fib6_rules_ops);
279} 272}
280 273