[PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink

Boudewijn van der Heide posted 1 patch 1 month ago
drivers/net/macvlan.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
[PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
Posted by Boudewijn van der Heide 1 month ago
The macvlan_common_newlink() function calls macvlan_port_create(),
which allocates a port structure and registers the RX handler via
netdev_rx_handler_register(). Once registered, the handler is
immediately live and can be invoked from softirq context.

If the subsequent call to register_netdevice() fails (e.g., due to
a name collision), the error path calls macvlan_port_destroy(),
which unregisters the handler and immediately frees the port with
kfree().

This creates a race condition: one thread may be processing a packet
in the RX handler and accessing the port structure, while another
thread is executing the error path and frees the port. This results
in the first thread reading freed memory, leading to a use-after-free
and undefined behavior.

Fix this by replacing kfree() with kfree_rcu() to defer the memory
release until all RCU read-side sections have completed,
and add an rcu_head field to the macvlan_port structure. This ensures
the port remains valid while any thread is still accessing it.

This functionality was previously present but was removed in
commit a1f5315ce4e1 ("driver: macvlan: Remove the rcu member of macvlan_port"),
which inadvertently introduced this use-after-free.

Fixes: a1f5315ce4e1 ("driver: macvlan: Remove the rcu member of macvlan_port")
Reported-by: syzbot+7182fbe91e58602ec1fe@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7182fbe91e58602ec1fe
Signed-off-by: Boudewijn van der Heide <boudewijn@delta-utec.com>
---
 drivers/net/macvlan.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 7966545512cf..d6e8f7774055 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -47,6 +47,7 @@ struct macvlan_port {
 	struct list_head	vlans;
 	struct sk_buff_head	bc_queue;
 	struct work_struct	bc_work;
+	struct rcu_head		rcu;
 	u32			bc_queue_len_used;
 	int			bc_cutoff;
 	u32			flags;
@@ -1302,7 +1303,7 @@ static void macvlan_port_destroy(struct net_device *dev)
 		dev_set_mac_address(port->dev, &ss, NULL);
 	}
 
-	kfree(port);
+	kfree_rcu(port, rcu);
 }
 
 static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
-- 
2.47.3
Re: [PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
Posted by Eric Dumazet 1 month ago
On Thu, Jan 8, 2026 at 6:45 PM Boudewijn van der Heide
<boudewijn@delta-utec.com> wrote:
>
> The macvlan_common_newlink() function calls macvlan_port_create(),
> which allocates a port structure and registers the RX handler via
> netdev_rx_handler_register(). Once registered, the handler is
> immediately live and can be invoked from softirq context.
>
> If the subsequent call to register_netdevice() fails (e.g., due to
> a name collision), the error path calls macvlan_port_destroy(),
> which unregisters the handler and immediately frees the port with
> kfree().
>
> This creates a race condition: one thread may be processing a packet
> in the RX handler and accessing the port structure, while another
> thread is executing the error path and frees the port. This results
> in the first thread reading freed memory, leading to a use-after-free
> and undefined behavior.
>
> Fix this by replacing kfree() with kfree_rcu() to defer the memory
> release until all RCU read-side sections have completed,
> and add an rcu_head field to the macvlan_port structure. This ensures
> the port remains valid while any thread is still accessing it.
>
> This functionality was previously present but was removed in
> commit a1f5315ce4e1 ("driver: macvlan: Remove the rcu member of macvlan_port"),
> which inadvertently introduced this use-after-free.
>
> Fixes: a1f5315ce4e1 ("driver: macvlan: Remove the rcu member of macvlan_port")
> Reported-by: syzbot+7182fbe91e58602ec1fe@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=7182fbe91e58602ec1fe
> Signed-off-by: Boudewijn van der Heide <boudewijn@delta-utec.com>
> ---
>  drivers/net/macvlan.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
> index 7966545512cf..d6e8f7774055 100644
> --- a/drivers/net/macvlan.c
> +++ b/drivers/net/macvlan.c
> @@ -47,6 +47,7 @@ struct macvlan_port {
>         struct list_head        vlans;
>         struct sk_buff_head     bc_queue;
>         struct work_struct      bc_work;
> +       struct rcu_head         rcu;
>         u32                     bc_queue_len_used;
>         int                     bc_cutoff;
>         u32                     flags;
> @@ -1302,7 +1303,7 @@ static void macvlan_port_destroy(struct net_device *dev)
>                 dev_set_mac_address(port->dev, &ss, NULL);
>         }
>
> -       kfree(port);
> +       kfree_rcu(port, rcu);
>  }
>
>  static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[],
> --
> 2.47.3
>

I have sent this instead

https://lore.kernel.org/all/20260108133651.1130486-1-edumazet@google.com/T/

I think my patch makes more sense.
Re: [PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
Posted by Boudewijn van der Heide 1 month ago
Hi Eric,

Thanks for the patch, I agree it improves safety for source-entry deletion.

However, I believe it does not fix the specific KASAN report from syzbot, 
which indicates a UAF on the struct macvlan_port itself, not a source entry.

The report shows the freed object is in kmalloc-cg-4k (size 4096):

The buggy address belongs to the object at ffff888030eda000
which belongs to the cache kmalloc-cg-4k of size 4096

struct macvlan_port fits this size (due to the large hash tables), 
whereas struct macvlan_source_entry is much smaller. 
The crash happens at offset 3580, which corresponds to the vlan_source_hash array inside the port:

The race occurs in the register_netdevice() error path in macvlan_common_newlink():

1. netdev_rx_handler_register() succeeds 
2. register_netdevice() fails.
3. macvlan_port_destroy() is called, performing a synchronous kfree(port).

If a packet arrives during step 3, 
macvlan_handle_frame() accesses port->vlan_source_hash (via macvlan_forward_source),
after it is freed.

My patch restores the kfree_rcu behavior for the port (removed in 2016). 
I believe both fixes are needed: yours for the source entries, and mine for the port itself.

Thanks,
Boudewijn
Re: [PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
Posted by Eric Dumazet 1 month ago
On Thu, Jan 8, 2026 at 8:19 PM Boudewijn van der Heide
<boudewijn@delta-utec.com> wrote:
>
> Hi Eric,
>
> Thanks for the patch, I agree it improves safety for source-entry deletion.
>
> However, I believe it does not fix the specific KASAN report from syzbot,
> which indicates a UAF on the struct macvlan_port itself, not a source entry.
>

It completely fixes the problem.

Crash occurs in

            if (entry->vlan->flags & MACVLAN_FLAG_NODST)

because entry->vlan has been freed already :

==================================================================
BUG: KASAN: slab-use-after-free in macvlan_forward_source+0x512/0x630
drivers/net/macvlan.c:436
Read of size 2 at addr ffff888029fb8dfc by task syz.1.2073/14062

CPU: 0 UID: 0 PID: 14062 Comm: syz.1.2073 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine,
BIOS Google 10/25/2025
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378 [inline]
print_report+0xca/0x240 mm/kasan/report.c:482
kasan_report+0x118/0x150 mm/kasan/report.c:595
macvlan_forward_source+0x512/0x630 drivers/net/macvlan.c:436
macvlan_handle_frame+0x1ba/0x12e0 drivers/net/macvlan.c:495
__netif_receive_skb_core+0x95f/0x2f90 net/core/dev.c:6024
__netif_receive_skb_one_core net/core/dev.c:6135 [inline]
__netif_receive_skb+0x72/0x380 net/core/dev.c:6250
netif_receive_skb_internal net/core/dev.c:6336 [inline]
netif_receive_skb+0x1bb/0x750 net/core/dev.c:6395
tun_rx_batched+0x1b9/0x730 drivers/net/tun.c:1485
tun_get_user+0x2aa3/0x3dc0 drivers/net/tun.c:1953
tun_chr_write_iter+0x113/0x200 drivers/net/tun.c:1999
new_sync_write fs/read_write.c:593 [inline]
vfs_write+0x5c9/0xb30 fs/read_write.c:686
ksys_write+0x145/0x250 fs/read_write.c:738
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f90edf8e1ff
Code: 89 54 24 18 48 89 74 24 10 89 7c 24 08 e8 f9 92 02 00 48 8b 54
24 18 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 01 00 00 00 0f 05 <48> 3d
00 f0 ff ff 77 31 44 89 c7 48 89 44 24 08 e8 4c 93 02 00 48
RSP: 002b:00007f90eedb6000 EFLAGS: 00000293 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f90ee1e6180 RCX: 00007f90edf8e1ff
RDX: 000000000000004e RSI: 0000200000000180 RDI: 00000000000000c8
RBP: 00007f90ee013f91 R08: 0000000000000000 R09: 0000000000000000
R10: 000000000000004e R11: 0000000000000293 R12: 0000000000000000
R13: 00007f90ee1e6218 R14: 00007f90ee1e6180 R15: 00007ffd5dc50558
</TASK>

Allocated by task 13998:
kasan_save_stack mm/kasan/common.c:56 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:77
poison_kmalloc_redzone mm/kasan/common.c:397 [inline]
__kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:414
kasan_kmalloc include/linux/kasan.h:262 [inline]
__do_kmalloc_node mm/slub.c:5657 [inline]
__kvmalloc_node_noprof+0x5d5/0x920 mm/slub.c:7134
alloc_netdev_mqs+0xa6/0x11b0 net/core/dev.c:11997
vti6_init_net+0x104/0x370 net/ipv6/ip6_vti.c:1146
ops_init+0x35c/0x5c0 net/core/net_namespace.c:137
setup_net+0x110/0x330 net/core/net_namespace.c:446
copy_net_ns+0x3e3/0x570 net/core/net_namespace.c:581
create_new_namespaces+0x3e7/0x6a0 kernel/nsproxy.c:130
unshare_nsproxy_namespaces+0x11c/0x170 kernel/nsproxy.c:226
ksys_unshare+0x4c8/0x8c0 kernel/fork.c:3171
__do_sys_unshare kernel/fork.c:3242 [inline]
__se_sys_unshare kernel/fork.c:3240 [inline]
__x64_sys_unshare+0x38/0x50 kernel/fork.c:3240
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f

Freed by task 13998:
kasan_save_stack mm/kasan/common.c:56 [inline]
kasan_save_track+0x3e/0x80 mm/kasan/common.c:77
kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:584
poison_slab_object mm/kasan/common.c:252 [inline]
__kasan_slab_free+0x5c/0x80 mm/kasan/common.c:284
kasan_slab_free include/linux/kasan.h:234 [inline]
slab_free_hook mm/slub.c:2540 [inline]
slab_free mm/slub.c:6668 [inline]
kfree+0x1c0/0x660 mm/slub.c:6876
vti6_init_net+0x2e2/0x370 net/ipv6/ip6_vti.c:1168
ops_init+0x35c/0x5c0 net/core/net_namespace.c:137
setup_net+0x110/0x330 net/core/net_namespace.c:446
copy_net_ns+0x3e3/0x570 net/core/net_namespace.c:581
create_new_namespaces+0x3e7/0x6a0 kernel/nsproxy.c:130
unshare_nsproxy_namespaces+0x11c/0x170 kernel/nsproxy.c:226
ksys_unshare+0x4c8/0x8c0 kernel/fork.c:3171
__do_sys_unshare kernel/fork.c:3242 [inline]
__se_sys_unshare kernel/fork.c:3240 [inline]
__x64_sys_unshare+0x38/0x50 kernel/fork.c:3240
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff888029fb8000
which belongs to the cache kmalloc-cg-4k of size 4096
The buggy address is located 3580 bytes inside of
freed 4096-byte region [ffff888029fb8000, ffff888029fb9000)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x29fb8
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
memcg:ffff88803317c501
anon flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000040 ffff88813ffb0500 0000000000000000 dead000000000001
raw: 0000000000000000 0000000000040004 00000000f5000000 ffff88803317c501
head: 00fff00000000040 ffff88813ffb0500 0000000000000000 dead000000000001
head: 0000000000000000 0000000000040004 00000000f5000000 ffff88803317c501
head: 00fff00000000003 ffffea0000a7ee01 00000000ffffffff 00000000ffffffff
head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 3, migratetype Unmovable, gfp_mask
0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC),
pid 11169, tgid 11169 (modprobe), ts 207829820236, free_ts
207789169305
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x234/0x290 mm/page_alloc.c:1846
prep_new_page mm/page_alloc.c:1854 [inline]
get_page_from_freelist+0x2365/0x2440 mm/page_alloc.c:3915
__alloc_frozen_pages_noprof+0x181/0x370 mm/page_alloc.c:5210
alloc_pages_mpol+0x232/0x4a0 mm/mempolicy.c:2486
alloc_slab_page mm/slub.c:3075 [inline]
allocate_slab+0x86/0x3b0 mm/slub.c:3248
new_slab mm/slub.c:3302 [inline]
___slab_alloc+0xf2b/0x1960 mm/slub.c:4656
__slab_alloc+0x65/0x100 mm/slub.c:4779
__slab_alloc_node mm/slub.c:4855 [inline]
slab_alloc_node mm/slub.c:5251 [inline]
__do_kmalloc_node mm/slub.c:5656 [inline]
__kvmalloc_node_noprof+0x6b6/0x920 mm/slub.c:7134
seq_buf_alloc fs/seq_file.c:38 [inline]
seq_read_iter+0x202/0xe20 fs/seq_file.c:210
proc_reg_read_iter+0x1b7/0x280 fs/proc/inode.c:299
new_sync_read fs/read_write.c:491 [inline]
vfs_read+0x55a/0xa30 fs/read_write.c:572
ksys_read+0x145/0x250 fs/read_write.c:715
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
page last free pid 11127 tgid 11119 stack trace:
reset_page_owner include/linux/page_owner.h:25 [inline]
free_pages_prepare mm/page_alloc.c:1395 [inline]
__free_frozen_pages+0xbc8/0xd30 mm/page_alloc.c:2943
__folio_put+0x21b/0x2c0 mm/swap.c:112
folio_put include/linux/mm.h:1612 [inline]
put_page include/linux/mm.h:1681 [inline]
do_exit+0x183b/0x2310 kernel/exit.c:1002
do_group_exit+0x21c/0x2d0 kernel/exit.c:1112
get_signal+0x1285/0x1340 kernel/signal.c:3034
arch_do_signal_or_restart+0x9a/0x7a0 arch/x86/kernel/signal.c:337
__exit_to_user_mode_loop kernel/entry/common.c:41 [inline]
exit_to_user_mode_loop+0x87/0x4f0 kernel/entry/common.c:75
__exit_to_user_mode_prepare include/linux/irq-entry-common.h:226 [inline]
syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:256 [inline]
syscall_exit_to_user_mode_work include/linux/entry-common.h:159 [inline]
syscall_exit_to_user_mode include/linux/entry-common.h:194 [inline]
do_syscall_64+0x2d0/0xf80 arch/x86/entry/syscall_64.c:100
entry_SYSCALL_64_after_hwframe+0x77/0x7f




> The report shows the freed object is in kmalloc-cg-4k (size 4096):
>
> The buggy address belongs to the object at ffff888030eda000
> which belongs to the cache kmalloc-cg-4k of size 4096
>
> struct macvlan_port fits this size (due to the large hash tables),
> whereas struct macvlan_source_entry is much smaller.
> The crash happens at offset 3580, which corresponds to the vlan_source_hash array inside the port:
>
> The race occurs in the register_netdevice() error path in macvlan_common_newlink():
>
> 1. netdev_rx_handler_register() succeeds
> 2. register_netdevice() fails.
> 3. macvlan_port_destroy() is called, performing a synchronous kfree(port).
>
> If a packet arrives during step 3,
> macvlan_handle_frame() accesses port->vlan_source_hash (via macvlan_forward_source),
> after it is freed.
>
> My patch restores the kfree_rcu behavior for the port (removed in 2016).
> I believe both fixes are needed: yours for the source entries, and mine for the port itself.

I do not think your patch is needed.

Let's wait after my patch is merged, we will see if new syzbot reports
are found.
Re: [PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
Posted by Boudewijn van der Heide 1 month ago
> It completely fixes the problem.
> 
> Crash occurs in
>
>             if (entry->vlan->flags & MACVLAN_FLAG_NODST)
>
> because entry->vlan has been freed already :
>
> ==================================================================
> BUG: KASAN: slab-use-after-free in macvlan_forward_source+0x512/0x630
> drivers/net/macvlan.c:436
> Read of size 2 at addr ffff888029fb8dfc by task syz.1.2073/14062
>
> CPU: 0 UID: 0 PID: 14062 Comm: syz.1.2073 Not tainted syzkaller #0 PREEMPT(full)
> Hardware name: Google Google Compute Engine/Google Compute Engine,
> BIOS Google 10/25/2025
> Call Trace:
> <TASK>
> dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
> print_address_description mm/kasan/report.c:378 [inline]
> print_report+0xca/0x240 mm/kasan/report.c:482
> kasan_report+0x118/0x150 mm/kasan/report.c:595
> macvlan_forward_source+0x512/0x630 drivers/net/macvlan.c:436
> macvlan_handle_frame+0x1ba/0x12e0 drivers/net/macvlan.c:495
> __netif_receive_skb_core+0x95f/0x2f90 net/core/dev.c:6024
> __netif_receive_skb_one_core net/core/dev.c:6135 [inline]
> __netif_receive_skb+0x72/0x380 net/core/dev.c:6250
> netif_receive_skb_internal net/core/dev.c:6336 [inline]
> netif_receive_skb+0x1bb/0x750 net/core/dev.c:6395
> tun_rx_batched+0x1b9/0x730 drivers/net/tun.c:1485
> tun_get_user+0x2aa3/0x3dc0 drivers/net/tun.c:1953
> tun_chr_write_iter+0x113/0x200 drivers/net/tun.c:1999
> new_sync_write fs/read_write.c:593 [inline]
> vfs_write+0x5c9/0xb30 fs/read_write.c:686
> ksys_write+0x145/0x250 fs/read_write.c:738
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> RIP: 0033:0x7f90edf8e1ff
> Code: 89 54 24 18 48 89 74 24 10 89 7c 24 08 e8 f9 92 02 00 48 8b 54
> 24 18 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 01 00 00 00 0f 05 <48> 3d
> 00 f0 ff ff 77 31 44 89 c7 48 89 44 24 08 e8 4c 93 02 00 48
> RSP: 002b:00007f90eedb6000 EFLAGS: 00000293 ORIG_RAX: 0000000000000001
> RAX: ffffffffffffffda RBX: 00007f90ee1e6180 RCX: 00007f90edf8e1ff
> RDX: 000000000000004e RSI: 0000200000000180 RDI: 00000000000000c8
> RBP: 00007f90ee013f91 R08: 0000000000000000 R09: 0000000000000000
> R10: 000000000000004e R11: 0000000000000293 R12: 0000000000000000
> R13: 00007f90ee1e6218 R14: 00007f90ee1e6180 R15: 00007ffd5dc50558
> </TASK>
>
> Allocated by task 13998:
> kasan_save_stack mm/kasan/common.c:56 [inline]
> kasan_save_track+0x3e/0x80 mm/kasan/common.c:77
> poison_kmalloc_redzone mm/kasan/common.c:397 [inline]
> __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:414
> kasan_kmalloc include/linux/kasan.h:262 [inline]
> __do_kmalloc_node mm/slub.c:5657 [inline]
> __kvmalloc_node_noprof+0x5d5/0x920 mm/slub.c:7134
> alloc_netdev_mqs+0xa6/0x11b0 net/core/dev.c:11997
> vti6_init_net+0x104/0x370 net/ipv6/ip6_vti.c:1146
> ops_init+0x35c/0x5c0 net/core/net_namespace.c:137
> setup_net+0x110/0x330 net/core/net_namespace.c:446
> copy_net_ns+0x3e3/0x570 net/core/net_namespace.c:581
> create_new_namespaces+0x3e7/0x6a0 kernel/nsproxy.c:130
> unshare_nsproxy_namespaces+0x11c/0x170 kernel/nsproxy.c:226
> ksys_unshare+0x4c8/0x8c0 kernel/fork.c:3171
> __do_sys_unshare kernel/fork.c:3242 [inline]
> __se_sys_unshare kernel/fork.c:3240 [inline]
> __x64_sys_unshare+0x38/0x50 kernel/fork.c:3240
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> Freed by task 13998:
> kasan_save_stack mm/kasan/common.c:56 [inline]
> kasan_save_track+0x3e/0x80 mm/kasan/common.c:77
> kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:584
> poison_slab_object mm/kasan/common.c:252 [inline]
> __kasan_slab_free+0x5c/0x80 mm/kasan/common.c:284
> kasan_slab_free include/linux/kasan.h:234 [inline]
> slab_free_hook mm/slub.c:2540 [inline]
> slab_free mm/slub.c:6668 [inline]
> kfree+0x1c0/0x660 mm/slub.c:6876
> vti6_init_net+0x2e2/0x370 net/ipv6/ip6_vti.c:1168
> ops_init+0x35c/0x5c0 net/core/net_namespace.c:137
> setup_net+0x110/0x330 net/core/net_namespace.c:446
>
> copy_net_ns+0x3e3/0x570 net/core/net_namespace.c:581
> create_new_namespaces+0x3e7/0x6a0 kernel/nsproxy.c:130
> unshare_nsproxy_namespaces+0x11c/0x170 kernel/nsproxy.c:226
> ksys_unshare+0x4c8/0x8c0 kernel/fork.c:3171
> __do_sys_unshare kernel/fork.c:3242 [inline]
> __se_sys_unshare kernel/fork.c:3240 [inline]
> __x64_sys_unshare+0x38/0x50 kernel/fork.c:3240
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
>
> The buggy address belongs to the object at ffff888029fb8000
> which belongs to the cache kmalloc-cg-4k of size 4096
> The buggy address is located 3580 bytes inside of
> freed 4096-byte region [ffff888029fb8000, ffff888029fb9000)
>
> The buggy address belongs to the physical page:
> page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x29fb8
> head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
> memcg:ffff88803317c501
> anon flags: 0xfff00000000040(head|node=0|zone=1|lastcpupid=0x7ff)
> page_type: f5(slab)
> raw: 00fff00000000040 ffff88813ffb0500 0000000000000000 dead000000000001
> raw: 0000000000000000 0000000000040004 00000000f5000000 ffff88803317c501
> head: 00fff00000000040 ffff88813ffb0500 0000000000000000 dead000000000001
> head: 0000000000000000 0000000000040004 00000000f5000000 ffff88803317c501
> head: 00fff00000000003 ffffea0000a7ee01 00000000ffffffff 00000000ffffffff
> head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
> page dumped because: kasan: bad access detected
> page_owner tracks the page as allocated
> page last allocated via order 3, migratetype Unmovable, gfp_mask
> 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC),
>pid 11169, tgid 11169 (modprobe), ts 207829820236, free_ts
> 207789169305
> set_page_owner include/linux/page_owner.h:32 [inline]
> post_alloc_hook+0x234/0x290 mm/page_alloc.c:1846
> prep_new_page mm/page_alloc.c:1854 [inline]
> get_page_from_freelist+0x2365/0x2440 mm/page_alloc.c:3915
> __alloc_frozen_pages_noprof+0x181/0x370 mm/page_alloc.c:5210
> alloc_pages_mpol+0x232/0x4a0 mm/mempolicy.c:2486
> alloc_slab_page mm/slub.c:3075 [inline]
> allocate_slab+0x86/0x3b0 mm/slub.c:3248
> new_slab mm/slub.c:3302 [inline]
> ___slab_alloc+0xf2b/0x1960 mm/slub.c:4656
> __slab_alloc+0x65/0x100 mm/slub.c:4779
> __slab_alloc_node mm/slub.c:4855 [inline]
> slab_alloc_node mm/slub.c:5251 [inline]
> __do_kmalloc_node mm/slub.c:5656 [inline]
> __kvmalloc_node_noprof+0x6b6/0x920 mm/slub.c:7134
> seq_buf_alloc fs/seq_file.c:38 [inline]
> seq_read_iter+0x202/0xe20 fs/seq_file.c:210
> proc_reg_read_iter+0x1b7/0x280 fs/proc/inode.c:299
> new_sync_read fs/read_write.c:491 [inline]
> vfs_read+0x55a/0xa30 fs/read_write.c:572
> ksys_read+0x145/0x250 fs/read_write.c:715
> do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> do_syscall_64+0xfa/0xf80 arch/x86/entry/syscall_64.c:94
> entry_SYSCALL_64_after_hwframe+0x77/0x7f
> page last free pid 11127 tgid 11119 stack trace:
> reset_page_owner include/linux/page_owner.h:25 [inline]
> free_pages_prepare mm/page_alloc.c:1395 [inline]
> __free_frozen_pages+0xbc8/0xd30 mm/page_alloc.c:2943
> __folio_put+0x21b/0x2c0 mm/swap.c:112
> folio_put include/linux/mm.h:1612 [inline]
> put_page include/linux/mm.h:1681 [inline]
> do_exit+0x183b/0x2310 kernel/exit.c:1002
> do_group_exit+0x21c/0x2d0 kernel/exit.c:1112
> get_signal+0x1285/0x1340 kernel/signal.c:3034
> arch_do_signal_or_restart+0x9a/0x7a0 arch/x86/kernel/signal.c:337
> __exit_to_user_mode_loop kernel/entry/common.c:41 [inline]
> exit_to_user_mode_loop+0x87/0x4f0 kernel/entry/common.c:75
> __exit_to_user_mode_prepare include/linux/irq-entry-common.h:226 [inline]
> syscall_exit_to_user_mode_prepare include/linux/irq-entry-common.h:256 [inline]
> syscall_exit_to_user_mode_work include/linux/entry-common.h:159 [inline]
> syscall_exit_to_user_mode include/linux/entry-common.h:194 [inline]
> do_syscall_64+0x2d0/0xf80 arch/x86/entry/syscall_64.c:100
> entry_SYSCALL_64_after_hwframe+0x77/0x7f




> > The report shows the freed object is in kmalloc-cg-4k (size 4096):
> >
> > The buggy address belongs to the object at ffff888030eda000
> > which belongs to the cache kmalloc-cg-4k of size 4096
> >
> > struct macvlan_port fits this size (due to the large hash tables),
> > whereas struct macvlan_source_entry is much smaller.
> > The crash happens at offset 3580, which corresponds to the vlan_source_hash array inside the port:
> >
> > The race occurs in the register_netdevice() error path in macvlan_common_newlink():
> >
> > 1. netdev_rx_handler_register() succeeds
> > 2. register_netdevice() fails.
> > 3. macvlan_port_destroy() is called, performing a synchronous kfree(port).
> >
> > If a packet arrives during step 3,
> > macvlan_handle_frame() accesses port->vlan_source_hash (via macvlan_forward_source),
> > after it is freed.
> >
> > My patch restores the kfree_rcu behavior for the port (removed in 2016).
> > I believe both fixes are needed: yours for the source entries, and mine for the port itself.

> I do not think your patch is needed.

> Let's wait after my patch is merged, we will see if new syzbot reports
> are found.

Thanks for the detailed explanation and for clarifying the crash.
That makes sense.

Let’s see how things look once your patch is merged and syzbot
reruns. If new reports show a port lifetime issue, we can revisit
this then.

Thanks,
Boudewijn