diff options
| author | Leon Hwang <leon.hwang@linux.dev> | 2026-06-14 00:24:42 +0800 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-06-14 17:38:55 -0700 |
| commit | ca0f587c029afa66227f7b932450b1c417403394 (patch) | |
| tree | 0c09eec65fcd11f39a17d437070554f631e18405 /net | |
| parent | cf750df538b0ee8f18c00a0b7d530399df363215 (diff) | |
| download | ath-ca0f587c029afa66227f7b932450b1c417403394.tar.gz | |
bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
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>
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/filter.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/net/core/filter.c b/net/core/filter.c index 9590877b0714f..57b00c6cc8cc1 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -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) { |
