diff options
author | Eric Dumazet <edumazet@google.com> | 2012-11-25 01:41:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-25 16:34:16 -0500 |
commit | 5e1859fbcc3ccdd56d528df91d7b6f70e73d6b82 (patch) | |
tree | efa1ce9061f7bcf8280159c9d2612221279766d3 /net/ipv4/ipmr.c | |
parent | 11e980299f922884377c7ce5d8c331327c5c3fd6 (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.c | 24 |
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; |