Message ID | 20250204145549.1216254-2-idosch@nvidia.com (mailing list archive) |
---|---|
State | New |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | vxlan: Age FDB entries based on Rx traffic | expand |
On Tue, Feb 4, 2025 at 3:56 PM Ido Schimmel <idosch@nvidia.com> wrote: > > The 'used' and 'updated' fields in the FDB entry structure can be > accessed concurrently by multiple threads, leading to reports such as > [1]. Can be reproduced using [2]. > > Suppress these reports by annotating these accesses using > READ_ONCE() / WRITE_ONCE(). > > > Reviewed-by: Petr Machata <petrm@nvidia.com> > Signed-off-by: Ido Schimmel <idosch@nvidia.com> > Reviewed-by: Eric Dumazet <edumazet@google.com>
On 2/4/25 16:55, Ido Schimmel wrote: > The 'used' and 'updated' fields in the FDB entry structure can be > accessed concurrently by multiple threads, leading to reports such as > [1]. Can be reproduced using [2]. > > Suppress these reports by annotating these accesses using > READ_ONCE() / WRITE_ONCE(). > > [1] > BUG: KCSAN: data-race in vxlan_xmit / vxlan_xmit > > write to 0xffff942604d263a8 of 8 bytes by task 286 on cpu 0: > vxlan_xmit+0xb29/0x2380 > dev_hard_start_xmit+0x84/0x2f0 > __dev_queue_xmit+0x45a/0x1650 > packet_xmit+0x100/0x150 > packet_sendmsg+0x2114/0x2ac0 > __sys_sendto+0x318/0x330 > __x64_sys_sendto+0x76/0x90 > x64_sys_call+0x14e8/0x1c00 > do_syscall_64+0x9e/0x1a0 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > > read to 0xffff942604d263a8 of 8 bytes by task 287 on cpu 2: > vxlan_xmit+0xadf/0x2380 > dev_hard_start_xmit+0x84/0x2f0 > __dev_queue_xmit+0x45a/0x1650 > packet_xmit+0x100/0x150 > packet_sendmsg+0x2114/0x2ac0 > __sys_sendto+0x318/0x330 > __x64_sys_sendto+0x76/0x90 > x64_sys_call+0x14e8/0x1c00 > do_syscall_64+0x9e/0x1a0 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > > value changed: 0x00000000fffbac6e -> 0x00000000fffbac6f > > Reported by Kernel Concurrency Sanitizer on: > CPU: 2 UID: 0 PID: 287 Comm: mausezahn Not tainted 6.13.0-rc7-01544-gb4b270f11a02 #5 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.3-3.fc41 04/01/2014 > > [2] > #!/bin/bash > > set +H > echo whitelist > /sys/kernel/debug/kcsan > echo !vxlan_xmit > /sys/kernel/debug/kcsan > > ip link add name vx0 up type vxlan id 10010 dstport 4789 local 192.0.2.1 > bridge fdb add 00:11:22:33:44:55 dev vx0 self static dst 198.51.100.1 > taskset -c 0 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & > taskset -c 2 mausezahn vx0 -a own -b 00:11:22:33:44:55 -c 0 -q & > > Reviewed-by: Petr Machata <petrm@nvidia.com> > Signed-off-by: Ido Schimmel <idosch@nvidia.com> > --- > drivers/net/vxlan/vxlan_core.c | 18 +++++++++--------- > 1 file changed, 9 insertions(+), 9 deletions(-) > Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c index 05c10acb2a57..2f2c6606f719 100644 --- a/drivers/net/vxlan/vxlan_core.c +++ b/drivers/net/vxlan/vxlan_core.c @@ -227,9 +227,9 @@ static int vxlan_fdb_info(struct sk_buff *skb, struct vxlan_dev *vxlan, be32_to_cpu(fdb->vni))) goto nla_put_failure; - ci.ndm_used = jiffies_to_clock_t(now - fdb->used); + ci.ndm_used = jiffies_to_clock_t(now - READ_ONCE(fdb->used)); ci.ndm_confirmed = 0; - ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); + ci.ndm_updated = jiffies_to_clock_t(now - READ_ONCE(fdb->updated)); ci.ndm_refcnt = 0; if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) @@ -434,8 +434,8 @@ static struct vxlan_fdb *vxlan_find_mac(struct vxlan_dev *vxlan, struct vxlan_fdb *f; f = __vxlan_find_mac(vxlan, mac, vni); - if (f && f->used != jiffies) - f->used = jiffies; + if (f && READ_ONCE(f->used) != jiffies) + WRITE_ONCE(f->used, jiffies); return f; } @@ -1009,12 +1009,12 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, !(f->flags & NTF_VXLAN_ADDED_BY_USER)) { if (f->state != state) { f->state = state; - f->updated = jiffies; + WRITE_ONCE(f->updated, jiffies); notify = 1; } if (f->flags != fdb_flags) { f->flags = fdb_flags; - f->updated = jiffies; + WRITE_ONCE(f->updated, jiffies); notify = 1; } } @@ -1048,7 +1048,7 @@ static int vxlan_fdb_update_existing(struct vxlan_dev *vxlan, } if (ndm_flags & NTF_USE) - f->used = jiffies; + WRITE_ONCE(f->used, jiffies); if (notify) { if (rd == NULL) @@ -1481,7 +1481,7 @@ static enum skb_drop_reason vxlan_snoop(struct net_device *dev, src_mac, &rdst->remote_ip.sa, &src_ip->sa); rdst->remote_ip = *src_ip; - f->updated = jiffies; + WRITE_ONCE(f->updated, jiffies); vxlan_fdb_notify(vxlan, f, rdst, RTM_NEWNEIGH, true, NULL); } else { u32 hash_index = fdb_head_index(vxlan, src_mac, vni); @@ -2852,7 +2852,7 @@ static void vxlan_cleanup(struct timer_list *t) if (f->flags & NTF_EXT_LEARNED) continue; - timeout = f->used + vxlan->cfg.age_interval * HZ; + timeout = READ_ONCE(f->used) + vxlan->cfg.age_interval * HZ; if (time_before_eq(timeout, jiffies)) { netdev_dbg(vxlan->dev, "garbage collect %pM\n",