Commit 1113ebbc authored by Nikolay Aleksandrov's avatar Nikolay Aleksandrov Committed by David S. Miller

net: ipmr: move the tbl id check in ipmr_new_table

Move the table id check in ipmr_new_table and make it return error
pointer. We need this change for the upcoming netlink table manipulation
support in order to avoid code duplication and a race condition.
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 930d3142
...@@ -252,8 +252,8 @@ static int __net_init ipmr_rules_init(struct net *net) ...@@ -252,8 +252,8 @@ static int __net_init ipmr_rules_init(struct net *net)
INIT_LIST_HEAD(&net->ipv4.mr_tables); INIT_LIST_HEAD(&net->ipv4.mr_tables);
mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
if (!mrt) { if (IS_ERR(mrt)) {
err = -ENOMEM; err = PTR_ERR(mrt);
goto err1; goto err1;
} }
...@@ -301,8 +301,13 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4, ...@@ -301,8 +301,13 @@ static int ipmr_fib_lookup(struct net *net, struct flowi4 *flp4,
static int __net_init ipmr_rules_init(struct net *net) static int __net_init ipmr_rules_init(struct net *net)
{ {
net->ipv4.mrt = ipmr_new_table(net, RT_TABLE_DEFAULT); struct mr_table *mrt;
return net->ipv4.mrt ? 0 : -ENOMEM;
mrt = ipmr_new_table(net, RT_TABLE_DEFAULT);
if (IS_ERR(mrt))
return PTR_ERR(mrt);
net->ipv4.mrt = mrt;
return 0;
} }
static void __net_exit ipmr_rules_exit(struct net *net) static void __net_exit ipmr_rules_exit(struct net *net)
...@@ -319,13 +324,17 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) ...@@ -319,13 +324,17 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
struct mr_table *mrt; struct mr_table *mrt;
unsigned int i; unsigned int i;
/* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
if (id != RT_TABLE_DEFAULT && id >= 1000000000)
return ERR_PTR(-EINVAL);
mrt = ipmr_get_table(net, id); mrt = ipmr_get_table(net, id);
if (mrt) if (mrt)
return mrt; return mrt;
mrt = kzalloc(sizeof(*mrt), GFP_KERNEL); mrt = kzalloc(sizeof(*mrt), GFP_KERNEL);
if (!mrt) if (!mrt)
return NULL; return ERR_PTR(-ENOMEM);
write_pnet(&mrt->net, net); write_pnet(&mrt->net, net);
mrt->id = id; mrt->id = id;
...@@ -1407,17 +1416,14 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi ...@@ -1407,17 +1416,14 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
if (get_user(v, (u32 __user *)optval)) if (get_user(v, (u32 __user *)optval))
return -EFAULT; return -EFAULT;
/* "pimreg%u" should not exceed 16 bytes (IFNAMSIZ) */
if (v != RT_TABLE_DEFAULT && v >= 1000000000)
return -EINVAL;
rtnl_lock(); rtnl_lock();
ret = 0; ret = 0;
if (sk == rtnl_dereference(mrt->mroute_sk)) { if (sk == rtnl_dereference(mrt->mroute_sk)) {
ret = -EBUSY; ret = -EBUSY;
} else { } else {
if (!ipmr_new_table(net, v)) mrt = ipmr_new_table(net, v);
ret = -ENOMEM; if (IS_ERR(mrt))
ret = PTR_ERR(mrt);
else else
raw_sk(sk)->ipmr_table = v; raw_sk(sk)->ipmr_table = v;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment