+++ /dev/null
-From 4838980149184dc89c26fb7b43ca522a87881143 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 13 Jan 2022 09:28:46 +0900
-Subject: bpf: af_unix: Use batching algorithm in bpf unix iter.
-
-From: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-
-[ Upstream commit 855d8e77ffb05be6e54c34dababccb20318aec00 ]
-
-The commit 04c7820b776f ("bpf: tcp: Bpf iter batching and lock_sock")
-introduces the batching algorithm to iterate TCP sockets with more
-consistency.
-
-This patch uses the same algorithm to iterate AF_UNIX sockets.
-
-Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.co.jp>
-Link: https://lore.kernel.org/r/20220113002849.4384-3-kuniyu@amazon.co.jp
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Stable-dep-of: 4d328dd69538 ("bpf, sockmap: Fix af_unix iter deadlock")
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 184 +++++++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 177 insertions(+), 7 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index ea8fd8eb3ebc1..12a4c1542459c 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -3300,6 +3300,15 @@ static const struct seq_operations unix_seq_ops = {
- };
-
- #if IS_BUILTIN(CONFIG_UNIX) && defined(CONFIG_BPF_SYSCALL)
-+struct bpf_unix_iter_state {
-+ struct seq_net_private p;
-+ unsigned int cur_sk;
-+ unsigned int end_sk;
-+ unsigned int max_sk;
-+ struct sock **batch;
-+ bool st_bucket_done;
-+};
-+
- struct bpf_iter__unix {
- __bpf_md_ptr(struct bpf_iter_meta *, meta);
- __bpf_md_ptr(struct unix_sock *, unix_sk);
-@@ -3318,24 +3327,156 @@ static int unix_prog_seq_show(struct bpf_prog *prog, struct bpf_iter_meta *meta,
- return bpf_iter_run_prog(prog, &ctx);
- }
-
-+static int bpf_iter_unix_hold_batch(struct seq_file *seq, struct sock *start_sk)
-+
-+{
-+ struct bpf_unix_iter_state *iter = seq->private;
-+ unsigned int expected = 1;
-+ struct sock *sk;
-+
-+ sock_hold(start_sk);
-+ iter->batch[iter->end_sk++] = start_sk;
-+
-+ for (sk = sk_next(start_sk); sk; sk = sk_next(sk)) {
-+ if (sock_net(sk) != seq_file_net(seq))
-+ continue;
-+
-+ if (iter->end_sk < iter->max_sk) {
-+ sock_hold(sk);
-+ iter->batch[iter->end_sk++] = sk;
-+ }
-+
-+ expected++;
-+ }
-+
-+ spin_unlock(&unix_table_locks[start_sk->sk_hash]);
-+
-+ return expected;
-+}
-+
-+static void bpf_iter_unix_put_batch(struct bpf_unix_iter_state *iter)
-+{
-+ while (iter->cur_sk < iter->end_sk)
-+ sock_put(iter->batch[iter->cur_sk++]);
-+}
-+
-+static int bpf_iter_unix_realloc_batch(struct bpf_unix_iter_state *iter,
-+ unsigned int new_batch_sz)
-+{
-+ struct sock **new_batch;
-+
-+ new_batch = kvmalloc(sizeof(*new_batch) * new_batch_sz,
-+ GFP_USER | __GFP_NOWARN);
-+ if (!new_batch)
-+ return -ENOMEM;
-+
-+ bpf_iter_unix_put_batch(iter);
-+ kvfree(iter->batch);
-+ iter->batch = new_batch;
-+ iter->max_sk = new_batch_sz;
-+
-+ return 0;
-+}
-+
-+static struct sock *bpf_iter_unix_batch(struct seq_file *seq,
-+ loff_t *pos)
-+{
-+ struct bpf_unix_iter_state *iter = seq->private;
-+ unsigned int expected;
-+ bool resized = false;
-+ struct sock *sk;
-+
-+ if (iter->st_bucket_done)
-+ *pos = set_bucket_offset(get_bucket(*pos) + 1, 1);
-+
-+again:
-+ /* Get a new batch */
-+ iter->cur_sk = 0;
-+ iter->end_sk = 0;
-+
-+ sk = unix_get_first(seq, pos);
-+ if (!sk)
-+ return NULL; /* Done */
-+
-+ expected = bpf_iter_unix_hold_batch(seq, sk);
-+
-+ if (iter->end_sk == expected) {
-+ iter->st_bucket_done = true;
-+ return sk;
-+ }
-+
-+ if (!resized && !bpf_iter_unix_realloc_batch(iter, expected * 3 / 2)) {
-+ resized = true;
-+ goto again;
-+ }
-+
-+ return sk;
-+}
-+
-+static void *bpf_iter_unix_seq_start(struct seq_file *seq, loff_t *pos)
-+{
-+ if (!*pos)
-+ return SEQ_START_TOKEN;
-+
-+ /* bpf iter does not support lseek, so it always
-+ * continue from where it was stop()-ped.
-+ */
-+ return bpf_iter_unix_batch(seq, pos);
-+}
-+
-+static void *bpf_iter_unix_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-+{
-+ struct bpf_unix_iter_state *iter = seq->private;
-+ struct sock *sk;
-+
-+ /* Whenever seq_next() is called, the iter->cur_sk is
-+ * done with seq_show(), so advance to the next sk in
-+ * the batch.
-+ */
-+ if (iter->cur_sk < iter->end_sk)
-+ sock_put(iter->batch[iter->cur_sk++]);
-+
-+ ++*pos;
-+
-+ if (iter->cur_sk < iter->end_sk)
-+ sk = iter->batch[iter->cur_sk];
-+ else
-+ sk = bpf_iter_unix_batch(seq, pos);
-+
-+ return sk;
-+}
-+
- static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
- {
- struct bpf_iter_meta meta;
- struct bpf_prog *prog;
- struct sock *sk = v;
- uid_t uid;
-+ bool slow;
-+ int ret;
-
- if (v == SEQ_START_TOKEN)
- return 0;
-
-+ slow = lock_sock_fast(sk);
-+
-+ if (unlikely(sk_unhashed(sk))) {
-+ ret = SEQ_SKIP;
-+ goto unlock;
-+ }
-+
- uid = from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk));
- meta.seq = seq;
- prog = bpf_iter_get_info(&meta, false);
-- return unix_prog_seq_show(prog, &meta, v, uid);
-+ ret = unix_prog_seq_show(prog, &meta, v, uid);
-+unlock:
-+ unlock_sock_fast(sk, slow);
-+ return ret;
- }
-
- static void bpf_iter_unix_seq_stop(struct seq_file *seq, void *v)
- {
-+ struct bpf_unix_iter_state *iter = seq->private;
- struct bpf_iter_meta meta;
- struct bpf_prog *prog;
-
-@@ -3346,12 +3487,13 @@ static void bpf_iter_unix_seq_stop(struct seq_file *seq, void *v)
- (void)unix_prog_seq_show(prog, &meta, v, 0);
- }
-
-- unix_seq_stop(seq, v);
-+ if (iter->cur_sk < iter->end_sk)
-+ bpf_iter_unix_put_batch(iter);
- }
-
- static const struct seq_operations bpf_iter_unix_seq_ops = {
-- .start = unix_seq_start,
-- .next = unix_seq_next,
-+ .start = bpf_iter_unix_seq_start,
-+ .next = bpf_iter_unix_seq_next,
- .stop = bpf_iter_unix_seq_stop,
- .show = bpf_iter_unix_seq_show,
- };
-@@ -3400,11 +3542,39 @@ static struct pernet_operations unix_net_ops = {
- DEFINE_BPF_ITER_FUNC(unix, struct bpf_iter_meta *meta,
- struct unix_sock *unix_sk, uid_t uid)
-
-+#define INIT_BATCH_SZ 16
-+
-+static int bpf_iter_init_unix(void *priv_data, struct bpf_iter_aux_info *aux)
-+{
-+ struct bpf_unix_iter_state *iter = priv_data;
-+ int err;
-+
-+ err = bpf_iter_init_seq_net(priv_data, aux);
-+ if (err)
-+ return err;
-+
-+ err = bpf_iter_unix_realloc_batch(iter, INIT_BATCH_SZ);
-+ if (err) {
-+ bpf_iter_fini_seq_net(priv_data);
-+ return err;
-+ }
-+
-+ return 0;
-+}
-+
-+static void bpf_iter_fini_unix(void *priv_data)
-+{
-+ struct bpf_unix_iter_state *iter = priv_data;
-+
-+ bpf_iter_fini_seq_net(priv_data);
-+ kvfree(iter->batch);
-+}
-+
- static const struct bpf_iter_seq_info unix_seq_info = {
- .seq_ops = &bpf_iter_unix_seq_ops,
-- .init_seq_private = bpf_iter_init_seq_net,
-- .fini_seq_private = bpf_iter_fini_seq_net,
-- .seq_priv_size = sizeof(struct seq_net_private),
-+ .init_seq_private = bpf_iter_init_unix,
-+ .fini_seq_private = bpf_iter_fini_unix,
-+ .seq_priv_size = sizeof(struct bpf_unix_iter_state),
- };
-
- static struct bpf_iter_reg unix_reg_info = {
---
-2.53.0
-
+++ /dev/null
-From 5c408c21d8be97c1a4ae88c010367b8623504665 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 16 Apr 2026 20:01:41 +0800
-Subject: bpf: allow UTF-8 literals in bpf_bprintf_prepare()
-
-From: Yihan Ding <dingyihan@uniontech.com>
-
-[ Upstream commit b960430ea8862ef37ce53c8bf74a8dc79d3f2404 ]
-
-bpf_bprintf_prepare() only needs ASCII parsing for conversion
-specifiers. Plain text can safely carry bytes >= 0x80, so allow
-UTF-8 literals outside '%' sequences while keeping ASCII control
-bytes rejected and format specifiers ASCII-only.
-
-This keeps existing parsing rules for format directives unchanged,
-while allowing helpers such as bpf_trace_printk() to emit UTF-8
-literal text.
-
-Update test_snprintf_negative() in the same commit so selftests keep
-matching the new plain-text vs format-specifier split during bisection.
-
-Fixes: 48cac3f4a96d ("bpf: Implement formatted output helpers with bstr_printf")
-Signed-off-by: Yihan Ding <dingyihan@uniontech.com>
-Acked-by: Paul Chaignon <paul.chaignon@gmail.com>
-Link: https://lore.kernel.org/r/20260416120142.1420646-2-dingyihan@uniontech.com
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- kernel/bpf/helpers.c | 17 ++++++++++++++++-
- .../testing/selftests/bpf/prog_tests/snprintf.c | 3 ++-
- 2 files changed, 18 insertions(+), 2 deletions(-)
-
-diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
-index b40ca025d9a44..b4abe6aefef4c 100644
---- a/kernel/bpf/helpers.c
-+++ b/kernel/bpf/helpers.c
-@@ -796,7 +796,13 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
- data->buf = buffers->buf;
-
- for (i = 0; i < fmt_size; i++) {
-- if ((!isprint(fmt[i]) && !isspace(fmt[i])) || !isascii(fmt[i])) {
-+ unsigned char c = fmt[i];
-+
-+ /*
-+ * Permit bytes >= 0x80 in plain text so UTF-8 literals can pass
-+ * through unchanged, while still rejecting ASCII control bytes.
-+ */
-+ if (isascii(c) && !isprint(c) && !isspace(c)) {
- err = -EINVAL;
- goto out;
- }
-@@ -818,6 +824,15 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
- * always access fmt[i + 1], in the worst case it will be a 0
- */
- i++;
-+ c = fmt[i];
-+ /*
-+ * The format parser below only understands ASCII conversion
-+ * specifiers and modifiers, so reject non-ASCII after '%'.
-+ */
-+ if (!isascii(c)) {
-+ err = -EINVAL;
-+ goto out;
-+ }
-
- /* skip optional "[0 +-][num]" width formatting field */
- while (fmt[i] == '0' || fmt[i] == '+' || fmt[i] == '-' ||
-diff --git a/tools/testing/selftests/bpf/prog_tests/snprintf.c b/tools/testing/selftests/bpf/prog_tests/snprintf.c
-index 8fd1b4b29a0e0..14419b9407281 100644
---- a/tools/testing/selftests/bpf/prog_tests/snprintf.c
-+++ b/tools/testing/selftests/bpf/prog_tests/snprintf.c
-@@ -116,7 +116,8 @@ void test_snprintf_negative(void)
- ASSERT_ERR(load_single_snprintf("%--------"), "invalid specifier 5");
- ASSERT_ERR(load_single_snprintf("%lc"), "invalid specifier 6");
- ASSERT_ERR(load_single_snprintf("%llc"), "invalid specifier 7");
-- ASSERT_ERR(load_single_snprintf("\x80"), "non ascii character");
-+ ASSERT_OK(load_single_snprintf("\x80"), "non ascii plain text");
-+ ASSERT_ERR(load_single_snprintf("%\x80"), "non ascii in specifier");
- ASSERT_ERR(load_single_snprintf("\x1"), "non printable character");
- }
-
---
-2.53.0
-
+++ /dev/null
-From 84dbf85f177c93739e33ca63d4f62e4bad2ea68d Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Fri, 17 Apr 2026 07:33:52 -0700
-Subject: bpf, arm32: Reject BPF-to-BPF calls and callbacks in the JIT
-
-From: Puranjay Mohan <puranjay@kernel.org>
-
-[ Upstream commit e1d486445af3c392628532229f7ce5f5cf7891b6 ]
-
-The ARM32 BPF JIT does not support BPF-to-BPF function calls
-(BPF_PSEUDO_CALL) or callbacks (BPF_PSEUDO_FUNC), but it does
-not reject them either.
-
-When a program with subprograms is loaded (e.g. libxdp's XDP
-dispatcher uses __noinline__ subprograms, or any program using
-callbacks like bpf_loop or bpf_for_each_map_elem), the verifier
-invokes bpf_jit_subprogs() which calls bpf_int_jit_compile()
-for each subprogram.
-
-For BPF_PSEUDO_CALL, since ARM32 does not reject it, the JIT
-silently emits code using the wrong address computation:
-
- func = __bpf_call_base + imm
-
-where imm is a pc-relative subprogram offset, producing a bogus
-function pointer.
-
-For BPF_PSEUDO_FUNC, the ldimm64 handler ignores src_reg and
-loads the immediate as a normal 64-bit value without error.
-
-In both cases, build_body() reports success and a JIT image is
-allocated. ARM32 lacks the jit_data/extra_pass mechanism needed
-for the second JIT pass in bpf_jit_subprogs(). On the second
-pass, bpf_int_jit_compile() performs a full fresh compilation,
-allocating a new JIT binary and overwriting prog->bpf_func. The
-first allocation is never freed. bpf_jit_subprogs() then detects
-the function pointer changed and aborts with -ENOTSUPP, but the
-original JIT binary has already been leaked. Each program
-load/unload cycle leaks one JIT binary allocation, as reported
-by kmemleak:
-
- unreferenced object 0xbf0a1000 (size 4096):
- backtrace:
- bpf_jit_binary_alloc+0x64/0xfc
- bpf_int_jit_compile+0x14c/0x348
- bpf_jit_subprogs+0x4fc/0xa60
-
-Fix this by rejecting both BPF_PSEUDO_CALL in the BPF_CALL
-handler and BPF_PSEUDO_FUNC in the BPF_LD_IMM64 handler, falling
-through to the existing 'notyet' path. This causes build_body()
-to fail before any JIT binary is allocated, so
-bpf_int_jit_compile() returns the original program unjitted.
-bpf_jit_subprogs() then sees !prog->jited and cleanly falls
-back to the interpreter with no leak.
-
-Acked-by: Daniel Borkmann <daniel@iogearbox.net>
-Fixes: 1c2a088a6626 ("bpf: x64: add JIT support for multi-function programs")
-Reported-by: Jonas Rebmann <jre@pengutronix.de>
-Closes: https://lore.kernel.org/bpf/b63e9174-7a3d-4e22-8294-16df07a4af89@pengutronix.de
-Tested-by: Jonas Rebmann <jre@pengutronix.de>
-Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
-Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
-Link: https://lore.kernel.org/r/20260417143353.838911-1-puranjay@kernel.org
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- arch/arm/net/bpf_jit_32.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
-index a903b26cde409..4fd6dd29e3286 100644
---- a/arch/arm/net/bpf_jit_32.c
-+++ b/arch/arm/net/bpf_jit_32.c
-@@ -1609,6 +1609,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
- {
- u64 val = (u32)imm | (u64)insn[1].imm << 32;
-
-+ if (insn->src_reg == BPF_PSEUDO_FUNC)
-+ goto notyet;
-+
- emit_a32_mov_i64(dst, val, ctx);
-
- return 1;
-@@ -1800,6 +1803,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
- const s8 *r5 = bpf2a32[BPF_REG_5];
- const u32 func = (u32)__bpf_call_base + (u32)imm;
-
-+ if (insn->src_reg == BPF_PSEUDO_CALL)
-+ goto notyet;
-+
- emit_a32_mov_r64(true, r0, r1, ctx);
- emit_a32_mov_r64(true, r1, r2, ctx);
- emit_push_r64(r5, ctx);
---
-2.53.0
-
+++ /dev/null
-From d425f706928ecfb9aff1b9453bac44f07e26ebb6 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Thu, 16 Apr 2026 14:27:19 +0200
-Subject: bpf: Fix precedence bug in convert_bpf_ld_abs alignment check
-
-From: Daniel Borkmann <daniel@iogearbox.net>
-
-[ Upstream commit e5f635edd393aeaa7cad9e42831d397e6e2e1eed ]
-
-Fix an operator precedence issue in convert_bpf_ld_abs() where the
-expression offset + ip_align % size evaluates as offset + (ip_align % size)
-due to % having higher precedence than +. That latter evaluation does
-not make any sense. The intended check is (offset + ip_align) % size == 0
-to verify that the packet load offset is properly aligned for direct
-access.
-
-With NET_IP_ALIGN == 2, the bug causes the inline fast-path for direct
-packet loads to almost never be taken on !CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
-platforms. This forces nearly all cBPF BPF_LD_ABS packet loads through
-the bpf_skb_load_helper slow path on the affected archs.
-
-Fixes: e0cea7ce988c ("bpf: implement ld_abs/ld_ind in native bpf")
-Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
-Link: https://lore.kernel.org/r/20260416122719.661033-1-daniel@iogearbox.net
-Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/core/filter.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/net/core/filter.c b/net/core/filter.c
-index 87447a7843b5a..3cab7f83fa661 100644
---- a/net/core/filter.c
-+++ b/net/core/filter.c
-@@ -490,7 +490,7 @@ static bool convert_bpf_ld_abs(struct sock_filter *fp, struct bpf_insn **insnp)
- ((unaligned_ok && offset >= 0) ||
- (!unaligned_ok && offset >= 0 &&
- offset + ip_align >= 0 &&
-- offset + ip_align % size == 0))) {
-+ (offset + ip_align) % size == 0))) {
- bool ldx_off_ok = offset <= S16_MAX;
-
- *insn++ = BPF_MOV64_REG(BPF_REG_TMP, BPF_REG_H);
---
-2.53.0
-
+++ /dev/null
-From db102ee067218fe45cfd2c1f5c23c663cccc73d9 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 14 Apr 2026 16:13:16 +0200
-Subject: bpf, sockmap: Fix af_unix iter deadlock
-
-From: Michal Luczaj <mhal@rbox.co>
-
-[ Upstream commit 4d328dd695383224aa750ddee6b4ad40c0f8d205 ]
-
-bpf_iter_unix_seq_show() may deadlock when lock_sock_fast() takes the fast
-path and the iter prog attempts to update a sockmap. Which ends up spinning
-at sock_map_update_elem()'s bh_lock_sock():
-
-WARNING: possible recursive locking detected
-test_progs/1393 is trying to acquire lock:
-ffff88811ec25f58 (slock-AF_UNIX){+...}-{3:3}, at: sock_map_update_elem+0xdb/0x1f0
-
-but task is already holding lock:
-ffff88811ec25f58 (slock-AF_UNIX){+...}-{3:3}, at: __lock_sock_fast+0x37/0xe0
-
-other info that might help us debug this:
- Possible unsafe locking scenario:
-
- CPU0
- ----
- lock(slock-AF_UNIX);
- lock(slock-AF_UNIX);
-
- *** DEADLOCK ***
-
- May be due to missing lock nesting notation
-
-4 locks held by test_progs/1393:
- #0: ffff88814b59c790 (&p->lock){+.+.}-{4:4}, at: bpf_seq_read+0x59/0x10d0
- #1: ffff88811ec25fd8 (sk_lock-AF_UNIX){+.+.}-{0:0}, at: bpf_seq_read+0x42c/0x10d0
- #2: ffff88811ec25f58 (slock-AF_UNIX){+...}-{3:3}, at: __lock_sock_fast+0x37/0xe0
- #3: ffffffff85a6a7c0 (rcu_read_lock){....}-{1:3}, at: bpf_iter_run_prog+0x51d/0xb00
-
-Call Trace:
- dump_stack_lvl+0x5d/0x80
- print_deadlock_bug.cold+0xc0/0xce
- __lock_acquire+0x130f/0x2590
- lock_acquire+0x14e/0x2b0
- _raw_spin_lock+0x30/0x40
- sock_map_update_elem+0xdb/0x1f0
- bpf_prog_2d0075e5d9b721cd_dump_unix+0x55/0x4f4
- bpf_iter_run_prog+0x5b9/0xb00
- bpf_iter_unix_seq_show+0x1f7/0x2e0
- bpf_seq_read+0x42c/0x10d0
- vfs_read+0x171/0xb20
- ksys_read+0xff/0x200
- do_syscall_64+0x6b/0x3a0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Fixes: 2c860a43dd77 ("bpf: af_unix: Implement BPF iterator for UNIX domain socket.")
-Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
-Suggested-by: Martin KaFai Lau <martin.lau@linux.dev>
-Signed-off-by: Michal Luczaj <mhal@rbox.co>
-Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
-Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>
-Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
-Link: https://patch.msgid.link/20260414-unix-proto-update-null-ptr-deref-v4-2-2af6fe97918e@rbox.co
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 7 +++----
- 1 file changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 12a4c1542459c..8584dc9592e05 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -3452,15 +3452,14 @@ static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
- struct bpf_prog *prog;
- struct sock *sk = v;
- uid_t uid;
-- bool slow;
- int ret;
-
- if (v == SEQ_START_TOKEN)
- return 0;
-
-- slow = lock_sock_fast(sk);
-+ lock_sock(sk);
-
-- if (unlikely(sk_unhashed(sk))) {
-+ if (unlikely(sock_flag(sk, SOCK_DEAD))) {
- ret = SEQ_SKIP;
- goto unlock;
- }
-@@ -3470,7 +3469,7 @@ static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
- prog = bpf_iter_get_info(&meta, false);
- ret = unix_prog_seq_show(prog, &meta, v, uid);
- unlock:
-- unlock_sock_fast(sk, slow);
-+ release_sock(sk);
- return ret;
- }
-
---
-2.53.0
-
+++ /dev/null
-From 87cdacf5177c6bde01797eaa0e08497b45904076 Mon Sep 17 00:00:00 2001
-From: Sasha Levin <sashal@kernel.org>
-Date: Tue, 14 Apr 2026 16:13:19 +0200
-Subject: bpf, sockmap: Take state lock for af_unix iter
-
-From: Michal Luczaj <mhal@rbox.co>
-
-[ Upstream commit 64c2f93fc3254d3bf5de4445fb732ee5c451edb6 ]
-
-When a BPF iterator program updates a sockmap, there is a race condition in
-unix_stream_bpf_update_proto() where the `peer` pointer can become stale[1]
-during a state transition TCP_ESTABLISHED -> TCP_CLOSE.
-
- CPU0 bpf CPU1 close
- -------- ----------
-// unix_stream_bpf_update_proto()
-sk_pair = unix_peer(sk)
-if (unlikely(!sk_pair))
- return -EINVAL;
- // unix_release_sock()
- skpair = unix_peer(sk);
- unix_peer(sk) = NULL;
- sock_put(skpair)
-sock_hold(sk_pair) // UaF
-
-More practically, this fix guarantees that the iterator program is
-consistently provided with a unix socket that remains stable during
-iterator execution.
-
-[1]:
-BUG: KASAN: slab-use-after-free in unix_stream_bpf_update_proto+0x155/0x490
-Write of size 4 at addr ffff8881178c9a00 by task test_progs/2231
-Call Trace:
- dump_stack_lvl+0x5d/0x80
- print_report+0x170/0x4f3
- kasan_report+0xe4/0x1c0
- kasan_check_range+0x125/0x200
- unix_stream_bpf_update_proto+0x155/0x490
- sock_map_link+0x71c/0xec0
- sock_map_update_common+0xbc/0x600
- sock_map_update_elem+0x19a/0x1f0
- bpf_prog_bbbf56096cdd4f01_selective_dump_unix+0x20c/0x217
- bpf_iter_run_prog+0x21e/0xae0
- bpf_iter_unix_seq_show+0x1e0/0x2a0
- bpf_seq_read+0x42c/0x10d0
- vfs_read+0x171/0xb20
- ksys_read+0xff/0x200
- do_syscall_64+0xf7/0x5e0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Allocated by task 2236:
- kasan_save_stack+0x30/0x50
- kasan_save_track+0x14/0x30
- __kasan_slab_alloc+0x63/0x80
- kmem_cache_alloc_noprof+0x1d5/0x680
- sk_prot_alloc+0x59/0x210
- sk_alloc+0x34/0x470
- unix_create1+0x86/0x8a0
- unix_stream_connect+0x318/0x15b0
- __sys_connect+0xfd/0x130
- __x64_sys_connect+0x72/0xd0
- do_syscall_64+0xf7/0x5e0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Freed by task 2236:
- kasan_save_stack+0x30/0x50
- kasan_save_track+0x14/0x30
- kasan_save_free_info+0x3b/0x70
- __kasan_slab_free+0x47/0x70
- kmem_cache_free+0x11c/0x590
- __sk_destruct+0x432/0x6e0
- unix_release_sock+0x9b3/0xf60
- unix_release+0x8a/0xf0
- __sock_release+0xb0/0x270
- sock_close+0x18/0x20
- __fput+0x36e/0xac0
- fput_close_sync+0xe5/0x1a0
- __x64_sys_close+0x7d/0xd0
- do_syscall_64+0xf7/0x5e0
- entry_SYSCALL_64_after_hwframe+0x76/0x7e
-
-Fixes: 2c860a43dd77 ("bpf: af_unix: Implement BPF iterator for UNIX domain socket.")
-Suggested-by: Kuniyuki Iwashima <kuniyu@google.com>
-Signed-off-by: Michal Luczaj <mhal@rbox.co>
-Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
-Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
-Link: https://patch.msgid.link/20260414-unix-proto-update-null-ptr-deref-v4-5-2af6fe97918e@rbox.co
-Signed-off-by: Sasha Levin <sashal@kernel.org>
----
- net/unix/af_unix.c | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
-index 8584dc9592e05..a2a19c31ebddd 100644
---- a/net/unix/af_unix.c
-+++ b/net/unix/af_unix.c
-@@ -3458,6 +3458,7 @@ static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
- return 0;
-
- lock_sock(sk);
-+ unix_state_lock(sk);
-
- if (unlikely(sock_flag(sk, SOCK_DEAD))) {
- ret = SEQ_SKIP;
-@@ -3469,6 +3470,7 @@ static int bpf_iter_unix_seq_show(struct seq_file *seq, void *v)
- prog = bpf_iter_get_info(&meta, false);
- ret = unix_prog_seq_show(prog, &meta, v, uid);
- unlock:
-+ unix_state_unlock(sk);
- release_sock(sk);
- return ret;
- }
---
-2.53.0
-
mtd-parsers-ofpart-call-of_node_get-for-dedicated-su.patch
mtd-rawnand-sunxi-fix-sunxi_nfc_hw_ecc_read_extra_oo.patch
hid-usbhid-fix-deadlock-in-hid_post_reset.patch
-bpf-af_unix-use-batching-algorithm-in-bpf-unix-iter.patch
-bpf-sockmap-fix-af_unix-iter-deadlock.patch
-bpf-sockmap-take-state-lock-for-af_unix-iter.patch
-bpf-fix-precedence-bug-in-convert_bpf_ld_abs-alignme.patch
-bpf-allow-utf-8-literals-in-bpf_bprintf_prepare.patch
-bpf-arm32-reject-bpf-to-bpf-calls-and-callbacks-in-t.patch
pinctrl-pinctrl-pic32-fix-resource-leak.patch
perf-branch-avoid-incrementing-null.patch
perf-tools-cs-etm-fix-print-issue-for-coresight-debu.patch