diff options
author | Xi Wang <xi.wang@gmail.com> | 2012-11-11 06:20:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-11-11 17:53:13 -0500 |
commit | 0c9f79be295c99ac7e4b569ca493d75fdcc19e4e (patch) | |
tree | 86ac3ac72907079585afc43ec2a25edcb8bb051b /net/ipv4/ip_sockglue.c | |
parent | 77b67063bb6bce6d475e910d3b886a606d0d91f7 (diff) |
ipv4: avoid undefined behavior in do_ip_setsockopt()
(1<<optname) is undefined behavior in C with a negative optname or
optname larger than 31. In those cases the result of the shift is
not necessarily zero (e.g., on x86).
This patch simplifies the code with a switch statement on optname.
It also allows the compiler to generate better code (e.g., using a
64-bit mask).
Signed-off-by: Xi Wang <xi.wang@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_sockglue.c')
-rw-r--r-- | net/ipv4/ip_sockglue.c | 35 |
1 files changed, 22 insertions, 13 deletions
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 5eea4a811042..14bbfcf717ac 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
457 | struct inet_sock *inet = inet_sk(sk); | 457 | struct inet_sock *inet = inet_sk(sk); |
458 | int val = 0, err; | 458 | int val = 0, err; |
459 | 459 | ||
460 | if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) | | 460 | switch (optname) { |
461 | (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) | | 461 | case IP_PKTINFO: |
462 | (1<<IP_RETOPTS) | (1<<IP_TOS) | | 462 | case IP_RECVTTL: |
463 | (1<<IP_TTL) | (1<<IP_HDRINCL) | | 463 | case IP_RECVOPTS: |
464 | (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) | | 464 | case IP_RECVTOS: |
465 | (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) | | 465 | case IP_RETOPTS: |
466 | (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) | | 466 | case IP_TOS: |
467 | (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) || | 467 | case IP_TTL: |
468 | optname == IP_UNICAST_IF || | 468 | case IP_HDRINCL: |
469 | optname == IP_MULTICAST_TTL || | 469 | case IP_MTU_DISCOVER: |
470 | optname == IP_MULTICAST_ALL || | 470 | case IP_RECVERR: |
471 | optname == IP_MULTICAST_LOOP || | 471 | case IP_ROUTER_ALERT: |
472 | optname == IP_RECVORIGDSTADDR) { | 472 | case IP_FREEBIND: |
473 | case IP_PASSSEC: | ||
474 | case IP_TRANSPARENT: | ||
475 | case IP_MINTTL: | ||
476 | case IP_NODEFRAG: | ||
477 | case IP_UNICAST_IF: | ||
478 | case IP_MULTICAST_TTL: | ||
479 | case IP_MULTICAST_ALL: | ||
480 | case IP_MULTICAST_LOOP: | ||
481 | case IP_RECVORIGDSTADDR: | ||
473 | if (optlen >= sizeof(int)) { | 482 | if (optlen >= sizeof(int)) { |
474 | if (get_user(val, (int __user *) optval)) | 483 | if (get_user(val, (int __user *) optval)) |
475 | return -EFAULT; | 484 | return -EFAULT; |