]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
netdevsim: fix a race issue related to the operation on bpf_bound_progs list
authorYun Lu <luyun@kylinos.cn>
Fri, 16 Jan 2026 09:53:08 +0000 (17:53 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 20 Jan 2026 16:18:52 +0000 (17:18 +0100)
The netdevsim driver lacks a protection mechanism for operations on the
bpf_bound_progs list. When the nsim_bpf_create_prog() performs
list_add_tail, it is possible that nsim_bpf_destroy_prog() is
simultaneously performs list_del. Concurrent operations on the list may
lead to list corruption and trigger a kernel crash as follows:

[  417.290971] kernel BUG at lib/list_debug.c:62!
[  417.290983] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
[  417.290992] CPU: 10 PID: 168 Comm: kworker/10:1 Kdump: loaded Not tainted 6.19.0-rc5 #1
[  417.291003] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[  417.291007] Workqueue: events bpf_prog_free_deferred
[  417.291021] RIP: 0010:__list_del_entry_valid_or_report+0xa7/0xc0
[  417.291034] Code: a8 ff 0f 0b 48 89 fe 48 89 ca 48 c7 c7 48 a1 eb ae e8 ed fb a8 ff 0f 0b 48 89 fe 48 89 c2 48 c7 c7 80 a1 eb ae e8 d9 fb a8 ff <0f> 0b 48 89 d1 48 c7 c7 d0 a1 eb ae 48 89 f2 48 89 c6 e8 c2 fb a8
[  417.291040] RSP: 0018:ffffb16a40807df8 EFLAGS: 00010246
[  417.291046] RAX: 000000000000006d RBX: ffff8e589866f500 RCX: 0000000000000000
[  417.291051] RDX: 0000000000000000 RSI: ffff8e59f7b23180 RDI: ffff8e59f7b23180
[  417.291055] RBP: ffffb16a412c9000 R08: 0000000000000000 R09: 0000000000000003
[  417.291059] R10: ffffb16a40807c80 R11: ffffffffaf9edce8 R12: ffff8e594427ac20
[  417.291063] R13: ffff8e59f7b44780 R14: ffff8e58800b7a05 R15: 0000000000000000
[  417.291074] FS:  0000000000000000(0000) GS:ffff8e59f7b00000(0000) knlGS:0000000000000000
[  417.291079] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  417.291083] CR2: 00007fc4083efe08 CR3: 00000001c3626006 CR4: 0000000000770ee0
[  417.291088] PKRU: 55555554
[  417.291091] Call Trace:
[  417.291096]  <TASK>
[  417.291103]  nsim_bpf_destroy_prog+0x31/0x80 [netdevsim]
[  417.291154]  __bpf_prog_offload_destroy+0x2a/0x80
[  417.291163]  bpf_prog_dev_bound_destroy+0x6f/0xb0
[  417.291171]  bpf_prog_free_deferred+0x18e/0x1a0
[  417.291178]  process_one_work+0x18a/0x3a0
[  417.291188]  worker_thread+0x27b/0x3a0
[  417.291197]  ? __pfx_worker_thread+0x10/0x10
[  417.291207]  kthread+0xe5/0x120
[  417.291214]  ? __pfx_kthread+0x10/0x10
[  417.291221]  ret_from_fork+0x31/0x50
[  417.291230]  ? __pfx_kthread+0x10/0x10
[  417.291236]  ret_from_fork_asm+0x1a/0x30
[  417.291246]  </TASK>

Add a mutex lock, to prevent simultaneous addition and deletion operations
on the list.

Fixes: 31d3ad832948 ("netdevsim: add bpf offload support")
Reported-by: Yinhao Hu <dddddd@hust.edu.cn>
Reported-by: Kaiyan Mei <M202472210@hust.edu.cn>
Signed-off-by: Yun Lu <luyun@kylinos.cn>
Link: https://patch.msgid.link/20260116095308.11441-1-luyun_611@163.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/netdevsim/bpf.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/netdevsim.h

index 49537d3c41205cdabc5c3a3e11758e97c295a4f4..5f17f68f3c08387b7e0cbb41981f862a7b4f4ce0 100644 (file)
@@ -244,7 +244,9 @@ static int nsim_bpf_create_prog(struct nsim_dev *nsim_dev,
                            &state->state, &nsim_bpf_string_fops);
        debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded);
 
+       mutex_lock(&nsim_dev->progs_list_lock);
        list_add_tail(&state->l, &nsim_dev->bpf_bound_progs);
+       mutex_unlock(&nsim_dev->progs_list_lock);
 
        prog->aux->offload->dev_priv = state;
 
@@ -273,12 +275,16 @@ static int nsim_bpf_translate(struct bpf_prog *prog)
 static void nsim_bpf_destroy_prog(struct bpf_prog *prog)
 {
        struct nsim_bpf_bound_prog *state;
+       struct nsim_dev *nsim_dev;
 
        state = prog->aux->offload->dev_priv;
+       nsim_dev = state->nsim_dev;
        WARN(state->is_loaded,
             "offload state destroyed while program still bound");
        debugfs_remove_recursive(state->ddir);
+       mutex_lock(&nsim_dev->progs_list_lock);
        list_del(&state->l);
+       mutex_unlock(&nsim_dev->progs_list_lock);
        kfree(state);
 }
 
index 2683a989873e1d68651918bd9d745549b9c5e237..dfd571b2210716aaaa97f037cf2c4a98e53b0ef6 100644 (file)
@@ -1647,6 +1647,7 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
        nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT;
        nsim_dev->test2 = NSIM_DEV_TEST2_DEFAULT;
        spin_lock_init(&nsim_dev->fa_cookie_lock);
+       mutex_init(&nsim_dev->progs_list_lock);
 
        dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
 
@@ -1785,6 +1786,7 @@ void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev)
        devl_unregister(devlink);
        kfree(nsim_dev->vfconfigs);
        kfree(nsim_dev->fa_cookie);
+       mutex_destroy(&nsim_dev->progs_list_lock);
        devl_unlock(devlink);
        devlink_free(devlink);
        dev_set_drvdata(&nsim_bus_dev->dev, NULL);
index d1a941e2b18fc94b2393a7800612c5b8d18a272a..46c67983c5171146f4b719588a954dbb46c2b413 100644 (file)
@@ -324,6 +324,7 @@ struct nsim_dev {
        u32 prog_id_gen;
        struct list_head bpf_bound_progs;
        struct list_head bpf_bound_maps;
+       struct mutex progs_list_lock;
        struct netdev_phys_item_id switch_id;
        struct list_head port_list;
        bool fw_update_status;