]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
authorLeon Hwang <leon.hwang@linux.dev>
Sat, 13 Jun 2026 16:24:42 +0000 (00:24 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 15 Jun 2026 00:38:55 +0000 (17:38 -0700)
When TCP over IPv4 via INET6 API, bpf_get/setsockopt with ipv4 will
fail, because sk->sk_family is AF_INET6. With ipv6 will success, not
take effect, because inet_csk(sk)->icsk_af_ops is ipv6_mapped and
use ip_queue_xmit, inet_sk(sk)->tos.

To relax this restriction, allow getting/setting tos for those possible
ipv4-mapped ipv6 sockets.

Fixes: ee7f1e1302f5 ("bpf: Change bpf_setsockopt(SOL_IP) to reuse do_ip_setsockopt()")
Signed-off-by: Feng Zhou <zhoufeng.zf@bytedance.com>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
Link: https://lore.kernel.org/r/20260613162443.60515-2-leon.hwang@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
net/core/filter.c

index 9590877b0714f7fd29c3efa32e00cb13671dc057..57b00c6cc8cc12d41effdb1862a2fe464b9b71f2 100644 (file)
@@ -5544,11 +5544,24 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
                                 KERNEL_SOCKPTR(optval), *optlen);
 }
 
+static bool sk_allows_sol_ip_sockopt(struct sock *sk)
+{
+       switch (sk->sk_family) {
+       case AF_INET:
+               return true;
+       case AF_INET6:
+               /* Allow getting/setting sockopt for possible ipv4-mapped ipv6 socket. */
+               return sk->sk_type != SOCK_RAW && !ipv6_only_sock(sk);
+       default:
+               return false;
+       }
+}
+
 static int sol_ip_sockopt(struct sock *sk, int optname,
                          char *optval, int *optlen,
                          bool getopt)
 {
-       if (sk->sk_family != AF_INET)
+       if (!sk_allows_sol_ip_sockopt(sk))
                return -EINVAL;
 
        switch (optname) {