Skip to content

Commit 2e207cf

Browse files
CIQ Kernel Automationroxanan1996
authored andcommitted
macvlan: fix possible UAF in macvlan_forward_source()
jira VULN-174917 cve CVE-2026-23001 commit-author Eric Dumazet <edumazet@google.com> commit 7470a7a Add RCU protection on (struct macvlan_source_entry)->vlan. Whenever macvlan_hash_del_source() is called, we must clear entry->vlan pointer before RCU grace period starts. This allows macvlan_forward_source() to skip over entries queued for freeing. Note that macvlan_dev are already RCU protected, as they are embedded in a standard netdev (netdev_priv(ndev)). Fixes: 79cf79a ("macvlan: add source mode") Reported-by: syzbot+7182fbe91e58602ec1fe@syzkaller.appspotmail.com https: //lore.kernel.org/netdev/695fb1e8.050a0220.1c677c.039f.GAE@google.com/T/#u Signed-off-by: Eric Dumazet <edumazet@google.com> Link: https://patch.msgid.link/20260108133651.1130486-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit 7470a7a) Signed-off-by: CIQ Kernel Automation <ciq_kernel_automation@ciq.com>
1 parent 5b870e1 commit 2e207cf

1 file changed

Lines changed: 13 additions & 7 deletions

File tree

drivers/net/macvlan.c

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ struct macvlan_port {
5656

5757
struct macvlan_source_entry {
5858
struct hlist_node hlist;
59-
struct macvlan_dev *vlan;
59+
struct macvlan_dev __rcu *vlan;
6060
unsigned char addr[6+2] __aligned(sizeof(u16));
6161
struct rcu_head rcu;
6262
};
@@ -143,7 +143,7 @@ static struct macvlan_source_entry *macvlan_hash_lookup_source(
143143

144144
hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
145145
if (ether_addr_equal_64bits(entry->addr, addr) &&
146-
entry->vlan == vlan)
146+
rcu_access_pointer(entry->vlan) == vlan)
147147
return entry;
148148
}
149149
return NULL;
@@ -165,7 +165,7 @@ static int macvlan_hash_add_source(struct macvlan_dev *vlan,
165165
return -ENOMEM;
166166

167167
ether_addr_copy(entry->addr, addr);
168-
entry->vlan = vlan;
168+
RCU_INIT_POINTER(entry->vlan, vlan);
169169
h = &port->vlan_source_hash[macvlan_eth_hash(addr)];
170170
hlist_add_head_rcu(&entry->hlist, h);
171171
vlan->macaddr_count++;
@@ -184,6 +184,7 @@ static void macvlan_hash_add(struct macvlan_dev *vlan)
184184

185185
static void macvlan_hash_del_source(struct macvlan_source_entry *entry)
186186
{
187+
RCU_INIT_POINTER(entry->vlan, NULL);
187188
hlist_del_rcu(&entry->hlist);
188189
kfree_rcu(entry, rcu);
189190
}
@@ -382,7 +383,7 @@ static void macvlan_flush_sources(struct macvlan_port *port,
382383
int i;
383384

384385
hash_for_each_safe(port->vlan_source_hash, i, next, entry, hlist)
385-
if (entry->vlan == vlan)
386+
if (rcu_access_pointer(entry->vlan) == vlan)
386387
macvlan_hash_del_source(entry);
387388

388389
vlan->macaddr_count = 0;
@@ -425,9 +426,14 @@ static bool macvlan_forward_source(struct sk_buff *skb,
425426

426427
hlist_for_each_entry_rcu(entry, h, hlist) {
427428
if (ether_addr_equal_64bits(entry->addr, addr)) {
428-
if (entry->vlan->flags & MACVLAN_FLAG_NODST)
429+
struct macvlan_dev *vlan = rcu_dereference(entry->vlan);
430+
431+
if (!vlan)
432+
continue;
433+
434+
if (vlan->flags & MACVLAN_FLAG_NODST)
429435
consume = true;
430-
macvlan_forward_source_one(skb, entry->vlan);
436+
macvlan_forward_source_one(skb, vlan);
431437
}
432438
}
433439

@@ -1646,7 +1652,7 @@ static int macvlan_fill_info_macaddr(struct sk_buff *skb,
16461652
struct macvlan_source_entry *entry;
16471653

16481654
hlist_for_each_entry_rcu(entry, h, hlist, lockdep_rtnl_is_held()) {
1649-
if (entry->vlan != vlan)
1655+
if (rcu_access_pointer(entry->vlan) != vlan)
16501656
continue;
16511657
if (nla_put(skb, IFLA_MACVLAN_MACADDR, ETH_ALEN, entry->addr))
16521658
return 1;

0 commit comments

Comments
 (0)