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 | |
| 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>
| -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; |
