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 --- 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