Skip to content

Commit e783bb0

Browse files
qsndavem330
authored andcommitted
ipmr: fix error path when ipmr_new_table fails
commit 0bbbf0e ("ipmr, ip6mr: Unite creation of new mr_table") refactored ipmr_new_table, so that it now returns NULL when mr_table_alloc fails. Unfortunately, all callers of ipmr_new_table expect an ERR_PTR. This can result in NULL deref, for example when ipmr_rules_exit calls ipmr_free_table with NULL net->ipv4.mrt in the !CONFIG_IP_MROUTE_MULTIPLE_TABLES version. This patch makes mr_table_alloc return errors, and changes ip6mr_new_table and its callers to return/expect error pointers as well. It also removes the version of mr_table_alloc defined under !CONFIG_IP_MROUTE_COMMON, since it is never used. Fixes: 0bbbf0e ("ipmr, ip6mr: Unite creation of new mr_table") Signed-off-by: Sabrina Dubroca <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 848235e commit e783bb0

File tree

3 files changed

+17
-19
lines changed

3 files changed

+17
-19
lines changed

include/linux/mroute_base.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -307,16 +307,6 @@ static inline void vif_device_init(struct vif_device *v,
307307
{
308308
}
309309

310-
static inline void *
311-
mr_table_alloc(struct net *net, u32 id,
312-
struct mr_table_ops *ops,
313-
void (*expire_func)(struct timer_list *t),
314-
void (*table_set)(struct mr_table *mrt,
315-
struct net *net))
316-
{
317-
return NULL;
318-
}
319-
320310
static inline void *mr_mfc_find_parent(struct mr_table *mrt,
321311
void *hasharg, int parent)
322312
{

net/ipv4/ipmr_base.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,19 @@ mr_table_alloc(struct net *net, u32 id,
3535
struct net *net))
3636
{
3737
struct mr_table *mrt;
38+
int err;
3839

3940
mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
4041
if (!mrt)
41-
return NULL;
42+
return ERR_PTR(-ENOMEM);
4243
mrt->id = id;
4344
write_pnet(&mrt->net, net);
4445

4546
mrt->ops = *ops;
46-
if (rhltable_init(&mrt->mfc_hash, mrt->ops.rht_params)) {
47+
err = rhltable_init(&mrt->mfc_hash, mrt->ops.rht_params);
48+
if (err) {
4749
kfree(mrt);
48-
return NULL;
50+
return ERR_PTR(err);
4951
}
5052
INIT_LIST_HEAD(&mrt->mfc_cache_list);
5153
INIT_LIST_HEAD(&mrt->mfc_unres_queue);

net/ipv6/ip6mr.c

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ static int __net_init ip6mr_rules_init(struct net *net)
228228
INIT_LIST_HEAD(&net->ipv6.mr6_tables);
229229

230230
mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
231-
if (!mrt) {
232-
err = -ENOMEM;
231+
if (IS_ERR(mrt)) {
232+
err = PTR_ERR(mrt);
233233
goto err1;
234234
}
235235

@@ -302,8 +302,13 @@ static int ip6mr_fib_lookup(struct net *net, struct flowi6 *flp6,
302302

303303
static int __net_init ip6mr_rules_init(struct net *net)
304304
{
305-
net->ipv6.mrt6 = ip6mr_new_table(net, RT6_TABLE_DFLT);
306-
return net->ipv6.mrt6 ? 0 : -ENOMEM;
305+
struct mr_table *mrt;
306+
307+
mrt = ip6mr_new_table(net, RT6_TABLE_DFLT);
308+
if (IS_ERR(mrt))
309+
return PTR_ERR(mrt);
310+
net->ipv6.mrt6 = mrt;
311+
return 0;
307312
}
308313

309314
static void __net_exit ip6mr_rules_exit(struct net *net)
@@ -1758,8 +1763,9 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
17581763

17591764
rtnl_lock();
17601765
ret = 0;
1761-
if (!ip6mr_new_table(net, v))
1762-
ret = -ENOMEM;
1766+
mrt = ip6mr_new_table(net, v);
1767+
if (IS_ERR(mrt))
1768+
ret = PTR_ERR(mrt);
17631769
else
17641770
raw6_sk(sk)->ip6mr_table = v;
17651771
rtnl_unlock();

0 commit comments

Comments
 (0)