* [PATCH v1 bpf 0/2] bpf: Reject access to unix_sk(sk)->{peer,listener}.
@ 2026-02-07 23:07 Kuniyuki Iwashima
2026-02-07 23:07 ` [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer Kuniyuki Iwashima
2026-02-07 23:07 ` [PATCH v1 bpf 2/2] bpf: Reject access to unix_sk(sk)->listener Kuniyuki Iwashima
0 siblings, 2 replies; 11+ messages in thread
From: Kuniyuki Iwashima @ 2026-02-07 23:07 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau
Cc: John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj,
Kuniyuki Iwashima, Kuniyuki Iwashima, bpf, netdev
Accessing unix_sk(sk)->{peer,listener} is only safe under
unix_state_lock().
There are many functions where bpf prog can access the fields
locklessly via fentry/fexit or bpf iter.
unix_sk(sk)->{peer,listener} could go away during such lockless
access by bpf.
This seires marks the fields with PTR_UNTRUSTED to prevent
such use-after-free.
Kuniyuki Iwashima (2):
bpf: Reject access to unix_sk(sk)->peer.
bpf: Reject access to unix_sk(sk)->listener.
kernel/bpf/verifier.c | 19 +++++++
.../selftests/bpf/progs/verifier_sock.c | 49 +++++++++++++++++++
2 files changed, 68 insertions(+)
--
2.53.0.rc2.204.g2597b5adb4-goog
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-07 23:07 [PATCH v1 bpf 0/2] bpf: Reject access to unix_sk(sk)->{peer,listener} Kuniyuki Iwashima @ 2026-02-07 23:07 ` Kuniyuki Iwashima 2026-02-09 23:00 ` Alexei Starovoitov 2026-02-07 23:07 ` [PATCH v1 bpf 2/2] bpf: Reject access to unix_sk(sk)->listener Kuniyuki Iwashima 1 sibling, 1 reply; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-07 23:07 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau Cc: John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, Kuniyuki Iwashima, bpf, netdev, Martin KaFai Lau Michal Luczaj reported use-after-free of unix_sk(sk)->peer by bpf_skc_to_unix_sock(). [0] Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), but there are many functions where bpf prog can access the field locklessly via fentry/fexit. unix_dgram_connect() could clear unix_sk(sk)->peer and release the last refcnt of the peer sk while a bpf prog is accessing it, resulting in use-after-free. Another problematic scenario is that unix_sk(sk)->peer could go away while being passed to bpf_setsockopt() in bpf iter. To avoid such issues, let's reject access to unix_sk(sk)->peer by marking the pointer with PTR_UNTRUSTED. If needed, we could add a new helper later that uses unix_peer_get() and requires bpf_sk_release(). [0]: BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 Read of size 2 at addr ffff888147d38890 by task test_progs/2495 Call Trace: dump_stack_lvl+0x5d/0x80 print_report+0x170/0x4f3 kasan_report+0xe1/0x180 bpf_skc_to_unix_sock+0xa4/0xb0 bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e bpf_trampoline_6442564662+0x47/0xab unix_shutdown+0x9/0x880 __sys_shutdown+0xe1/0x160 __x64_sys_shutdown+0x52/0x90 do_syscall_64+0x6b/0x3a0 entry_SYSCALL_64_after_hwframe+0x76/0x7e Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") Reported-by: Michal Luczaj <mhal@rbox.co> Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> --- kernel/bpf/verifier.c | 18 +++++++++++++ .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 3135643d5695..b328a1640c82 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) /* * Allow list few fields as RCU trusted or full trusted. @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { struct file *vm_file; }; +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { + struct sock *peer; +}; + static bool type_is_rcu(struct bpf_verifier_env *env, struct bpf_reg_state *reg, const char *field_name, u32 btf_id) @@ -7201,6 +7206,16 @@ static bool type_is_trusted_or_null(struct bpf_verifier_env *env, "__safe_trusted_or_null"); } +static bool type_is_untrusted(struct bpf_verifier_env *env, + struct bpf_reg_state *reg, + const char *field_name, u32 btf_id) +{ + BTF_TYPE_EMIT(BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock)); + + return btf_nested_type_is_trusted(&env->log, reg, field_name, btf_id, + "__safe_untrusted"); +} + static int check_ptr_to_btf_access(struct bpf_verifier_env *env, struct bpf_reg_state *regs, int regno, int off, int size, @@ -7343,6 +7358,9 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env, } else { /* Old compat. Deprecated */ clear_trusted_flags(&flag); + + if (type_is_untrusted(env, reg, field_name, btf_id)) + flag |= PTR_UNTRUSTED; } if (atype == BPF_READ && value_regno >= 0) { diff --git a/tools/testing/selftests/bpf/progs/verifier_sock.c b/tools/testing/selftests/bpf/progs/verifier_sock.c index a2132c72d3b8..8de4d3ed98d4 100644 --- a/tools/testing/selftests/bpf/progs/verifier_sock.c +++ b/tools/testing/selftests/bpf/progs/verifier_sock.c @@ -3,6 +3,7 @@ #include "vmlinux.h" #include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> #include "bpf_misc.h" struct { @@ -1166,4 +1167,28 @@ int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk) return TCX_PASS; } +SEC("fentry/unix_dgram_sendmsg") +__failure __msg("R1 type=untrusted_ptr_ expected=sock_common, sock, tcp_sock, xdp_sock, ptr_, trusted_ptr_") +int BPF_PROG(trace_unix_dgram_sendmsg, struct socket *sock, struct msghdr *msg, + size_t len) +{ + struct unix_sock *u, *u_other; + + if (!sock) + return 0; + + u = bpf_skc_to_unix_sock(sock->sk); + if (!u) + return 0; + + /* unix_dgram_connect() could clear u->peer + * and the peer could be freed. + */ + u_other = bpf_skc_to_unix_sock(u->peer); + if (!u_other) + return 0; + + return 0; +} + char _license[] SEC("license") = "GPL"; -- 2.53.0.rc2.204.g2597b5adb4-goog ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-07 23:07 ` [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer Kuniyuki Iwashima @ 2026-02-09 23:00 ` Alexei Starovoitov 2026-02-10 1:19 ` Kuniyuki Iwashima 0 siblings, 1 reply; 11+ messages in thread From: Alexei Starovoitov @ 2026-02-09 23:00 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > bpf_skc_to_unix_sock(). [0] > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > but there are many functions where bpf prog can access the field > locklessly via fentry/fexit. > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > the last refcnt of the peer sk while a bpf prog is accessing it, > resulting in use-after-free. > > Another problematic scenario is that unix_sk(sk)->peer could > go away while being passed to bpf_setsockopt() in bpf iter. > > To avoid such issues, let's reject access to unix_sk(sk)->peer > by marking the pointer with PTR_UNTRUSTED. > > If needed, we could add a new helper later that uses unix_peer_get() > and requires bpf_sk_release(). > > [0]: > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > Call Trace: > dump_stack_lvl+0x5d/0x80 > print_report+0x170/0x4f3 > kasan_report+0xe1/0x180 > bpf_skc_to_unix_sock+0xa4/0xb0 > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > bpf_trampoline_6442564662+0x47/0xab > unix_shutdown+0x9/0x880 > __sys_shutdown+0xe1/0x160 > __x64_sys_shutdown+0x52/0x90 > do_syscall_64+0x6b/0x3a0 > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > Reported-by: Michal Luczaj <mhal@rbox.co> > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > --- > kernel/bpf/verifier.c | 18 +++++++++++++ > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > 2 files changed, 43 insertions(+) > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 3135643d5695..b328a1640c82 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > /* > * Allow list few fields as RCU trusted or full trusted. > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > struct file *vm_file; > }; > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > + struct sock *peer; > +}; > + That's just one out of many. It's not really a fix, but a bandaid for one case. We discussed it in the past and the only way forward is to make helpers only accept trusted args. Recently we made KF_TRUSTED_ARGS a default for all kfuncs. We should do the same for helpers. pw-bot: cr ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-09 23:00 ` Alexei Starovoitov @ 2026-02-10 1:19 ` Kuniyuki Iwashima 2026-02-11 2:47 ` Alexei Starovoitov 0 siblings, 1 reply; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-10 1:19 UTC (permalink / raw) To: Alexei Starovoitov Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > bpf_skc_to_unix_sock(). [0] > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > but there are many functions where bpf prog can access the field > > locklessly via fentry/fexit. > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > the last refcnt of the peer sk while a bpf prog is accessing it, > > resulting in use-after-free. > > > > Another problematic scenario is that unix_sk(sk)->peer could > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > by marking the pointer with PTR_UNTRUSTED. > > > > If needed, we could add a new helper later that uses unix_peer_get() > > and requires bpf_sk_release(). > > > > [0]: > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > Call Trace: > > dump_stack_lvl+0x5d/0x80 > > print_report+0x170/0x4f3 > > kasan_report+0xe1/0x180 > > bpf_skc_to_unix_sock+0xa4/0xb0 > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > bpf_trampoline_6442564662+0x47/0xab > > unix_shutdown+0x9/0x880 > > __sys_shutdown+0xe1/0x160 > > __x64_sys_shutdown+0x52/0x90 > > do_syscall_64+0x6b/0x3a0 > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > Reported-by: Michal Luczaj <mhal@rbox.co> > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > --- > > kernel/bpf/verifier.c | 18 +++++++++++++ > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > 2 files changed, 43 insertions(+) > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > index 3135643d5695..b328a1640c82 100644 > > --- a/kernel/bpf/verifier.c > > +++ b/kernel/bpf/verifier.c > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > /* > > * Allow list few fields as RCU trusted or full trusted. > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > struct file *vm_file; > > }; > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > + struct sock *peer; > > +}; > > + > > That's just one out of many. It's not really a fix, > but a bandaid for one case. Right, this is only one example where a pointer lifetime does not match with bpf prog. > We discussed it in the past and the only way forward is to make > helpers only accept trusted args. > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > We should do the same for helpers. What about just reading an untrusted pointer ? I used bpf_skc_to_unix_sock() in selftest in case compiler could optimise out branches that always return 0. Currently, this passes the verifier and can trigger UAF. u = bpf_skc_to_unix_sock(sock->sk); if (!u || !u->peer) return 0; if (u->peer->__sk_common.skc_family) # unsafe access return 0; Thanks ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-10 1:19 ` Kuniyuki Iwashima @ 2026-02-11 2:47 ` Alexei Starovoitov 2026-02-11 4:23 ` Kuniyuki Iwashima 0 siblings, 1 reply; 11+ messages in thread From: Alexei Starovoitov @ 2026-02-11 2:47 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > <alexei.starovoitov@gmail.com> wrote: > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > bpf_skc_to_unix_sock(). [0] > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > but there are many functions where bpf prog can access the field > > > locklessly via fentry/fexit. > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > resulting in use-after-free. > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > and requires bpf_sk_release(). > > > > > > [0]: > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > Call Trace: > > > dump_stack_lvl+0x5d/0x80 > > > print_report+0x170/0x4f3 > > > kasan_report+0xe1/0x180 > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > bpf_trampoline_6442564662+0x47/0xab > > > unix_shutdown+0x9/0x880 > > > __sys_shutdown+0xe1/0x160 > > > __x64_sys_shutdown+0x52/0x90 > > > do_syscall_64+0x6b/0x3a0 > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > --- > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > 2 files changed, 43 insertions(+) > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > index 3135643d5695..b328a1640c82 100644 > > > --- a/kernel/bpf/verifier.c > > > +++ b/kernel/bpf/verifier.c > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > /* > > > * Allow list few fields as RCU trusted or full trusted. > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > struct file *vm_file; > > > }; > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > + struct sock *peer; > > > +}; > > > + > > > > That's just one out of many. It's not really a fix, > > but a bandaid for one case. > > Right, this is only one example where a pointer lifetime > does not match with bpf prog. > > > We discussed it in the past and the only way forward is to make > > helpers only accept trusted args. > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > We should do the same for helpers. > > What about just reading an untrusted pointer ? What do you mean 'untrusted' ? There are 3 types of ptr_to_btf_id: trusted, untrusted, legacy (without either trusted or untrusted flags). kfuncs now accept only trusted, while helpers still accept trusted and legacy. The legacy should be disallowed. That might break some bpf programs, so it has to be done carefully. > I used bpf_skc_to_unix_sock() in selftest in case compiler > could optimise out branches that always return 0. > > Currently, this passes the verifier and can trigger UAF. > > u = bpf_skc_to_unix_sock(sock->sk); > if (!u || !u->peer) > return 0; > if (u->peer->__sk_common.skc_family) # unsafe access > return 0; No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem treatment. So above works and won't crash the kernel. It's effectively inlined probe_read_kernel. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-11 2:47 ` Alexei Starovoitov @ 2026-02-11 4:23 ` Kuniyuki Iwashima 2026-02-11 21:25 ` Alexei Starovoitov 0 siblings, 1 reply; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-11 4:23 UTC (permalink / raw) To: Alexei Starovoitov Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Tue, Feb 10, 2026 at 6:47 PM Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > > <alexei.starovoitov@gmail.com> wrote: > > > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > > bpf_skc_to_unix_sock(). [0] > > > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > > but there are many functions where bpf prog can access the field > > > > locklessly via fentry/fexit. > > > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > > resulting in use-after-free. > > > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > > and requires bpf_sk_release(). > > > > > > > > [0]: > > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > > Call Trace: > > > > dump_stack_lvl+0x5d/0x80 > > > > print_report+0x170/0x4f3 > > > > kasan_report+0xe1/0x180 > > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > > bpf_trampoline_6442564662+0x47/0xab > > > > unix_shutdown+0x9/0x880 > > > > __sys_shutdown+0xe1/0x160 > > > > __x64_sys_shutdown+0x52/0x90 > > > > do_syscall_64+0x6b/0x3a0 > > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > > --- > > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > > 2 files changed, 43 insertions(+) > > > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > index 3135643d5695..b328a1640c82 100644 > > > > --- a/kernel/bpf/verifier.c > > > > +++ b/kernel/bpf/verifier.c > > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > > > /* > > > > * Allow list few fields as RCU trusted or full trusted. > > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > > struct file *vm_file; > > > > }; > > > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > > + struct sock *peer; > > > > +}; > > > > + > > > > > > That's just one out of many. It's not really a fix, > > > but a bandaid for one case. > > > > Right, this is only one example where a pointer lifetime > > does not match with bpf prog. > > > > > We discussed it in the past and the only way forward is to make > > > helpers only accept trusted args. > > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > > We should do the same for helpers. > > > > What about just reading an untrusted pointer ? > > What do you mean 'untrusted' ? > There are 3 types of ptr_to_btf_id: > trusted, untrusted, legacy (without either trusted or untrusted flags). Ah sorry, I used 'untrusted' since the pointer is not always valid, but I think legacy is the one I meant in this case. > > kfuncs now accept only trusted, while helpers still accept > trusted and legacy. The legacy should be disallowed. > That might break some bpf programs, so it has to be done carefully. > > > I used bpf_skc_to_unix_sock() in selftest in case compiler > > could optimise out branches that always return 0. > > > > Currently, this passes the verifier and can trigger UAF. > > > > u = bpf_skc_to_unix_sock(sock->sk); > > if (!u || !u->peer) > > return 0; > > if (u->peer->__sk_common.skc_family) # unsafe access > > return 0; > > No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem > treatment. So above works and won't crash the kernel. > It's effectively inlined probe_read_kernel. Yes, it doesn't crash. I was just unsure about the bpf expectation [0] like how we should treat KASAN use-after-free report by bpf prog reading a pointer whose lifetime is not guaranteed by bpf helper/verifier. So, if this is WAI, I'm fine with that. [0]: https://lore.kernel.org/all/CAAVpQUDrC1rO2diM3gVg5GV5CTVAUS2RbLP+SpHBGqKcUT0iMA@mail.gmail.com/ ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-11 4:23 ` Kuniyuki Iwashima @ 2026-02-11 21:25 ` Alexei Starovoitov 2026-02-11 22:22 ` Kuniyuki Iwashima 0 siblings, 1 reply; 11+ messages in thread From: Alexei Starovoitov @ 2026-02-11 21:25 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Tue, Feb 10, 2026 at 8:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > On Tue, Feb 10, 2026 at 6:47 PM Alexei Starovoitov > <alexei.starovoitov@gmail.com> wrote: > > > > On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > > > bpf_skc_to_unix_sock(). [0] > > > > > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > > > but there are many functions where bpf prog can access the field > > > > > locklessly via fentry/fexit. > > > > > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > > > resulting in use-after-free. > > > > > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > > > and requires bpf_sk_release(). > > > > > > > > > > [0]: > > > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > > > Call Trace: > > > > > dump_stack_lvl+0x5d/0x80 > > > > > print_report+0x170/0x4f3 > > > > > kasan_report+0xe1/0x180 > > > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > > > bpf_trampoline_6442564662+0x47/0xab > > > > > unix_shutdown+0x9/0x880 > > > > > __sys_shutdown+0xe1/0x160 > > > > > __x64_sys_shutdown+0x52/0x90 > > > > > do_syscall_64+0x6b/0x3a0 > > > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > > > --- > > > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > > > 2 files changed, 43 insertions(+) > > > > > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > > index 3135643d5695..b328a1640c82 100644 > > > > > --- a/kernel/bpf/verifier.c > > > > > +++ b/kernel/bpf/verifier.c > > > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > > > > > /* > > > > > * Allow list few fields as RCU trusted or full trusted. > > > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > > > struct file *vm_file; > > > > > }; > > > > > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > > > + struct sock *peer; > > > > > +}; > > > > > + > > > > > > > > That's just one out of many. It's not really a fix, > > > > but a bandaid for one case. > > > > > > Right, this is only one example where a pointer lifetime > > > does not match with bpf prog. > > > > > > > We discussed it in the past and the only way forward is to make > > > > helpers only accept trusted args. > > > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > > > We should do the same for helpers. > > > > > > What about just reading an untrusted pointer ? > > > > What do you mean 'untrusted' ? > > There are 3 types of ptr_to_btf_id: > > trusted, untrusted, legacy (without either trusted or untrusted flags). > > Ah sorry, I used 'untrusted' since the pointer is not always > valid, but I think legacy is the one I meant in this case. > > > > > > kfuncs now accept only trusted, while helpers still accept > > trusted and legacy. The legacy should be disallowed. > > That might break some bpf programs, so it has to be done carefully. > > > > > I used bpf_skc_to_unix_sock() in selftest in case compiler > > > could optimise out branches that always return 0. > > > > > > Currently, this passes the verifier and can trigger UAF. > > > > > > u = bpf_skc_to_unix_sock(sock->sk); > > > if (!u || !u->peer) > > > return 0; > > > if (u->peer->__sk_common.skc_family) # unsafe access > > > return 0; > > > > No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem > > treatment. So above works and won't crash the kernel. > > It's effectively inlined probe_read_kernel. > > Yes, it doesn't crash. > > I was just unsure about the bpf expectation [0] like how we > should treat KASAN use-after-free report by bpf prog reading > a pointer whose lifetime is not guaranteed by bpf helper/verifier. > > So, if this is WAI, I'm fine with that. > > [0]: https://lore.kernel.org/all/CAAVpQUDrC1rO2diM3gVg5GV5CTVAUS2RbLP+SpHBGqKcUT0iMA@mail.gmail.com/ That's different. That's the actual UAF inside bpf_skc_to_unix_sock(). That needs to be fixed with what I described above by allowing only trusted pointers into helpers. In my earlier reply I meant that: if (u->peer->__sk_common.skc_family) # unsafe access is fine. It's safe access, because it's sanitized by the verifier/JIT. The code inside helpers is a normal kernel code, so kfuncs/helpers should only accept trusted pointers. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-11 21:25 ` Alexei Starovoitov @ 2026-02-11 22:22 ` Kuniyuki Iwashima 2026-02-11 22:39 ` Alexei Starovoitov 0 siblings, 1 reply; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-11 22:22 UTC (permalink / raw) To: Alexei Starovoitov Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Wed, Feb 11, 2026 at 1:26 PM Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Tue, Feb 10, 2026 at 8:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > On Tue, Feb 10, 2026 at 6:47 PM Alexei Starovoitov > > <alexei.starovoitov@gmail.com> wrote: > > > > > > On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > > > > bpf_skc_to_unix_sock(). [0] > > > > > > > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > > > > but there are many functions where bpf prog can access the field > > > > > > locklessly via fentry/fexit. > > > > > > > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > > > > resulting in use-after-free. > > > > > > > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > > > > and requires bpf_sk_release(). > > > > > > > > > > > > [0]: > > > > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > > > > Call Trace: > > > > > > dump_stack_lvl+0x5d/0x80 > > > > > > print_report+0x170/0x4f3 > > > > > > kasan_report+0xe1/0x180 > > > > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > > > > bpf_trampoline_6442564662+0x47/0xab > > > > > > unix_shutdown+0x9/0x880 > > > > > > __sys_shutdown+0xe1/0x160 > > > > > > __x64_sys_shutdown+0x52/0x90 > > > > > > do_syscall_64+0x6b/0x3a0 > > > > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > > > > --- > > > > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > > > > 2 files changed, 43 insertions(+) > > > > > > > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > > > index 3135643d5695..b328a1640c82 100644 > > > > > > --- a/kernel/bpf/verifier.c > > > > > > +++ b/kernel/bpf/verifier.c > > > > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > > > > > > > /* > > > > > > * Allow list few fields as RCU trusted or full trusted. > > > > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > > > > struct file *vm_file; > > > > > > }; > > > > > > > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > > > > + struct sock *peer; > > > > > > +}; > > > > > > + > > > > > > > > > > That's just one out of many. It's not really a fix, > > > > > but a bandaid for one case. > > > > > > > > Right, this is only one example where a pointer lifetime > > > > does not match with bpf prog. > > > > > > > > > We discussed it in the past and the only way forward is to make > > > > > helpers only accept trusted args. > > > > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > > > > We should do the same for helpers. > > > > > > > > What about just reading an untrusted pointer ? > > > > > > What do you mean 'untrusted' ? > > > There are 3 types of ptr_to_btf_id: > > > trusted, untrusted, legacy (without either trusted or untrusted flags). > > > > Ah sorry, I used 'untrusted' since the pointer is not always > > valid, but I think legacy is the one I meant in this case. > > > > > > > > > > kfuncs now accept only trusted, while helpers still accept > > > trusted and legacy. The legacy should be disallowed. > > > That might break some bpf programs, so it has to be done carefully. > > > > > > > I used bpf_skc_to_unix_sock() in selftest in case compiler > > > > could optimise out branches that always return 0. > > > > > > > > Currently, this passes the verifier and can trigger UAF. > > > > > > > > u = bpf_skc_to_unix_sock(sock->sk); > > > > if (!u || !u->peer) > > > > return 0; > > > > if (u->peer->__sk_common.skc_family) # unsafe access > > > > return 0; > > > > > > No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem > > > treatment. So above works and won't crash the kernel. > > > It's effectively inlined probe_read_kernel. > > > > Yes, it doesn't crash. > > > > I was just unsure about the bpf expectation [0] like how we > > should treat KASAN use-after-free report by bpf prog reading > > a pointer whose lifetime is not guaranteed by bpf helper/verifier. > > > > So, if this is WAI, I'm fine with that. > > > > [0]: https://lore.kernel.org/all/CAAVpQUDrC1rO2diM3gVg5GV5CTVAUS2RbLP+SpHBGqKcUT0iMA@mail.gmail.com/ > > That's different. That's the actual UAF inside bpf_skc_to_unix_sock(). > That needs to be fixed with what I described above by allowing > only trusted pointers into helpers. I got this point. > In my earlier reply I meant that: > if (u->peer->__sk_common.skc_family) # unsafe access > is fine. It's safe access, because it's sanitized by the verifier/JIT. but I'm a bit confused here.. Even though the verifier makes sure the pointer is not NULL, u->peer can be freed concurrently by another thread, then how can verifier/JIT prevent UAF ? Or can this be still called 'safe access' regardless of runtime UAF because the user-provided bpf prog was verified once and not in-tree kernel code ? > The code inside helpers is a normal kernel code, > so kfuncs/helpers should only accept trusted pointers. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-11 22:22 ` Kuniyuki Iwashima @ 2026-02-11 22:39 ` Alexei Starovoitov 2026-02-11 23:01 ` Kuniyuki Iwashima 0 siblings, 1 reply; 11+ messages in thread From: Alexei Starovoitov @ 2026-02-11 22:39 UTC (permalink / raw) To: Kuniyuki Iwashima Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Wed, Feb 11, 2026 at 2:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > On Wed, Feb 11, 2026 at 1:26 PM Alexei Starovoitov > <alexei.starovoitov@gmail.com> wrote: > > > > On Tue, Feb 10, 2026 at 8:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > On Tue, Feb 10, 2026 at 6:47 PM Alexei Starovoitov > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > > > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > > > > > bpf_skc_to_unix_sock(). [0] > > > > > > > > > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > > > > > but there are many functions where bpf prog can access the field > > > > > > > locklessly via fentry/fexit. > > > > > > > > > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > > > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > > > > > resulting in use-after-free. > > > > > > > > > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > > > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > > > > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > > > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > > > > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > > > > > and requires bpf_sk_release(). > > > > > > > > > > > > > > [0]: > > > > > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > > > > > Call Trace: > > > > > > > dump_stack_lvl+0x5d/0x80 > > > > > > > print_report+0x170/0x4f3 > > > > > > > kasan_report+0xe1/0x180 > > > > > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > > > > > bpf_trampoline_6442564662+0x47/0xab > > > > > > > unix_shutdown+0x9/0x880 > > > > > > > __sys_shutdown+0xe1/0x160 > > > > > > > __x64_sys_shutdown+0x52/0x90 > > > > > > > do_syscall_64+0x6b/0x3a0 > > > > > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > > > > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > > > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > > > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > > > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > > > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > > > > > --- > > > > > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > > > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > > > > > 2 files changed, 43 insertions(+) > > > > > > > > > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > > > > index 3135643d5695..b328a1640c82 100644 > > > > > > > --- a/kernel/bpf/verifier.c > > > > > > > +++ b/kernel/bpf/verifier.c > > > > > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > > > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > > > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > > > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > > > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > > > > > > > > > /* > > > > > > > * Allow list few fields as RCU trusted or full trusted. > > > > > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > > > > > struct file *vm_file; > > > > > > > }; > > > > > > > > > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > > > > > + struct sock *peer; > > > > > > > +}; > > > > > > > + > > > > > > > > > > > > That's just one out of many. It's not really a fix, > > > > > > but a bandaid for one case. > > > > > > > > > > Right, this is only one example where a pointer lifetime > > > > > does not match with bpf prog. > > > > > > > > > > > We discussed it in the past and the only way forward is to make > > > > > > helpers only accept trusted args. > > > > > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > > > > > We should do the same for helpers. > > > > > > > > > > What about just reading an untrusted pointer ? > > > > > > > > What do you mean 'untrusted' ? > > > > There are 3 types of ptr_to_btf_id: > > > > trusted, untrusted, legacy (without either trusted or untrusted flags). > > > > > > Ah sorry, I used 'untrusted' since the pointer is not always > > > valid, but I think legacy is the one I meant in this case. > > > > > > > > > > > > > > kfuncs now accept only trusted, while helpers still accept > > > > trusted and legacy. The legacy should be disallowed. > > > > That might break some bpf programs, so it has to be done carefully. > > > > > > > > > I used bpf_skc_to_unix_sock() in selftest in case compiler > > > > > could optimise out branches that always return 0. > > > > > > > > > > Currently, this passes the verifier and can trigger UAF. > > > > > > > > > > u = bpf_skc_to_unix_sock(sock->sk); > > > > > if (!u || !u->peer) > > > > > return 0; > > > > > if (u->peer->__sk_common.skc_family) # unsafe access > > > > > return 0; > > > > > > > > No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem > > > > treatment. So above works and won't crash the kernel. > > > > It's effectively inlined probe_read_kernel. > > > > > > Yes, it doesn't crash. > > > > > > I was just unsure about the bpf expectation [0] like how we > > > should treat KASAN use-after-free report by bpf prog reading > > > a pointer whose lifetime is not guaranteed by bpf helper/verifier. > > > > > > So, if this is WAI, I'm fine with that. > > > > > > [0]: https://lore.kernel.org/all/CAAVpQUDrC1rO2diM3gVg5GV5CTVAUS2RbLP+SpHBGqKcUT0iMA@mail.gmail.com/ > > > > That's different. That's the actual UAF inside bpf_skc_to_unix_sock(). > > That needs to be fixed with what I described above by allowing > > only trusted pointers into helpers. > > I got this point. > > > In my earlier reply I meant that: > > if (u->peer->__sk_common.skc_family) # unsafe access > > is fine. It's safe access, because it's sanitized by the verifier/JIT. > > but I'm a bit confused here.. > > Even though the verifier makes sure the pointer is not NULL, > u->peer can be freed concurrently by another thread, > then how can verifier/JIT prevent UAF ? > > Or can this be still called 'safe access' regardless of runtime UAF > because the user-provided bpf prog was verified once and not in-tree > kernel code ? The verifier/JIT are not preventing UAF. They're preventing crashes. u->peer->__sk_common.skc_family is equivalent to two copy_from_kernel_nofault(). They may read garbage, but won't crash and won't cause any ill kernel effects. It's up to the program to use the values in a sane way. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer. 2026-02-11 22:39 ` Alexei Starovoitov @ 2026-02-11 23:01 ` Kuniyuki Iwashima 0 siblings, 0 replies; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-11 23:01 UTC (permalink / raw) To: Alexei Starovoitov Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, bpf, Network Development, Martin KaFai Lau On Wed, Feb 11, 2026 at 2:39 PM Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote: > > On Wed, Feb 11, 2026 at 2:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > On Wed, Feb 11, 2026 at 1:26 PM Alexei Starovoitov > > <alexei.starovoitov@gmail.com> wrote: > > > > > > On Tue, Feb 10, 2026 at 8:23 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > On Tue, Feb 10, 2026 at 6:47 PM Alexei Starovoitov > > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > > > On Mon, Feb 9, 2026 at 5:19 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > > > On Mon, Feb 9, 2026 at 3:00 PM Alexei Starovoitov > > > > > > <alexei.starovoitov@gmail.com> wrote: > > > > > > > > > > > > > > On Sat, Feb 7, 2026 at 3:07 PM Kuniyuki Iwashima <kuniyu@google.com> wrote: > > > > > > > > > > > > > > > > Michal Luczaj reported use-after-free of unix_sk(sk)->peer by > > > > > > > > bpf_skc_to_unix_sock(). [0] > > > > > > > > > > > > > > > > Accessing unix_sk(sk)->peer is safe only under unix_state_lock(), > > > > > > > > but there are many functions where bpf prog can access the field > > > > > > > > locklessly via fentry/fexit. > > > > > > > > > > > > > > > > unix_dgram_connect() could clear unix_sk(sk)->peer and release > > > > > > > > the last refcnt of the peer sk while a bpf prog is accessing it, > > > > > > > > resulting in use-after-free. > > > > > > > > > > > > > > > > Another problematic scenario is that unix_sk(sk)->peer could > > > > > > > > go away while being passed to bpf_setsockopt() in bpf iter. > > > > > > > > > > > > > > > > To avoid such issues, let's reject access to unix_sk(sk)->peer > > > > > > > > by marking the pointer with PTR_UNTRUSTED. > > > > > > > > > > > > > > > > If needed, we could add a new helper later that uses unix_peer_get() > > > > > > > > and requires bpf_sk_release(). > > > > > > > > > > > > > > > > [0]: > > > > > > > > BUG: KASAN: slab-use-after-free in bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > > > Read of size 2 at addr ffff888147d38890 by task test_progs/2495 > > > > > > > > Call Trace: > > > > > > > > dump_stack_lvl+0x5d/0x80 > > > > > > > > print_report+0x170/0x4f3 > > > > > > > > kasan_report+0xe1/0x180 > > > > > > > > bpf_skc_to_unix_sock+0xa4/0xb0 > > > > > > > > bpf_prog_564a1c39c35d86a2_unix_shutdown_entry+0x8a/0x8e > > > > > > > > bpf_trampoline_6442564662+0x47/0xab > > > > > > > > unix_shutdown+0x9/0x880 > > > > > > > > __sys_shutdown+0xe1/0x160 > > > > > > > > __x64_sys_shutdown+0x52/0x90 > > > > > > > > do_syscall_64+0x6b/0x3a0 > > > > > > > > entry_SYSCALL_64_after_hwframe+0x76/0x7e > > > > > > > > > > > > > > > > Fixes: 9eeb3aa33ae0 ("bpf: Add bpf_skc_to_unix_sock() helper") > > > > > > > > Reported-by: Michal Luczaj <mhal@rbox.co> > > > > > > > > Closes: https://lore.kernel.org/all/408569e7-2b82-4eff-b767-79ce6ef6cae0@rbox.co/ > > > > > > > > Suggested-by: Martin KaFai Lau <martin.lau@kernel.org> > > > > > > > > Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> > > > > > > > > --- > > > > > > > > kernel/bpf/verifier.c | 18 +++++++++++++ > > > > > > > > .../selftests/bpf/progs/verifier_sock.c | 25 +++++++++++++++++++ > > > > > > > > 2 files changed, 43 insertions(+) > > > > > > > > > > > > > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > > > > > > > index 3135643d5695..b328a1640c82 100644 > > > > > > > > --- a/kernel/bpf/verifier.c > > > > > > > > +++ b/kernel/bpf/verifier.c > > > > > > > > @@ -7076,6 +7076,7 @@ static int bpf_map_direct_read(struct bpf_map *map, int off, int size, u64 *val, > > > > > > > > #define BTF_TYPE_SAFE_RCU_OR_NULL(__type) __PASTE(__type, __safe_rcu_or_null) > > > > > > > > #define BTF_TYPE_SAFE_TRUSTED(__type) __PASTE(__type, __safe_trusted) > > > > > > > > #define BTF_TYPE_SAFE_TRUSTED_OR_NULL(__type) __PASTE(__type, __safe_trusted_or_null) > > > > > > > > +#define BTF_TYPE_SAFE_UNTRUSTED(__type) __PASTE(__type, __safe_untrusted) > > > > > > > > > > > > > > > > /* > > > > > > > > * Allow list few fields as RCU trusted or full trusted. > > > > > > > > @@ -7154,6 +7155,10 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { > > > > > > > > struct file *vm_file; > > > > > > > > }; > > > > > > > > > > > > > > > > +BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { > > > > > > > > + struct sock *peer; > > > > > > > > +}; > > > > > > > > + > > > > > > > > > > > > > > That's just one out of many. It's not really a fix, > > > > > > > but a bandaid for one case. > > > > > > > > > > > > Right, this is only one example where a pointer lifetime > > > > > > does not match with bpf prog. > > > > > > > > > > > > > We discussed it in the past and the only way forward is to make > > > > > > > helpers only accept trusted args. > > > > > > > Recently we made KF_TRUSTED_ARGS a default for all kfuncs. > > > > > > > We should do the same for helpers. > > > > > > > > > > > > What about just reading an untrusted pointer ? > > > > > > > > > > What do you mean 'untrusted' ? > > > > > There are 3 types of ptr_to_btf_id: > > > > > trusted, untrusted, legacy (without either trusted or untrusted flags). > > > > > > > > Ah sorry, I used 'untrusted' since the pointer is not always > > > > valid, but I think legacy is the one I meant in this case. > > > > > > > > > > > > > > > > > > kfuncs now accept only trusted, while helpers still accept > > > > > trusted and legacy. The legacy should be disallowed. > > > > > That might break some bpf programs, so it has to be done carefully. > > > > > > > > > > > I used bpf_skc_to_unix_sock() in selftest in case compiler > > > > > > could optimise out branches that always return 0. > > > > > > > > > > > > Currently, this passes the verifier and can trigger UAF. > > > > > > > > > > > > u = bpf_skc_to_unix_sock(sock->sk); > > > > > > if (!u || !u->peer) > > > > > > return 0; > > > > > > if (u->peer->__sk_common.skc_family) # unsafe access > > > > > > return 0; > > > > > > > > > > No. It's fine. Both legacy and untrusted ptr_to_btf_id get probe_mem > > > > > treatment. So above works and won't crash the kernel. > > > > > It's effectively inlined probe_read_kernel. > > > > > > > > Yes, it doesn't crash. > > > > > > > > I was just unsure about the bpf expectation [0] like how we > > > > should treat KASAN use-after-free report by bpf prog reading > > > > a pointer whose lifetime is not guaranteed by bpf helper/verifier. > > > > > > > > So, if this is WAI, I'm fine with that. > > > > > > > > [0]: https://lore.kernel.org/all/CAAVpQUDrC1rO2diM3gVg5GV5CTVAUS2RbLP+SpHBGqKcUT0iMA@mail.gmail.com/ > > > > > > That's different. That's the actual UAF inside bpf_skc_to_unix_sock(). > > > That needs to be fixed with what I described above by allowing > > > only trusted pointers into helpers. > > > > I got this point. > > > > > In my earlier reply I meant that: > > > if (u->peer->__sk_common.skc_family) # unsafe access > > > is fine. It's safe access, because it's sanitized by the verifier/JIT. > > > > but I'm a bit confused here.. > > > > Even though the verifier makes sure the pointer is not NULL, > > u->peer can be freed concurrently by another thread, > > then how can verifier/JIT prevent UAF ? > > > > Or can this be still called 'safe access' regardless of runtime UAF > > because the user-provided bpf prog was verified once and not in-tree > > kernel code ? > > The verifier/JIT are not preventing UAF. They're preventing crashes. > u->peer->__sk_common.skc_family is equivalent to two > copy_from_kernel_nofault(). They may read garbage, but won't crash > and won't cause any ill kernel effects. It's up to the program > to use the values in a sane way. I see, that's fair. Thanks for explaining ! ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v1 bpf 2/2] bpf: Reject access to unix_sk(sk)->listener. 2026-02-07 23:07 [PATCH v1 bpf 0/2] bpf: Reject access to unix_sk(sk)->{peer,listener} Kuniyuki Iwashima 2026-02-07 23:07 ` [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer Kuniyuki Iwashima @ 2026-02-07 23:07 ` Kuniyuki Iwashima 1 sibling, 0 replies; 11+ messages in thread From: Kuniyuki Iwashima @ 2026-02-07 23:07 UTC (permalink / raw) To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau Cc: John Fastabend, Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Michal Luczaj, Kuniyuki Iwashima, Kuniyuki Iwashima, bpf, netdev With the previous patch, bpf prog cannot access unix_sk(sk)->peer. struct unix_sock has two pointers to struct sock, and another pointer unix_sk(sk)->listener also has the same problem mentioned in the previous patch. unix_sk(sk)->listener is set by unix_stream_connect() and cleared by unix_update_edges() during accept(), and both are done under unix_state_lock(). There are some functions where unix_sk(sk)->peer is passed and bpf prog can access unix_sk(unix_sk(sk)->peer)->listener locklessly, which is unsafe. (e.g. unix_maybe_add_creds()) Let's reject bpf access to unix_sk(sk)->listener too. Fixes: aed6ecef55d7 ("af_unix: Save listener for embryo socket.") Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> --- kernel/bpf/verifier.c | 1 + .../selftests/bpf/progs/verifier_sock.c | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index b328a1640c82..2ffc6eff5584 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -7157,6 +7157,7 @@ BTF_TYPE_SAFE_TRUSTED_OR_NULL(struct vm_area_struct) { BTF_TYPE_SAFE_UNTRUSTED(struct unix_sock) { struct sock *peer; + struct sock *listener; }; static bool type_is_rcu(struct bpf_verifier_env *env, diff --git a/tools/testing/selftests/bpf/progs/verifier_sock.c b/tools/testing/selftests/bpf/progs/verifier_sock.c index 8de4d3ed98d4..730850e93d6d 100644 --- a/tools/testing/selftests/bpf/progs/verifier_sock.c +++ b/tools/testing/selftests/bpf/progs/verifier_sock.c @@ -1191,4 +1191,28 @@ int BPF_PROG(trace_unix_dgram_sendmsg, struct socket *sock, struct msghdr *msg, return 0; } +SEC("fentry/unix_maybe_add_creds") +__failure __msg("R1 type=untrusted_ptr_ expected=sock_common, sock, tcp_sock, xdp_sock, ptr_, trusted_ptr_") +int BPF_PROG(trace_unix_maybe_add_creds, struct sk_buff *skb, + const struct sock *sk, struct sock *other) +{ + struct unix_sock *u_other, *u_listener; + + if (!other) + return 0; + + u_other = bpf_skc_to_unix_sock(other); + if (!u_other) + return 0; + + /* unix_accept() could clear u_other->listener + * and the listener could be close()d. + */ + u_listener = bpf_skc_to_unix_sock(u_other->listener); + if (!u_listener) + return 0; + + return 0; +} + char _license[] SEC("license") = "GPL"; -- 2.53.0.rc2.204.g2597b5adb4-goog ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-02-11 23:01 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-07 23:07 [PATCH v1 bpf 0/2] bpf: Reject access to unix_sk(sk)->{peer,listener} Kuniyuki Iwashima
2026-02-07 23:07 ` [PATCH v1 bpf 1/2] bpf: Reject access to unix_sk(sk)->peer Kuniyuki Iwashima
2026-02-09 23:00 ` Alexei Starovoitov
2026-02-10 1:19 ` Kuniyuki Iwashima
2026-02-11 2:47 ` Alexei Starovoitov
2026-02-11 4:23 ` Kuniyuki Iwashima
2026-02-11 21:25 ` Alexei Starovoitov
2026-02-11 22:22 ` Kuniyuki Iwashima
2026-02-11 22:39 ` Alexei Starovoitov
2026-02-11 23:01 ` Kuniyuki Iwashima
2026-02-07 23:07 ` [PATCH v1 bpf 2/2] bpf: Reject access to unix_sk(sk)->listener Kuniyuki Iwashima
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox