[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20251013171122.1403859-1-listout@listout.xyz>
Date: Mon, 13 Oct 2025 22:41:22 +0530
From: Brahmajit Das <listout@...tout.xyz>
To: syzbot+1f1fbecb9413cdbfbef8@...kaller.appspotmail.com
Cc: listout@...tout.xyz,
andrii@...nel.org,
ast@...nel.org,
bpf@...r.kernel.org,
daniel@...earbox.net,
davem@...emloft.net,
eddyz87@...il.com,
edumazet@...gle.com,
haoluo@...gle.com,
horms@...nel.org,
john.fastabend@...il.com,
jolsa@...nel.org,
kpsingh@...nel.org,
kuba@...nel.org,
linux-kernel@...r.kernel.org,
martin.lau@...ux.dev,
netdev@...r.kernel.org,
pabeni@...hat.com,
sdf@...ichev.me,
song@...nel.org,
syzkaller-bugs@...glegroups.com,
yonghong.song@...ux.dev,
Menglong Dong <menglong.dong@...ux.dev>,
Sahil Chandna <chandna.linuxkernel@...il.com>
Subject: [PATCH v2] bpf: avoid sleeping in invalid context during sock_map_delete_elem path
The syzkaller report exposed a BUG: “sleeping function called from
invalid context” in sock_map_delete_elem, which happens when
`bpf_test_timer_enter()` disables preemption but the delete path later
invokes a sleeping function while still in that context. Specifically:
- The crash trace shows `bpf_test_timer_enter()` acquiring a
preempt_disable path (via t->mode == NO_PREEMPT), but the symmetric
release path always calls migrate_enable(), mismatching the earlier
disable.
- As a result, preemption remains disabled across the
sock_map_delete_elem path, leading to a sleeping call under an invalid
context. :contentReference[oaicite:0]{index=0}
To fix this, normalize the disable/enable pairing: always use
migrate_disable()/migrate_enable() regardless of t->mode. This ensures
that we never remain with preemption disabled unintentionally when
entering the delete path, and avoids invalid-context sleeping.
Reported-by: syzbot+1f1fbecb9413cdbfbef8@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=1f1fbecb9413cdbfbef8
Suggested-by: Yonghong Song <yonghong.song@...ux.dev>
Suggested-by: Menglong Dong <menglong.dong@...ux.dev>
Co-authored-by: Sahil Chandna <chandna.linuxkernel@...il.com>
Signed-off-by: Brahmajit Das <listout@...tout.xyz>
---
Changes in v2:
- remove enum { NO_PREEMPT, NO_MIGRATE } mode
- Using rcu_read_lock_dont_migrate/rcu_read_unlock_migrate
Changes in v1:
- Changes on top of Sahil's initial work based on feedback from
Yonghong's. i.e. remove NO_PREEMPT/NO_MIGRATE in test_run.c and use
migrate_disable()/migrate_enable() universally.
Link: https://lore.kernel.org/all/d0fdced7-a9a5-473e-991f-4f5e4c13f616@linux.dev/
Please also find Sahil's v2 patch:
Link: https://lore.kernel.org/all/20251010075923.408195-1-chandna.linuxkernel@gmail.com/T/
---
net/bpf/test_run.c | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index dfb03ee0bb62..83f97ee34419 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -29,7 +29,6 @@
#include <trace/events/bpf_test_run.h>
struct bpf_test_timer {
- enum { NO_PREEMPT, NO_MIGRATE } mode;
u32 i;
u64 time_start, time_spent;
};
@@ -37,11 +36,7 @@ struct bpf_test_timer {
static void bpf_test_timer_enter(struct bpf_test_timer *t)
__acquires(rcu)
{
- rcu_read_lock();
- if (t->mode == NO_PREEMPT)
- preempt_disable();
- else
- migrate_disable();
+ rcu_read_lock_dont_migrate();
t->time_start = ktime_get_ns();
}
@@ -51,11 +46,7 @@ static void bpf_test_timer_leave(struct bpf_test_timer *t)
{
t->time_start = 0;
- if (t->mode == NO_PREEMPT)
- preempt_enable();
- else
- migrate_enable();
- rcu_read_unlock();
+ rcu_read_unlock_migrate();
}
static bool bpf_test_timer_continue(struct bpf_test_timer *t, int iterations,
@@ -374,7 +365,7 @@ static int bpf_test_run_xdp_live(struct bpf_prog *prog, struct xdp_buff *ctx,
{
struct xdp_test_data xdp = { .batch_size = batch_size };
- struct bpf_test_timer t = { .mode = NO_MIGRATE };
+ struct bpf_test_timer t = {};
int ret;
if (!repeat)
@@ -404,7 +395,7 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
struct bpf_prog_array_item item = {.prog = prog};
struct bpf_run_ctx *old_ctx;
struct bpf_cg_run_ctx run_ctx;
- struct bpf_test_timer t = { NO_MIGRATE };
+ struct bpf_test_timer t = {};
enum bpf_cgroup_storage_type stype;
int ret;
@@ -1377,7 +1368,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
const union bpf_attr *kattr,
union bpf_attr __user *uattr)
{
- struct bpf_test_timer t = { NO_PREEMPT };
+ struct bpf_test_timer t = {};
u32 size = kattr->test.data_size_in;
struct bpf_flow_dissector ctx = {};
u32 repeat = kattr->test.repeat;
@@ -1445,7 +1436,7 @@ int bpf_prog_test_run_flow_dissector(struct bpf_prog *prog,
int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kattr,
union bpf_attr __user *uattr)
{
- struct bpf_test_timer t = { NO_PREEMPT };
+ struct bpf_test_timer t = {};
struct bpf_prog_array *progs = NULL;
struct bpf_sk_lookup_kern ctx = {};
u32 repeat = kattr->test.repeat;
--
2.51.0
Powered by blists - more mailing lists