[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>
This commit is contained in:
parent
33d36bb83c
commit
2994c63863
5 changed files with 62 additions and 64 deletions
|
@ -107,4 +107,7 @@ extern int fib_rules_unregister(struct fib_rules_ops *);
|
||||||
extern int fib_rules_lookup(struct fib_rules_ops *,
|
extern int fib_rules_lookup(struct fib_rules_ops *,
|
||||||
struct flowi *, int flags,
|
struct flowi *, int flags,
|
||||||
struct fib_lookup_arg *);
|
struct fib_lookup_arg *);
|
||||||
|
extern int fib_default_rule_add(struct fib_rules_ops *,
|
||||||
|
u32 pref, u32 table,
|
||||||
|
u32 flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,6 +18,28 @@
|
||||||
static LIST_HEAD(rules_ops);
|
static LIST_HEAD(rules_ops);
|
||||||
static DEFINE_SPINLOCK(rules_mod_lock);
|
static DEFINE_SPINLOCK(rules_mod_lock);
|
||||||
|
|
||||||
|
int fib_default_rule_add(struct fib_rules_ops *ops,
|
||||||
|
u32 pref, u32 table, u32 flags)
|
||||||
|
{
|
||||||
|
struct fib_rule *r;
|
||||||
|
|
||||||
|
r = kzalloc(ops->rule_size, GFP_KERNEL);
|
||||||
|
if (r == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
atomic_set(&r->refcnt, 1);
|
||||||
|
r->action = FR_ACT_TO_TBL;
|
||||||
|
r->pref = pref;
|
||||||
|
r->table = table;
|
||||||
|
r->flags = flags;
|
||||||
|
|
||||||
|
/* The lock is not required here, the list in unreacheable
|
||||||
|
* at the moment this function is called */
|
||||||
|
list_add_tail(&r->list, &ops->rules_list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(fib_default_rule_add);
|
||||||
|
|
||||||
static void notify_rule_change(int event, struct fib_rule *rule,
|
static void notify_rule_change(int event, struct fib_rule *rule,
|
||||||
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
|
struct fib_rules_ops *ops, struct nlmsghdr *nlh,
|
||||||
u32 pid);
|
u32 pid);
|
||||||
|
|
|
@ -48,15 +48,6 @@ struct dn_fib_rule
|
||||||
u8 flags;
|
u8 flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct dn_fib_rule default_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.pref = 0x7fff,
|
|
||||||
.table = RT_TABLE_MAIN,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
|
int dn_fib_lookup(struct flowi *flp, struct dn_fib_res *res)
|
||||||
{
|
{
|
||||||
|
@ -262,8 +253,8 @@ static struct fib_rules_ops dn_fib_rules_ops = {
|
||||||
|
|
||||||
void __init dn_fib_rules_init(void)
|
void __init dn_fib_rules_init(void)
|
||||||
{
|
{
|
||||||
list_add_tail(&default_rule.common.list,
|
BUG_ON(fib_default_rule_add(&dn_fib_rules_ops, 0x7fff,
|
||||||
&dn_fib_rules_ops.rules_list);
|
RT_TABLE_MAIN, 0));
|
||||||
fib_rules_register(&dn_fib_rules_ops);
|
fib_rules_register(&dn_fib_rules_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,33 +49,6 @@ struct fib4_rule
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct fib4_rule default_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.pref = 0x7FFF,
|
|
||||||
.table = RT_TABLE_DEFAULT,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct fib4_rule main_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.pref = 0x7FFE,
|
|
||||||
.table = RT_TABLE_MAIN,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct fib4_rule local_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.table = RT_TABLE_LOCAL,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
.flags = FIB_RULE_PERMANENT,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef CONFIG_NET_CLS_ROUTE
|
#ifdef CONFIG_NET_CLS_ROUTE
|
||||||
u32 fib_rules_tclass(struct fib_result *res)
|
u32 fib_rules_tclass(struct fib_result *res)
|
||||||
{
|
{
|
||||||
|
@ -319,11 +292,27 @@ static struct fib_rules_ops fib4_rules_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int __init fib_default_rules_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fib_default_rule_add(&fib4_rules_ops, 0,
|
||||||
|
RT_TABLE_LOCAL, FIB_RULE_PERMANENT);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = fib_default_rule_add(&fib4_rules_ops, 0x7FFE,
|
||||||
|
RT_TABLE_MAIN, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = fib_default_rule_add(&fib4_rules_ops, 0x7FFF,
|
||||||
|
RT_TABLE_DEFAULT, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void __init fib4_rules_init(void)
|
void __init fib4_rules_init(void)
|
||||||
{
|
{
|
||||||
list_add_tail(&local_rule.common.list, &fib4_rules_ops.rules_list);
|
BUG_ON(fib_default_rules_init());
|
||||||
list_add_tail(&main_rule.common.list, &fib4_rules_ops.rules_list);
|
|
||||||
list_add_tail(&default_rule.common.list, &fib4_rules_ops.rules_list);
|
|
||||||
|
|
||||||
fib_rules_register(&fib4_rules_ops);
|
fib_rules_register(&fib4_rules_ops);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,25 +31,6 @@ struct fib6_rule
|
||||||
|
|
||||||
static struct fib_rules_ops fib6_rules_ops;
|
static struct fib_rules_ops fib6_rules_ops;
|
||||||
|
|
||||||
static struct fib6_rule main_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.pref = 0x7FFE,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
.table = RT6_TABLE_MAIN,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct fib6_rule local_rule = {
|
|
||||||
.common = {
|
|
||||||
.refcnt = ATOMIC_INIT(2),
|
|
||||||
.pref = 0,
|
|
||||||
.action = FR_ACT_TO_TBL,
|
|
||||||
.table = RT6_TABLE_LOCAL,
|
|
||||||
.flags = FIB_RULE_PERMANENT,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
|
struct dst_entry *fib6_rule_lookup(struct flowi *fl, int flags,
|
||||||
pol_lookup_t lookup)
|
pol_lookup_t lookup)
|
||||||
{
|
{
|
||||||
|
@ -270,11 +251,23 @@ static struct fib_rules_ops fib6_rules_ops = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int __init fib6_default_rules_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = fib_default_rule_add(&fib6_rules_ops, 0,
|
||||||
|
RT6_TABLE_LOCAL, FIB_RULE_PERMANENT);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
err = fib_default_rule_add(&fib6_rules_ops, 0x7FFE, RT6_TABLE_MAIN, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void __init fib6_rules_init(void)
|
void __init fib6_rules_init(void)
|
||||||
{
|
{
|
||||||
list_add_tail(&local_rule.common.list, &fib6_rules_ops.rules_list);
|
BUG_ON(fib6_default_rules_init());
|
||||||
list_add_tail(&main_rule.common.list, &fib6_rules_ops.rules_list);
|
|
||||||
|
|
||||||
fib_rules_register(&fib6_rules_ops);
|
fib_rules_register(&fib6_rules_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue