Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv{4,6}/raw: fix output xfrm lookup wrt protocol

With a raw socket bound to IPPROTO_RAW (ie with hdrincl enabled), the
protocol field of the flow structure, build by raw_sendmsg() /
rawv6_sendmsg()), is set to IPPROTO_RAW. This breaks the ipsec policy
lookup when some policies are defined with a protocol in the selector.

For ipv6, the sin6_port field from 'struct sockaddr_in6' could be used to
specify the protocol. Just accept all values for IPPROTO_RAW socket.

For ipv4, the sin_port field of 'struct sockaddr_in' could not be used
without breaking backward compatibility (the value of this field was never
checked). Let's add a new kind of control message, so that the userland
could specify which protocol is used.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
CC: stable@vger.kernel.org
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Link: https://lore.kernel.org/r/20230522120820.1319391-1-nicolas.dichtel@6wind.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Nicolas Dichtel and committed by
Paolo Abeni
3632679d 60076124

+20 -3
+2
include/net/ip.h
··· 76 76 __be32 addr; 77 77 int oif; 78 78 struct ip_options_rcu *opt; 79 + __u8 protocol; 79 80 __u8 ttl; 80 81 __s16 tos; 81 82 char priority; ··· 97 96 ipcm->sockc.tsflags = inet->sk.sk_tsflags; 98 97 ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if); 99 98 ipcm->addr = inet->inet_saddr; 99 + ipcm->protocol = inet->inet_num; 100 100 } 101 101 102 102 #define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
+1
include/uapi/linux/in.h
··· 163 163 #define IP_MULTICAST_ALL 49 164 164 #define IP_UNICAST_IF 50 165 165 #define IP_LOCAL_PORT_RANGE 51 166 + #define IP_PROTOCOL 52 166 167 167 168 #define MCAST_EXCLUDE 0 168 169 #define MCAST_INCLUDE 1
+11 -1
net/ipv4/ip_sockglue.c
··· 317 317 ipc->tos = val; 318 318 ipc->priority = rt_tos2priority(ipc->tos); 319 319 break; 320 - 320 + case IP_PROTOCOL: 321 + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) 322 + return -EINVAL; 323 + val = *(int *)CMSG_DATA(cmsg); 324 + if (val < 1 || val > 255) 325 + return -EINVAL; 326 + ipc->protocol = val; 327 + break; 321 328 default: 322 329 return -EINVAL; 323 330 } ··· 1767 1760 break; 1768 1761 case IP_LOCAL_PORT_RANGE: 1769 1762 val = inet->local_port_range.hi << 16 | inet->local_port_range.lo; 1763 + break; 1764 + case IP_PROTOCOL: 1765 + val = inet_sk(sk)->inet_num; 1770 1766 break; 1771 1767 default: 1772 1768 sockopt_release_sock(sk);
+4 -1
net/ipv4/raw.c
··· 532 532 } 533 533 534 534 ipcm_init_sk(&ipc, inet); 535 + /* Keep backward compat */ 536 + if (hdrincl) 537 + ipc.protocol = IPPROTO_RAW; 535 538 536 539 if (msg->msg_controllen) { 537 540 err = ip_cmsg_send(sk, msg, &ipc, false); ··· 602 599 603 600 flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, 604 601 RT_SCOPE_UNIVERSE, 605 - hdrincl ? IPPROTO_RAW : sk->sk_protocol, 602 + hdrincl ? ipc.protocol : sk->sk_protocol, 606 603 inet_sk_flowi_flags(sk) | 607 604 (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), 608 605 daddr, saddr, 0, 0, sk->sk_uid);
+2 -1
net/ipv6/raw.c
··· 793 793 794 794 if (!proto) 795 795 proto = inet->inet_num; 796 - else if (proto != inet->inet_num) 796 + else if (proto != inet->inet_num && 797 + inet->inet_num != IPPROTO_RAW) 797 798 return -EINVAL; 798 799 799 800 if (proto > 255)