[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20260108174504.86488-1-boudewijn@delta-utec.com>
Date: Thu, 8 Jan 2026 18:45:04 +0100
From: Boudewijn van der Heide <boudewijn@...ta-utec.com>
To: netdev@...r.kernel.org
Cc: andrew+netdev@...n.ch,
davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com,
linux-kernel@...r.kernel.org,
Boudewijn van der Heide <boudewijn@...ta-utec.com>,
syzbot+7182fbe91e58602ec1fe@...kaller.appspotmail.com
Subject: [PATCH net] macvlan: Fix use-after-free in macvlan_common_newlink
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@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=7182fbe91e58602ec1fe
Signed-off-by: Boudewijn van der Heide <boudewijn@...ta-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
Powered by blists - more mailing lists