bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
Subsystems (6)
v4 cover bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
When TCP over IPv4 via INET6 API, sk->sk_family is AF_INET6, but it is a v4 pkt. inet_csk(sk)->icsk_af_ops is ipv6_mapped and use ip_queue_xmit. The tos sockopt does not work for bpf [get,set]sockopt() helpers.
Changelog:
v3 -> v4:
* Add 'sk->sk_type != SOCK_RAW && !ipv6_only_sock(sk)' check.
* Re-implement test with LLM assistance.
* v3: https://lore.kernel.org/all/[email protected]/
v2->v3:
* Use sk_is_inet() helper. (Eric Dumazet)
* https://lore.kernel.org/bpf/CANn89i+9GmBLCdgsfH=WWe-tyFYpiO27wONyxaxiU6aOBC6G8g@mail.gmail.com/T/
v1->v2:
* Fix compilation error. (kernel test robot)
* https://lore.kernel.org/bpf/[email protected]/T/
Leon Hwang (2):
bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket selftests/bpf: Add test to verify the fix for bpf_setsockopt() helper
net/core/filter.c | 15 +++- .../selftests/bpf/prog_tests/setget_sockopt.c | 78 +++++++++++++++++++ .../selftests/bpf/progs/setget_sockopt.c | 23 ++++++ 3 files changed, 115 insertions(+), 1 deletion(-)
Signature · 1 line
2.54.0
PATCH v4 1/2 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.
--- net/core/filter.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
net/core/filter.c +14 -1
@@ -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) {
Signature · 1 line
2.54.0
[email protected]
AI reviewIn an earlier review round it was suggested that "bpf_get/setsockopt with ipv4 will fail" should read "bpf_get/setsockopt with SOL_IP will fail", since the call uses the SOL_IP level rather than an…
Quoted 9 lines
When TCP over IPv4 via INET6 API, bpf_get/setsockopt with ipv4 will fail, because
sk->sk_familyisAF_INET6. With ipv6 will success, not take effect, because inet_csk(sk)->icsk_af_ops isipv6_mappedand useip_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 <[email protected]>Signed-off-by Leon Hwang <[email protected]>
In an earlier review round it was suggested that "bpf_get/setsockopt with ipv4 will fail" should read "bpf_get/setsockopt with SOL_IP will fail", since the call uses the SOL_IP level rather than an ipv4 option.
The body here still reads "with ipv4 will fail" - was the s/ipv4/SOL_IP/ reword intended to be picked up?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27472657322
PATCH v4 2/2 selftests/bpf: Add test to verify the fix for bpf_setsockopt() helper
In reply to Leon HwangVerify the fix by:
1. Attach cgroup sockops prog.
2. Build a tcp connection using ipv4 addr in ipv6 socket.
3. Verify the return value of bpf_setsockopt() helper.
--- .../selftests/bpf/prog_tests/setget_sockopt.c | 78 +++++++++++++++++++ .../selftests/bpf/progs/setget_sockopt.c | 23 ++++++ 2 files changed, 101 insertions(+)
tools/testing/selftests/bpf/prog_tests/setget_sockopt.c +78 -0
@@ -199,6 +199,83 @@ static void test_nonstandard_opt(int family)bpf_link__destroy (getsockopt_link); } +static int connect_to_v4mapped_v6_fd (int server_fd) +{ +struct sockaddr_storage addr; +struct sockaddr_in *addr4 = (void *)&addr; +socklen_t addrlen =sizeof (addr); +struct sockaddr_in6 addr6 = {}; +int fd =-1 , v6only =0 , err; + + err =getsockname (server_fd, (struct sockaddr *)&addr, &addrlen); +if (!ASSERT_OK (err,"getsockname" )) +return -1 ; + + fd =socket (AF_INET6 ,SOCK_STREAM ,0 ); +if (!ASSERT_GE (fd,0 ,"socket" )) +return -1 ; + + err =settimeo (fd,0 ); +if (!ASSERT_OK (err,"settimeo" )) + goto err_out; + + err =setsockopt (fd,IPPROTO_IPV6 ,IPV6_V6ONLY , &v6only,sizeof (v6only)); +if (!ASSERT_OK (err,"clear_v6only" )) + goto err_out; + + addr6.sin6_family =AF_INET6 ; + addr6.sin6_port = addr4->sin_port; + addr6.sin6_addr.s6_addr[10 ] =0xff ; + addr6.sin6_addr.s6_addr[11 ] =0xff ; +memcpy (&addr6.sin6_addr.s6_addr[12 ], &addr4->sin_addr,sizeof (addr4->sin_addr)); + + err =connect (fd, (struct sockaddr *)&addr6,sizeof (addr6)); +if (!ASSERT_OK (err,"connect" )) + goto err_out; + +return fd; + +err_out: +close (fd); +return -1 ; +} + +static void test_v4mapped_v6_ip_tos (void ) +{ +struct setget_sockopt__bss *bss = skel->bss; +int sfd =-1 , fd =-1 , got =0 , exp =0x1c ; +socklen_t optlen; + +memset (bss,0 ,sizeof (*bss)); + bss->v4mapped_v6_ip_tos_enable =1 ; + bss->v4mapped_v6_ip_tos_ret =-1 ; + bss->v4mapped_v6_ip_tos_val = exp; + + sfd =start_server (AF_INET ,SOCK_STREAM , addr4_str,0 ,0 ); +if (!ASSERT_GE (sfd,0 ,"start_server" )) + goto err_out; + + fd =connect_to_v4mapped_v6_fd (sfd); +if (!ASSERT_GE (fd,0 ,"connect_to_v4mapped_v6_fd" )) + goto err_out; + +ASSERT_GT (bss->v4mapped_v6_ip_tos_cnt,0 ,"v4mapped_v6_ip_tos_cnt" ); +ASSERT_EQ (bss->v4mapped_v6_ip_tos_ret,0 ,"v4mapped_v6_ip_tos_ret" ); + + optlen =sizeof (got); +if (!ASSERT_OK (getsockopt (fd,SOL_IP ,IP_TOS , &got, &optlen),"getsockopt_ip_tos" )) + goto err_out; + +ASSERT_EQ (got, exp,"ip_tos" ); + +err_out: + bss->v4mapped_v6_ip_tos_enable =0 ; +if (fd >=0 ) +close (fd); +if (sfd >=0 ) +close (sfd); +} +void test_setget_sockopt (void ) { cg_fd =test__join_cgroup (CG_NAME );
@@ -238,6 +315,7 @@ void test_setget_sockopt(void)test_ktls (AF_INET );test_nonstandard_opt (AF_INET );test_nonstandard_opt (AF_INET6 ); +test_v4mapped_v6_ip_tos (); done:setget_sockopt__destroy (skel);
tools/testing/selftests/bpf/progs/setget_sockopt.c +23 -0
@@ -387,6 +387,24 @@ int _getsockopt(struct bpf_sockopt *ctx)return 1 ; } +int v4mapped_v6_ip_tos_enable; +int v4mapped_v6_ip_tos_ret; +int v4mapped_v6_ip_tos_cnt; +int v4mapped_v6_ip_tos_val; + +static void test_v4mapped_v6_ip_tos (struct bpf_sock_ops *skops) +{ +int tos = v4mapped_v6_ip_tos_val; + +if (!v4mapped_v6_ip_tos_enable || skops->op !=BPF_SOCK_OPS_TCP_CONNECT_CB ) +return ; +if (skops->family !=AF_INET6 ) +return ; + + v4mapped_v6_ip_tos_cnt++; + v4mapped_v6_ip_tos_ret =bpf_setsockopt (skops,IPPROTO_IP ,IP_TOS , &tos,sizeof (tos)); +} + SEC("sockops")int skops_sockopt (struct bpf_sock_ops *skops) {
@@ -401,6 +419,11 @@ int skops_sockopt(struct bpf_sock_ops *skops)if (!sk)return 1 ; +if (v4mapped_v6_ip_tos_enable) { +test_v4mapped_v6_ip_tos (skops); +return 1 ; + } +switch (skops->op) {case BPF_SOCK_OPS_TCP_LISTEN_CB : nr_listen += !(bpf_test_sockopt(skops, sk) ||
Signature · 1 line
2.54.0
This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov <[email protected]>:
Hello:
This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov <[email protected]>:
Quoted 11 lines · On Sun, 14 Jun 2026 00:24:41 +0800 you wrote:
When TCP over IPv4 via INET6 API,
sk->sk_familyisAF_INET6, but it is a v4 pkt. inet_csk(sk)->icsk_af_ops isipv6_mappedand useip_queue_xmit. The tos sockopt does not work for bpf [get,set]sockopt() helpers.Changelog:
v3 -> v4:
* Add 'sk->sk_type!=SOCK_RAW&& !ipv6_only_sock(sk)' check.
* Re-implement test with LLM assistance.
* v3: https://lore.kernel.org/all/[email protected]/[...]
Here is the summary with links:
- [bpf-next,v4,1/2] bpf: Fix bpf_get/setsockopt to tos for ipv4-mapped ipv6 socket
https://git.kernel.org/bpf/bpf-next/c/ca0f587c029a - [bpf-next,v4,2/2] selftests/bpf: Add test to verify the fix for bpf_setsockopt() helper https://git.kernel.org/bpf/bpf-next/c/5cf2c21ab090
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html