Re: [BUG] KFENCE: use-after-free read in udp_tunnel_nic_device_sync_work

From: Sam Sun

Date: Wed Jun 24 2026 - 10:50:03 EST


On Wed, Jun 24, 2026 at 10:10 PM Eric Dumazet <edumazet@xxxxxxxxxx> wrote:
>
> On Wed, Jun 24, 2026 at 6:59 AM Eric Dumazet <edumazet@xxxxxxxxxx> wrote:
>
> > Oh well.
> >
> > u8 need_sync:1;
> > u8 need_replay:1;
> > u8 work_pending:1;
> >
> > These bitfields are not safe, obviously :/
> >
> > Time to convert them to atomic bit operations.
>
> Can you try:
>
> diff --git a/net/ipv4/udp_tunnel_nic.c b/net/ipv4/udp_tunnel_nic.c
> index 9944ed923ddfd10f9adf6ad788c0740daeaf2adb..939d6f656bb71814718bc3bf84be665adad27e4b
> 100644
> --- a/net/ipv4/udp_tunnel_nic.c
> +++ b/net/ipv4/udp_tunnel_nic.c
> @@ -30,9 +30,7 @@ struct udp_tunnel_nic_table_entry {
> * @work: async work for talking to hardware from process context
> * @dev: netdev pointer
> * @lock: protects all fields
> - * @need_sync: at least one port start changed
> - * @need_replay: space was freed, we need a replay of all ports
> - * @work_pending: @work is currently scheduled
> + * @flags: sync, replay, pending flags
> * @n_tables: number of tables under @entries
> * @missed: bitmap of tables which overflown
> * @entries: table of tables of ports currently offloaded
> @@ -44,9 +42,10 @@ struct udp_tunnel_nic {
>
> struct mutex lock;
>
> - u8 need_sync:1;
> - u8 need_replay:1;
> - u8 work_pending:1;
> + unsigned long flags;
> +#define UDP_TUNNEL_NIC_NEED_SYNC 0
> +#define UDP_TUNNEL_NIC_NEED_REPLAY 1
> +#define UDP_TUNNEL_NIC_WORK_PENDING 2
>
> unsigned int n_tables;
> unsigned long missed;
> @@ -116,7 +115,7 @@ udp_tunnel_nic_entry_queue(struct udp_tunnel_nic *utn,
> unsigned int flag)
> {
> entry->flags |= flag;
> - utn->need_sync = 1;
> + set_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags);
> }
>
> static void
> @@ -283,7 +282,7 @@ udp_tunnel_nic_device_sync_by_table(struct net_device *dev,
> static void
> __udp_tunnel_nic_device_sync(struct net_device *dev, struct
> udp_tunnel_nic *utn)
> {
> - if (!utn->need_sync)
> + if (!test_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags))
> return;
>
> if (dev->udp_tunnel_nic_info->sync_table)
> @@ -291,21 +290,24 @@ __udp_tunnel_nic_device_sync(struct net_device
> *dev, struct udp_tunnel_nic *utn)
> else
> udp_tunnel_nic_device_sync_by_port(dev, utn);
>
> - utn->need_sync = 0;
> + clear_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags);
> /* Can't replay directly here, in case we come from the tunnel driver's
> * notification - trying to replay may deadlock inside tunnel driver.
> */
> - utn->need_replay = udp_tunnel_nic_should_replay(dev, utn);
> + if (udp_tunnel_nic_should_replay(dev, utn))
> + set_bit(UDP_TUNNEL_NIC_NEED_REPLAY, &utn->flags);
> + else
> + clear_bit(UDP_TUNNEL_NIC_NEED_REPLAY, &utn->flags);
> }
>
> static void
> udp_tunnel_nic_device_sync(struct net_device *dev, struct udp_tunnel_nic *utn)
> {
> - if (!utn->need_sync)
> + if (!test_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags))
> return;
>
> + set_bit(UDP_TUNNEL_NIC_WORK_PENDING, &utn->flags);
> queue_work(udp_tunnel_nic_workqueue, &utn->work);
> - utn->work_pending = 1;
> }
>
> static bool
> @@ -348,7 +350,7 @@ udp_tunnel_nic_has_collision(struct net_device
> *dev, struct udp_tunnel_nic *utn,
> if (!udp_tunnel_nic_entry_is_free(entry) &&
> entry->port == ti->port &&
> entry->type != ti->type) {
> - __set_bit(i, &utn->missed);
> + set_bit(i, &utn->missed);
> return true;
> }
> }
> @@ -483,7 +485,7 @@ udp_tunnel_nic_add_new(struct net_device *dev,
> struct udp_tunnel_nic *utn,
> * are no devices currently which have multiple tables accepting
> * the same tunnel type, and false positives are okay.
> */
> - __set_bit(i, &utn->missed);
> + set_bit(i, &utn->missed);
> }
>
> return false;
> @@ -552,7 +554,7 @@ static void __udp_tunnel_nic_reset_ntf(struct
> net_device *dev)
>
> mutex_lock(&utn->lock);
>
> - utn->need_sync = false;
> + clear_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags);
> for (i = 0; i < utn->n_tables; i++)
> for (j = 0; j < info->tables[i].n_entries; j++) {
> struct udp_tunnel_nic_table_entry *entry;
> @@ -696,8 +698,8 @@ udp_tunnel_nic_flush(struct net_device *dev,
> struct udp_tunnel_nic *utn)
> for (i = 0; i < utn->n_tables; i++)
> memset(utn->entries[i], 0, array_size(info->tables[i].n_entries,
> sizeof(**utn->entries)));
> - WARN_ON(utn->need_sync);
> - utn->need_replay = 0;
> + WARN_ON(test_bit(UDP_TUNNEL_NIC_NEED_SYNC, &utn->flags));
> + clear_bit(UDP_TUNNEL_NIC_NEED_REPLAY, &utn->flags);
> }
>
> static void
> @@ -713,8 +715,8 @@ udp_tunnel_nic_replay(struct net_device *dev,
> struct udp_tunnel_nic *utn)
> for (i = 0; i < utn->n_tables; i++)
> for (j = 0; j < info->tables[i].n_entries; j++)
> udp_tunnel_nic_entry_freeze_used(&utn->entries[i][j]);
> - utn->missed = 0;
> - utn->need_replay = 0;
> + bitmap_zero(&utn->missed, UDP_TUNNEL_NIC_MAX_TABLES);
> + clear_bit(UDP_TUNNEL_NIC_NEED_REPLAY, &utn->flags);
>
> if (!info->shared) {
> udp_tunnel_get_rx_info(dev);
> @@ -736,10 +738,10 @@ static void
> udp_tunnel_nic_device_sync_work(struct work_struct *work)
> rtnl_lock();
> mutex_lock(&utn->lock);
>
> - utn->work_pending = 0;
> + clear_bit(UDP_TUNNEL_NIC_WORK_PENDING, &utn->flags);
> __udp_tunnel_nic_device_sync(utn->dev, utn);
>
> - if (utn->need_replay)
> + if (test_bit(UDP_TUNNEL_NIC_NEED_REPLAY, &utn->flags))
> udp_tunnel_nic_replay(utn->dev, utn);
>
> mutex_unlock(&utn->lock);
> @@ -866,6 +868,11 @@ udp_tunnel_nic_unregister(struct net_device *dev,
> struct udp_tunnel_nic *utn)
>
> udp_tunnel_nic_lock(dev);
>
> + if (test_bit(UDP_TUNNEL_NIC_WORK_PENDING, &utn->flags)) {
> + udp_tunnel_nic_unlock(dev);
> + return;
> + }
> +
> /* For a shared table remove this dev from the list of sharing devices
> * and if there are other devices just detach.
> */
> @@ -901,12 +908,6 @@ udp_tunnel_nic_unregister(struct net_device *dev,
> struct udp_tunnel_nic *utn)
> udp_tunnel_nic_flush(dev, utn);
> udp_tunnel_nic_unlock(dev);
>
> - /* Wait for the work to be done using the state, netdev core will
> - * retry unregister until we give up our reference on this device.
> - */
> - if (utn->work_pending)
> - return;
> -
> udp_tunnel_nic_free(utn);
> release_dev:
> dev->udp_tunnel_nic = NULL;

I tested this version as well, but it still does not stop the C reproducer
on my side.

This time the VM panicked after about 50 seconds on a debugobjects warning:

[ 50.420529][ T9744] ------------[ cut here ]------------
[ 50.421258][ T9744] ODEBUG: free active (active state 0) object:
ff110001114b5a00 object type: work_struct hint:
udp_tunnel_nic_device_sync_work+0x0/0x940
[ 50.424052][ T9744] WARNING: lib/debugobjects.c:629 at
debug_print_object+0x1a0/0x2e0, CPU#0: repro/9744
[ 50.425766][ T9744] Modules linked in:
[ 50.426279][ T9744] CPU: 0 UID: 0 PID: 9744 Comm: repro Not tainted
7.1.0-11240-g840ef6c78e6a-dirty #33 PREEMPT(full)
[ 50.428614][ T9744] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.15.0-1 04/01/2014
[ 50.429661][ T9744] RIP: 0010:debug_print_object+0x1a5/0x2e0
[ 50.430338][ T9744] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 8a 00
00 00 48 8b 14 ed 60 33 1e 8c 48 83 fd 05 77 47 48 8d 3d e0 0c 1e 0c
41 56 4c 89 e6 <67> 48 0f b9 3a 58 83 05 42 30 14 0c 01 48 83 c4 20 5b
5d 41 5c 41
[ 50.432538][ T9744] RSP: 0018:ffa0000012c8ee60 EFLAGS: 00010293
[ 50.433045][ T9744] RAX: dffffc0000000000 RBX: ffa0000012c8ef40 RCX:
0000000000000000
[ 50.433710][ T9744] RDX: ffffffff8c1e32a0 RSI: ffffffff8c1e2e80 RDI:
ffffffff90e31820
[ 50.434390][ T9744] RBP: 0000000000000003 R08: ff110001114b5a00 R09:
ffffffff8bae17e0
[ 50.435050][ T9744] R10: ffffffff90d907d7 R11: 0000000000000000 R12:
ffffffff8c1e2e80
[ 50.435719][ T9744] R13: ffffffff8bae1820 R14: ffffffff8a0f69e0 R15:
ffa0000012c8ef58
[ 50.436393][ T9744] FS: 00007f8430d5b640(0000)
GS:ff1100018394a000(0000) knlGS:0000000000000000
[ 50.437149][ T9744] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 50.437749][ T9744] CR2: 00007f422d7b8000 CR3: 000000010b850000 CR4:
0000000000753ef0
[ 50.438404][ T9744] PKRU: 55555554
[ 50.438716][ T9744] Call Trace:
[ 50.439004][ T9744] <TASK>
[ 50.439277][ T9744] ? __pfx_udp_tunnel_nic_device_sync_work+0x10/0x10
[ 50.439856][ T9744] ? _raw_spin_unlock_irqrestore+0x58/0x70
[ 50.440942][ T9744] debug_check_no_obj_freed+0x3ec/0x520
[ 50.441419][ T9744] ? __udp_tunnel_nic_lock+0x47/0x60
[ 50.441878][ T9744] ? __pfx_debug_check_no_obj_freed+0x10/0x10
[ 50.442403][ T9744] ? kasan_quarantine_put+0x10d/0x230
[ 50.442875][ T9744] ? lockdep_hardirqs_on+0x7c/0x110
[ 50.443325][ T9744] kfree+0x2a0/0x6d0
[ 50.443663][ T9744] ? udp_tunnel_nic_netdevice_event+0xc14/0x1e40
[ 50.444214][ T9744] udp_tunnel_nic_netdevice_event+0xc14/0x1e40
[ 50.444730][ T9744] notifier_call_chain+0xbd/0x430
[ 50.445164][ T9744] ? __pfx_udp_tunnel_nic_netdevice_event+0x10/0x10
[ 50.445729][ T9744] call_netdevice_notifiers_info+0xbe/0x110
[ 50.446236][ T9744] unregister_netdevice_many_notify+0xbab/0x2130
[ 50.446781][ T9744] ? __pfx_unregister_netdevice_many_notify+0x10/0x10
[ 50.447907][ T9744] ? __pfx___mutex_lock+0x10/0x10
[ 50.448351][ T9744] unregister_netdevice_queue+0x305/0x3c0
[ 50.448842][ T9744] ? __pfx_unregister_netdevice_queue+0x10/0x10
[ 50.449369][ T9744] nsim_destroy+0x231/0x980
[ 50.449773][ T9744] __nsim_dev_port_del+0x197/0x2c0
[ 50.450215][ T9744] nsim_dev_reload_destroy+0x105/0x490
[ 50.450677][ T9744] nsim_dev_reload_down+0x67/0xd0
[ 50.451143][ T9744] devlink_reload+0x197/0x7b0
[ 50.451564][ T9744] ? __pfx_devlink_reload+0x10/0x10
[ 50.452020][ T9744] ? security_capable+0x210/0x250
[ 50.452466][ T9744] ? ns_capable+0xe2/0x120
[ 50.452858][ T9744] devlink_nl_reload_doit+0x541/0x1160
[ 50.453323][ T9744] ? __pfx_devlink_nl_reload_doit+0x10/0x10
[ 50.453828][ T9744] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x1e5/0x2f0
[ 50.454458][ T9744] genl_family_rcv_msg_doit+0x1ff/0x2f0
[ 50.454930][ T9744] ? __pfx_genl_family_rcv_msg_doit+0x10/0x10
[ 50.455442][ T9744] ? bpf_lsm_capable+0x9/0x10
[ 50.455845][ T9744] ? security_capable+0x210/0x250
[ 50.456297][ T9744] genl_rcv_msg+0x532/0x7e0
[ 50.456683][ T9744] ? __pfx_genl_rcv_msg+0x10/0x10
[ 50.457115][ T9744] ? __pfx_devlink_nl_pre_doit_dev_lock+0x10/0x10
[ 50.457690][ T9744] ? __pfx_devlink_nl_reload_doit+0x10/0x10
[ 50.458218][ T9744] ? __pfx_devlink_nl_post_doit_dev_lock+0x10/0x10
[ 50.458776][ T9744] ? __lock_acquire+0x476/0x2420
[ 50.459208][ T9744] netlink_rcv_skb+0x147/0x430
[ 50.459633][ T9744] ? __pfx_genl_rcv_msg+0x10/0x10
[ 50.460062][ T9744] ? __pfx_netlink_rcv_skb+0x10/0x10
[ 50.460520][ T9744] ? netlink_deliver_tap+0x1ae/0xd10
[ 50.460976][ T9744] genl_rcv+0x28/0x40
[ 50.461330][ T9744] netlink_unicast+0x58d/0x850
[ 50.461739][ T9744] ? __pfx_netlink_unicast+0x10/0x10
[ 50.462198][ T9744] netlink_sendmsg+0x88d/0xd90
[ 50.462610][ T9744] ? __pfx_netlink_sendmsg+0x10/0x10
[ 50.463092][ T9744] ? __pfx_netlink_sendmsg+0x10/0x10
[ 50.463557][ T9744] ____sys_sendmsg+0xa27/0xb90
[ 50.463982][ T9744] ? __pfx_____sys_sendmsg+0x10/0x10
[ 50.464438][ T9744] ? __pfx_copy_msghdr_from_user+0x10/0x10
[ 50.464938][ T9744] ? find_held_lock+0x2b/0x80
[ 50.465347][ T9744] ? futex_wake+0x4f7/0x5e0
[ 50.465735][ T9744] ___sys_sendmsg+0x11c/0x1b0
[ 50.466129][ T9744] ? __pfx____sys_sendmsg+0x10/0x10
[ 50.466586][ T9744] ? __pfx_futex_wake+0x10/0x10
[ 50.467002][ T9744] ? __fget_files+0x1f1/0x3b0
[ 50.467440][ T9744] ? __fget_files+0x1fb/0x3b0
[ 50.467836][ T9744] ? __lock_acquire+0x450/0x2420
[ 50.468298][ T9744] __sys_sendmsg+0x142/0x1f0
[ 50.468696][ T9744] ? __pfx___sys_sendmsg+0x10/0x10
[ 50.469133][ T9744] ? __cpu_to_node+0x8a/0x130
[ 50.469538][ T9744] do_syscall_64+0x11f/0x860
[ 50.469953][ T9744] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 50.470454][ T9744] RIP: 0033:0x451a4d
[ 50.470783][ T9744] Code: c3 e8 a7 23 00 00 0f 1f 80 00 00 00 00 f3
0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b
4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8
64 89 01 48
[ 50.472393][ T9744] RSP: 002b:00007f8430d5b198 EFLAGS: 00000246
ORIG_RAX: 000000000000002e
[ 50.473102][ T9744] RAX: ffffffffffffffda RBX: 00000000004e9440 RCX:
0000000000451a4d
[ 50.473761][ T9744] RDX: 0000000000000000 RSI: 0000200000000800 RDI:
0000000000000003
[ 50.474419][ T9744] RBP: 00000000004b66b4 R08: 000000000000006d R09:
0000000000000000
[ 50.475085][ T9744] R10: 0000000000000001 R11: 0000000000000246 R12:
0000200000000280
[ 50.475738][ T9744] R13: 0000200000000190 R14: 0000200000000180 R15:
00000000004e9448
[ 50.476418][ T9744] </TASK>
[ 50.476683][ T9744] Kernel panic - not syncing: kernel: panic_on_warn set ...
[ 50.477297][ T9744] CPU: 0 UID: 0 PID: 9744 Comm: repro Not tainted
7.1.0-11240-g840ef6c78e6a-dirty #33 PREEMPT(full)
[ 50.478201][ T9744] Hardware name: QEMU Standard PC (i440FX + PIIX,
1996), BIOS 1.15.0-1 04/01/2014
[ 50.478952][ T9744] Call Trace:
[ 50.479240][ T9744] <TASK>
[ 50.479492][ T9744] dump_stack_lvl+0x3d/0x1b0
[ 50.479895][ T9744] vpanic+0x7f2/0xa70
[ 50.480241][ T9744] ? __pfx_vpanic+0x10/0x10
[ 50.480621][ T9744] ? is_bpf_text_address+0x96/0x1a0
[ 50.481070][ T9744] ? debug_print_object+0x1a0/0x2e0
[ 50.481512][ T9744] panic+0xc2/0xd0
[ 50.481844][ T9744] ? __pfx_panic+0x10/0x10
[ 50.482230][ T9744] ? check_panic_on_warn+0x1f/0xc0
[ 50.482673][ T9744] check_panic_on_warn+0xb1/0xc0
[ 50.483102][ T9744] __warn+0x108/0x3f0
[ 50.483460][ T9744] __report_bug+0x42c/0x510
[ 50.483854][ T9744] ? debug_print_object+0x1a0/0x2e0
[ 50.484297][ T9744] ? __pfx___report_bug+0x10/0x10
[ 50.484721][ T9744] ? __kernel_text_address+0xd/0x40
[ 50.485166][ T9744] ? unwind_get_return_address+0x59/0xa0
[ 50.485664][ T9744] report_bug_entry+0xe1/0x280
[ 50.486068][ T9744] ? debug_print_object+0x1a5/0x2e0
[ 50.486508][ T9744] handle_bug+0x428/0x4e0
[ 50.486889][ T9744] exc_invalid_op+0x35/0x80
[ 50.487281][ T9744] asm_exc_invalid_op+0x1a/0x20
[ 50.487693][ T9744] RIP: 0010:debug_print_object+0x1a5/0x2e0
[ 50.488194][ T9744] Code: 89 fa 48 c1 ea 03 80 3c 02 00 0f 85 8a 00
00 00 48 8b 14 ed 60 33 1e 8c 48 83 fd 05 77 47 48 8d 3d e0 0c 1e 0c
41 56 4c 89 e6 <67> 48 0f b9 3a 58 83 05 42 30 14 0c 01 48 83 c4 20 5b
5d 41 5c 41
[ 50.489814][ T9744] RSP: 0018:ffa0000012c8ee60 EFLAGS: 00010293
[ 50.490362][ T9744] RAX: dffffc0000000000 RBX: ffa0000012c8ef40 RCX:
0000000000000000
[ 50.491033][ T9744] RDX: ffffffff8c1e32a0 RSI: ffffffff8c1e2e80 RDI:
ffffffff90e31820
[ 50.491698][ T9744] RBP: 0000000000000003 R08: ff110001114b5a00 R09:
ffffffff8bae17e0
[ 50.492384][ T9744] R10: ffffffff90d907d7 R11: 0000000000000000 R12:
ffffffff8c1e2e80
[ 50.493043][ T9744] R13: ffffffff8bae1820 R14: ffffffff8a0f69e0 R15:
ffa0000012c8ef58
[ 50.493718][ T9744] ? __pfx_udp_tunnel_nic_device_sync_work+0x10/0x10
[ 50.494288][ T9744] ? __pfx_udp_tunnel_nic_device_sync_work+0x10/0x10
[ 50.494845][ T9744] ? _raw_spin_unlock_irqrestore+0x58/0x70
[ 50.495347][ T9744] debug_check_no_obj_freed+0x3ec/0x520
[ 50.495825][ T9744] ? __udp_tunnel_nic_lock+0x47/0x60
[ 50.496276][ T9744] ? __pfx_debug_check_no_obj_freed+0x10/0x10
[ 50.496794][ T9744] ? kasan_quarantine_put+0x10d/0x230
[ 50.497266][ T9744] ? lockdep_hardirqs_on+0x7c/0x110
[ 50.497706][ T9744] kfree+0x2a0/0x6d0
[ 50.498038][ T9744] ? udp_tunnel_nic_netdevice_event+0xc14/0x1e40
[ 50.498577][ T9744] udp_tunnel_nic_netdevice_event+0xc14/0x1e40
[ 50.499107][ T9744] notifier_call_chain+0xbd/0x430
[ 50.499544][ T9744] ? __pfx_udp_tunnel_nic_netdevice_event+0x10/0x10
[ 50.500096][ T9744] call_netdevice_notifiers_info+0xbe/0x110
[ 50.500625][ T9744] unregister_netdevice_many_notify+0xbab/0x2130
[ 50.501169][ T9744] ? __pfx_unregister_netdevice_many_notify+0x10/0x10
[ 50.501737][ T9744] ? __pfx___mutex_lock+0x10/0x10
[ 50.502174][ T9744] unregister_netdevice_queue+0x305/0x3c0
[ 50.502660][ T9744] ? __pfx_unregister_netdevice_queue+0x10/0x10
[ 50.503186][ T9744] nsim_destroy+0x231/0x980
[ 50.503564][ T9744] __nsim_dev_port_del+0x197/0x2c0
[ 50.503966][ T9744] nsim_dev_reload_destroy+0x105/0x490
[ 50.504406][ T9744] nsim_dev_reload_down+0x67/0xd0
[ 50.504808][ T9744] devlink_reload+0x197/0x7b0
[ 50.505220][ T9744] ? __pfx_devlink_reload+0x10/0x10
[ 50.505679][ T9744] ? security_capable+0x210/0x250
[ 50.506113][ T9744] ? ns_capable+0xe2/0x120
[ 50.506490][ T9744] devlink_nl_reload_doit+0x541/0x1160
[ 50.506962][ T9744] ? __pfx_devlink_nl_reload_doit+0x10/0x10
[ 50.507471][ T9744] ? genl_family_rcv_msg_attrs_parse.constprop.0+0x1e5/0x2f0
[ 50.508094][ T9744] genl_family_rcv_msg_doit+0x1ff/0x2f0
[ 50.508577][ T9744] ? __pfx_genl_family_rcv_msg_doit+0x10/0x10
[ 50.509098][ T9744] ? bpf_lsm_capable+0x9/0x10
[ 50.509495][ T9744] ? security_capable+0x210/0x250
[ 50.509924][ T9744] genl_rcv_msg+0x532/0x7e0
[ 50.510327][ T9744] ? __pfx_genl_rcv_msg+0x10/0x10
[ 50.510753][ T9744] ? __pfx_devlink_nl_pre_doit_dev_lock+0x10/0x10
[ 50.511291][ T9744] ? __pfx_devlink_nl_reload_doit+0x10/0x10
[ 50.511795][ T9744] ? __pfx_devlink_nl_post_doit_dev_lock+0x10/0x10
[ 50.512365][ T9744] ? __lock_acquire+0x476/0x2420
[ 50.512785][ T9744] netlink_rcv_skb+0x147/0x430
[ 50.513197][ T9744] ? __pfx_genl_rcv_msg+0x10/0x10
[ 50.513627][ T9744] ? __pfx_netlink_rcv_skb+0x10/0x10
[ 50.514090][ T9744] ? netlink_deliver_tap+0x1ae/0xd10
[ 50.514542][ T9744] genl_rcv+0x28/0x40
[ 50.514879][ T9744] netlink_unicast+0x58d/0x850
[ 50.515302][ T9744] ? __pfx_netlink_unicast+0x10/0x10
[ 50.515760][ T9744] netlink_sendmsg+0x88d/0xd90
[ 50.516181][ T9744] ? __pfx_netlink_sendmsg+0x10/0x10
[ 50.516640][ T9744] ? __pfx_netlink_sendmsg+0x10/0x10
[ 50.517109][ T9744] ____sys_sendmsg+0xa27/0xb90
[ 50.517520][ T9744] ? __pfx_____sys_sendmsg+0x10/0x10
[ 50.517965][ T9744] ? __pfx_copy_msghdr_from_user+0x10/0x10
[ 50.518457][ T9744] ? find_held_lock+0x2b/0x80
[ 50.518871][ T9744] ? futex_wake+0x4f7/0x5e0
[ 50.519271][ T9744] ___sys_sendmsg+0x11c/0x1b0
[ 50.519677][ T9744] ? __pfx____sys_sendmsg+0x10/0x10
[ 50.520117][ T9744] ? __pfx_futex_wake+0x10/0x10
[ 50.520542][ T9744] ? __fget_files+0x1f1/0x3b0
[ 50.520945][ T9744] ? __fget_files+0x1fb/0x3b0
[ 50.521347][ T9744] ? __lock_acquire+0x450/0x2420
[ 50.521770][ T9744] __sys_sendmsg+0x142/0x1f0
[ 50.522176][ T9744] ? __pfx___sys_sendmsg+0x10/0x10
[ 50.522617][ T9744] ? __cpu_to_node+0x8a/0x130
[ 50.523021][ T9744] do_syscall_64+0x11f/0x860
[ 50.523417][ T9744] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 50.523926][ T9744] RIP: 0033:0x451a4d
[ 50.524264][ T9744] Code: c3 e8 a7 23 00 00 0f 1f 80 00 00 00 00 f3
0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b
4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8
64 89 01 48
[ 50.525868][ T9744] RSP: 002b:00007f8430d5b198 EFLAGS: 00000246
ORIG_RAX: 000000000000002e
[ 50.526579][ T9744] RAX: ffffffffffffffda RBX: 00000000004e9440 RCX:
0000000000451a4d
[ 50.527243][ T9744] RDX: 0000000000000000 RSI: 0000200000000800 RDI:
0000000000000003
[ 50.527914][ T9744] RBP: 00000000004b66b4 R08: 000000000000006d R09:
0000000000000000
[ 50.528614][ T9744] R10: 0000000000000001 R11: 0000000000000246 R12:
0000200000000280
[ 50.529305][ T9744] R13: 0000200000000190 R14: 0000200000000180 R15:
00000000004e9448
[ 50.529982][ T9744] </TASK>
[ 50.530453][ T9744] Kernel Offset: disabled

Resolved from the patched vmlinux:
udp_tunnel_nic_netdevice_event+0xc14/0x1e40:
udp_tunnel_nic_unregister at net/ipv4/udp_tunnel_nic.c:913
udp_tunnel_nic_netdevice_event at net/ipv4/udp_tunnel_nic.c:943

So we are still freeing struct udp_tunnel_nic while its embedded work_struct
is active. debugobjects catches this at kfree() before the active work gets a
chance to run later and dereference the freed utn.

My read is that the conversion from bitfields to atomic bitops removes the
plain bitfield data race, but UDP_TUNNEL_NIC_WORK_PENDING is still only one
boolean state. It can represent "some work is pending", but it cannot
distinguish between:
idle
queued
running
running and queued again

In particular, the workqueue core clears WORK_STRUCT_PENDING before invoking
the worker. At that point the same work item can be queued again by
udp_tunnel_nic_device_sync(). If an already running instance later executes:

clear_bit(UDP_TUNNEL_NIC_WORK_PENDING, &utn->flags);

it can still clear the bit that was set for the requeued instance. Then
udp_tunnel_nic_unregister() may observe UDP_TUNNEL_NIC_WORK_PENDING clear and
free utn, even though debugobjects still sees utn->work as active.

Thanks,
Yue