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>
This commit is contained in:
Родитель
77b67063bb
Коммит
0c9f79be29
|
@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level,
|
|||
struct inet_sock *inet = inet_sk(sk);
|
||||
int val = 0, err;
|
||||
|
||||
if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
|
||||
(1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
|
||||
(1<<IP_RETOPTS) | (1<<IP_TOS) |
|
||||
(1<<IP_TTL) | (1<<IP_HDRINCL) |
|
||||
(1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
|
||||
(1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
|
||||
(1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
|
||||
(1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
|
||||
optname == IP_UNICAST_IF ||
|
||||
optname == IP_MULTICAST_TTL ||
|
||||
optname == IP_MULTICAST_ALL ||
|
||||
optname == IP_MULTICAST_LOOP ||
|
||||
optname == IP_RECVORIGDSTADDR) {
|
||||
switch (optname) {
|
||||
case IP_PKTINFO:
|
||||
case IP_RECVTTL:
|
||||
case IP_RECVOPTS:
|
||||
case IP_RECVTOS:
|
||||
case IP_RETOPTS:
|
||||
case IP_TOS:
|
||||
case IP_TTL:
|
||||
case IP_HDRINCL:
|
||||
case IP_MTU_DISCOVER:
|
||||
case IP_RECVERR:
|
||||
case IP_ROUTER_ALERT:
|
||||
case IP_FREEBIND:
|
||||
case IP_PASSSEC:
|
||||
case IP_TRANSPARENT:
|
||||
case IP_MINTTL:
|
||||
case IP_NODEFRAG:
|
||||
case IP_UNICAST_IF:
|
||||
case IP_MULTICAST_TTL:
|
||||
case IP_MULTICAST_ALL:
|
||||
case IP_MULTICAST_LOOP:
|
||||
case IP_RECVORIGDSTADDR:
|
||||
if (optlen >= sizeof(int)) {
|
||||
if (get_user(val, (int __user *) optval))
|
||||
return -EFAULT;
|
||||
|
|
Загрузка…
Ссылка в новой задаче