Bug #446
openDAT: entries updated without locking
0%
Description
In batadv_dat_snoop_incoming_dhcp_ack() overwrites the MAC address of an DAT entry without ensuring that a parallel writer/reader is accessing the same entry. Culd this concurrent in-place update of the MAC address cause readers to fetch a torn address? Looking at batadv_dat_entry_add(), it updates the shared dat_entry->mac_addr using ether_addr_copy() without synchronization:
net/batman-adv/distributed-arp-table.c:batadv_dat_entry_add() {
...
if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr))
ether_addr_copy(dat_entry->mac_addr, mac_addr);
...
}
Concurrently, a reader such as batadv_dat_snoop_outgoing_arp_request() can fetch the same dat_entry via batadv_dat_entry_hash_find() and read the
mac_addr locklessly while it is being updated:
net/batman-adv/distributed-arp-table.c:batadv_dat_snoop_outgoing_arp_request() {
...
skb_new = batadv_dat_arp_create_reply(bat_priv, ip_dst, ip_src,
dat_entry->mac_addr,
hw_src, vid);
...
}
Can this lead to poisoning the remote node's ARP cache with a bogus MAC address if it reads a partially updated 6-byte address, causing connectivity loss?
See https://sashiko.dev/#/patchset/20260628-skb-post-realloc-v2-0-59a58f5a471b%40narfation.org?part=3
Updated by Sven Eckelmann 11 days ago
Potential workaround (without enrolling own locks and use native atomic 64 bit writes on supported architectures):
u64 u64_mac = ether_addr_to_u64(mac_addr); atomic64_set(&dat_entry->mac_addr, u64_mac);
And on the read path:
u64 u64_mac = atomic64_read(&dat_entry->mac_addr); u64_to_ether_addr(u64_mac, mac_addr);
Updated by Sven Eckelmann 4 days ago
- Status changed from New to In Progress
- Target version set to 2026.3