aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/ipmr.c
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2012-11-25 01:41:45 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-25 16:34:16 -0500
commit5e1859fbcc3ccdd56d528df91d7b6f70e73d6b82 (patch)
treeefa1ce9061f7bcf8280159c9d2612221279766d3 /net/ipv4/ipmr.c
parent11e980299f922884377c7ce5d8c331327c5c3fd6 (diff)
ipv4: ipmr: various fixes and cleanups
1) ip_mroute_setsockopt() & ip_mroute_getsockopt() should not access/set raw_sk(sk)->ipmr_table before making sure the socket is a raw socket, and protocol is IGMP 2) MRT_INIT should return -EINVAL if optlen != sizeof(int), not -ENOPROTOOPT 3) MRT_ASSERT & MRT_PIM should validate optlen 4) " (v) ? 1 : 0 " can be written as " !!v " Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r--net/ipv4/ipmr.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index adf3d349566f..0394a8e6d978 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -1207,6 +1207,10 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1207 struct net *net = sock_net(sk); 1207 struct net *net = sock_net(sk);
1208 struct mr_table *mrt; 1208 struct mr_table *mrt;
1209 1209
1210 if (sk->sk_type != SOCK_RAW ||
1211 inet_sk(sk)->inet_num != IPPROTO_IGMP)
1212 return -EOPNOTSUPP;
1213
1210 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); 1214 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
1211 if (mrt == NULL) 1215 if (mrt == NULL)
1212 return -ENOENT; 1216 return -ENOENT;
@@ -1219,11 +1223,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1219 1223
1220 switch (optname) { 1224 switch (optname) {
1221 case MRT_INIT: 1225 case MRT_INIT:
1222 if (sk->sk_type != SOCK_RAW ||
1223 inet_sk(sk)->inet_num != IPPROTO_IGMP)
1224 return -EOPNOTSUPP;
1225 if (optlen != sizeof(int)) 1226 if (optlen != sizeof(int))
1226 return -ENOPROTOOPT; 1227 return -EINVAL;
1227 1228
1228 rtnl_lock(); 1229 rtnl_lock();
1229 if (rtnl_dereference(mrt->mroute_sk)) { 1230 if (rtnl_dereference(mrt->mroute_sk)) {
@@ -1284,9 +1285,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1284 case MRT_ASSERT: 1285 case MRT_ASSERT:
1285 { 1286 {
1286 int v; 1287 int v;
1288 if (optlen != sizeof(v))
1289 return -EINVAL;
1287 if (get_user(v, (int __user *)optval)) 1290 if (get_user(v, (int __user *)optval))
1288 return -EFAULT; 1291 return -EFAULT;
1289 mrt->mroute_do_assert = (v) ? 1 : 0; 1292 mrt->mroute_do_assert = !!v;
1290 return 0; 1293 return 0;
1291 } 1294 }
1292#ifdef CONFIG_IP_PIMSM 1295#ifdef CONFIG_IP_PIMSM
@@ -1294,9 +1297,11 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1294 { 1297 {
1295 int v; 1298 int v;
1296 1299
1300 if (optlen != sizeof(v))
1301 return -EINVAL;
1297 if (get_user(v, (int __user *)optval)) 1302 if (get_user(v, (int __user *)optval))
1298 return -EFAULT; 1303 return -EFAULT;
1299 v = (v) ? 1 : 0; 1304 v = !!v;
1300 1305
1301 rtnl_lock(); 1306 rtnl_lock();
1302 ret = 0; 1307 ret = 0;
@@ -1325,7 +1330,8 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
1325 } else { 1330 } else {
1326 if (!ipmr_new_table(net, v)) 1331 if (!ipmr_new_table(net, v))
1327 ret = -ENOMEM; 1332 ret = -ENOMEM;
1328 raw_sk(sk)->ipmr_table = v; 1333 else
1334 raw_sk(sk)->ipmr_table = v;
1329 } 1335 }
1330 rtnl_unlock(); 1336 rtnl_unlock();
1331 return ret; 1337 return ret;
@@ -1351,6 +1357,10 @@ int ip_mroute_getsockopt(struct sock *sk, int optname, char __user *optval, int
1351 struct net *net = sock_net(sk); 1357 struct net *net = sock_net(sk);
1352 struct mr_table *mrt; 1358 struct mr_table *mrt;
1353 1359
1360 if (sk->sk_type != SOCK_RAW ||
1361 inet_sk(sk)->inet_num != IPPROTO_IGMP)
1362 return -EOPNOTSUPP;
1363
1354 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT); 1364 mrt = ipmr_get_table(net, raw_sk(sk)->ipmr_table ? : RT_TABLE_DEFAULT);
1355 if (mrt == NULL) 1365 if (mrt == NULL)
1356 return -ENOENT; 1366 return -ENOENT;