diff options
| author | Denis V. Lunev <den@openvz.org> | 2007-11-11 01:12:03 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2007-11-11 01:12:03 -0500 |
| commit | 2994c63863ac350c4c8c6a65d8110749c2abb95c (patch) | |
| tree | 5509f71222641098683df1b1e0ff7bdfc2758b2c /net | |
| parent | 33d36bb83c5b566c98a441e791736e25dbc35fc3 (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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/fib_rules.c | 22 | ||||
| -rw-r--r-- | net/decnet/dn_rules.c | 13 | ||||
| -rw-r--r-- | net/ipv4/fib_rules.c | 51 | ||||
| -rw-r--r-- | net/ipv6/fib6_rules.c | 37 |
4 files changed, 59 insertions, 64 deletions
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 @@ | |||
| 18 | static LIST_HEAD(rules_ops); | 18 | static LIST_HEAD(rules_ops); |
| 19 | static DEFINE_SPINLOCK(rules_mod_lock); | 19 | static DEFINE_SPINLOCK(rules_mod_lock); |
| 20 | 20 | ||
| 21 | int 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 | } | ||
| 41 | EXPORT_SYMBOL(fib_default_rule_add); | ||
| 42 | |||
| 21 | static void notify_rule_change(int event, struct fib_rule *rule, | 43 | static 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 | ||
| 51 | static 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 | ||
| 61 | int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res) | 52 | int 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 | ||
| 263 | void __init dn_fib_rules_init(void) | 254 | void __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 | ||
| 52 | static 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 | |||
| 61 | static 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 | |||
| 70 | static 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 |
| 80 | u32 fib_rules_tclass(struct fib_result *res) | 53 | u32 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 | ||
| 322 | void __init fib4_rules_init(void) | 295 | static 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 | ||
| 314 | void __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 | ||
| 32 | static struct fib_rules_ops fib6_rules_ops; | 32 | static struct fib_rules_ops fib6_rules_ops; |
| 33 | 33 | ||
| 34 | static 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 | |||
| 43 | static 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 | |||
| 53 | struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags, | 34 | struct 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 | ||
| 273 | void __init fib6_rules_init(void) | 254 | static 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 | ||
| 268 | void __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 | ||
