Skip to content

Commit 0a9e579

Browse files
edumazetklassert
authored andcommitted
xfrm: annotate data-race around use_time
KCSAN reported multiple cpus can update use_time at the same time. Adds READ_ONCE()/WRITE_ONCE() annotations. Note that 32bit arches are not fully protected, but they will probably no longer be supported/used in 2106. BUG: KCSAN: data-race in __xfrm_policy_check / __xfrm_policy_check write to 0xffff88813e7ec108 of 8 bytes by interrupt on cpu 0: __xfrm_policy_check+0x6ae/0x17f0 net/xfrm/xfrm_policy.c:3664 __xfrm_policy_check2 include/net/xfrm.h:1174 [inline] xfrm_policy_check include/net/xfrm.h:1179 [inline] xfrm6_policy_check+0x2e9/0x320 include/net/xfrm.h:1189 udpv6_queue_rcv_one_skb+0x48/0xa30 net/ipv6/udp.c:703 udpv6_queue_rcv_skb+0x2d6/0x310 net/ipv6/udp.c:792 udp6_unicast_rcv_skb+0x16b/0x190 net/ipv6/udp.c:935 __udp6_lib_rcv+0x84b/0x9b0 net/ipv6/udp.c:1020 udpv6_rcv+0x4b/0x50 net/ipv6/udp.c:1133 ip6_protocol_deliver_rcu+0x99e/0x1020 net/ipv6/ip6_input.c:439 ip6_input_finish net/ipv6/ip6_input.c:484 [inline] NF_HOOK include/linux/netfilter.h:302 [inline] ip6_input+0xca/0x180 net/ipv6/ip6_input.c:493 dst_input include/net/dst.h:454 [inline] ip6_rcv_finish+0x1e9/0x2d0 net/ipv6/ip6_input.c:79 NF_HOOK include/linux/netfilter.h:302 [inline] ipv6_rcv+0x85/0x140 net/ipv6/ip6_input.c:309 __netif_receive_skb_one_core net/core/dev.c:5482 [inline] __netif_receive_skb+0x8b/0x1b0 net/core/dev.c:5596 process_backlog+0x23f/0x3b0 net/core/dev.c:5924 __napi_poll+0x65/0x390 net/core/dev.c:6485 napi_poll net/core/dev.c:6552 [inline] net_rx_action+0x37e/0x730 net/core/dev.c:6663 __do_softirq+0xf2/0x2c7 kernel/softirq.c:571 do_softirq+0xb1/0xf0 kernel/softirq.c:472 __local_bh_enable_ip+0x6f/0x80 kernel/softirq.c:396 __raw_read_unlock_bh include/linux/rwlock_api_smp.h:257 [inline] _raw_read_unlock_bh+0x17/0x20 kernel/locking/spinlock.c:284 wg_socket_send_skb_to_peer+0x107/0x120 drivers/net/wireguard/socket.c:184 wg_packet_create_data_done drivers/net/wireguard/send.c:251 [inline] wg_packet_tx_worker+0x142/0x360 drivers/net/wireguard/send.c:276 process_one_work+0x3d3/0x720 kernel/workqueue.c:2289 worker_thread+0x618/0xa70 kernel/workqueue.c:2436 kthread+0x1a9/0x1e0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308 write to 0xffff88813e7ec108 of 8 bytes by interrupt on cpu 1: __xfrm_policy_check+0x6ae/0x17f0 net/xfrm/xfrm_policy.c:3664 __xfrm_policy_check2 include/net/xfrm.h:1174 [inline] xfrm_policy_check include/net/xfrm.h:1179 [inline] xfrm6_policy_check+0x2e9/0x320 include/net/xfrm.h:1189 udpv6_queue_rcv_one_skb+0x48/0xa30 net/ipv6/udp.c:703 udpv6_queue_rcv_skb+0x2d6/0x310 net/ipv6/udp.c:792 udp6_unicast_rcv_skb+0x16b/0x190 net/ipv6/udp.c:935 __udp6_lib_rcv+0x84b/0x9b0 net/ipv6/udp.c:1020 udpv6_rcv+0x4b/0x50 net/ipv6/udp.c:1133 ip6_protocol_deliver_rcu+0x99e/0x1020 net/ipv6/ip6_input.c:439 ip6_input_finish net/ipv6/ip6_input.c:484 [inline] NF_HOOK include/linux/netfilter.h:302 [inline] ip6_input+0xca/0x180 net/ipv6/ip6_input.c:493 dst_input include/net/dst.h:454 [inline] ip6_rcv_finish+0x1e9/0x2d0 net/ipv6/ip6_input.c:79 NF_HOOK include/linux/netfilter.h:302 [inline] ipv6_rcv+0x85/0x140 net/ipv6/ip6_input.c:309 __netif_receive_skb_one_core net/core/dev.c:5482 [inline] __netif_receive_skb+0x8b/0x1b0 net/core/dev.c:5596 process_backlog+0x23f/0x3b0 net/core/dev.c:5924 __napi_poll+0x65/0x390 net/core/dev.c:6485 napi_poll net/core/dev.c:6552 [inline] net_rx_action+0x37e/0x730 net/core/dev.c:6663 __do_softirq+0xf2/0x2c7 kernel/softirq.c:571 do_softirq+0xb1/0xf0 kernel/softirq.c:472 __local_bh_enable_ip+0x6f/0x80 kernel/softirq.c:396 __raw_read_unlock_bh include/linux/rwlock_api_smp.h:257 [inline] _raw_read_unlock_bh+0x17/0x20 kernel/locking/spinlock.c:284 wg_socket_send_skb_to_peer+0x107/0x120 drivers/net/wireguard/socket.c:184 wg_packet_create_data_done drivers/net/wireguard/send.c:251 [inline] wg_packet_tx_worker+0x142/0x360 drivers/net/wireguard/send.c:276 process_one_work+0x3d3/0x720 kernel/workqueue.c:2289 worker_thread+0x618/0xa70 kernel/workqueue.c:2436 kthread+0x1a9/0x1e0 kernel/kthread.c:376 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:308 value changed: 0x0000000063c62d6f -> 0x0000000063c62d70 Reported by Kernel Concurrency Sanitizer on: CPU: 1 PID: 4185 Comm: kworker/1:2 Tainted: G W 6.2.0-rc4-syzkaller-00009-gd532dd102151-dirty #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 Workqueue: wg-crypt-wg0 wg_packet_tx_worker Fixes: 1da177e ("Linux-2.6.12-rc2") Reported-by: syzbot <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Cc: Steffen Klassert <[email protected]> Cc: Arnd Bergmann <[email protected]> Acked-by: Arnd Bergmann <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 195e4aa commit 0a9e579

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

net/xfrm/xfrm_policy.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ static void xfrm_policy_timer(struct timer_list *t)
336336
}
337337
if (xp->lft.hard_use_expires_seconds) {
338338
time64_t tmo = xp->lft.hard_use_expires_seconds +
339-
(xp->curlft.use_time ? : xp->curlft.add_time) - now;
339+
(READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now;
340340
if (tmo <= 0)
341341
goto expired;
342342
if (tmo < next)
@@ -354,7 +354,7 @@ static void xfrm_policy_timer(struct timer_list *t)
354354
}
355355
if (xp->lft.soft_use_expires_seconds) {
356356
time64_t tmo = xp->lft.soft_use_expires_seconds +
357-
(xp->curlft.use_time ? : xp->curlft.add_time) - now;
357+
(READ_ONCE(xp->curlft.use_time) ? : xp->curlft.add_time) - now;
358358
if (tmo <= 0) {
359359
warn = 1;
360360
tmo = XFRM_KM_TIMEOUT;
@@ -3661,7 +3661,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
36613661
return 1;
36623662
}
36633663

3664-
pol->curlft.use_time = ktime_get_real_seconds();
3664+
/* This lockless write can happen from different cpus. */
3665+
WRITE_ONCE(pol->curlft.use_time, ktime_get_real_seconds());
36653666

36663667
pols[0] = pol;
36673668
npols++;
@@ -3676,7 +3677,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
36763677
xfrm_pol_put(pols[0]);
36773678
return 0;
36783679
}
3679-
pols[1]->curlft.use_time = ktime_get_real_seconds();
3680+
/* This write can happen from different cpus. */
3681+
WRITE_ONCE(pols[1]->curlft.use_time,
3682+
ktime_get_real_seconds());
36803683
npols++;
36813684
}
36823685
}

net/xfrm/xfrm_state.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
595595
}
596596
if (x->lft.hard_use_expires_seconds) {
597597
time64_t tmo = x->lft.hard_use_expires_seconds +
598-
(x->curlft.use_time ? : now) - now;
598+
(READ_ONCE(x->curlft.use_time) ? : now) - now;
599599
if (tmo <= 0)
600600
goto expired;
601601
if (tmo < next)
@@ -617,7 +617,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
617617
}
618618
if (x->lft.soft_use_expires_seconds) {
619619
time64_t tmo = x->lft.soft_use_expires_seconds +
620-
(x->curlft.use_time ? : now) - now;
620+
(READ_ONCE(x->curlft.use_time) ? : now) - now;
621621
if (tmo <= 0)
622622
warn = 1;
623623
else if (tmo < next)
@@ -1906,7 +1906,7 @@ int xfrm_state_update(struct xfrm_state *x)
19061906

19071907
hrtimer_start(&x1->mtimer, ktime_set(1, 0),
19081908
HRTIMER_MODE_REL_SOFT);
1909-
if (x1->curlft.use_time)
1909+
if (READ_ONCE(x1->curlft.use_time))
19101910
xfrm_state_check_expire(x1);
19111911

19121912
if (x->props.smark.m || x->props.smark.v || x->if_id) {
@@ -1940,8 +1940,8 @@ int xfrm_state_check_expire(struct xfrm_state *x)
19401940
{
19411941
xfrm_dev_state_update_curlft(x);
19421942

1943-
if (!x->curlft.use_time)
1944-
x->curlft.use_time = ktime_get_real_seconds();
1943+
if (!READ_ONCE(x->curlft.use_time))
1944+
WRITE_ONCE(x->curlft.use_time, ktime_get_real_seconds());
19451945

19461946
if (x->curlft.bytes >= x->lft.hard_byte_limit ||
19471947
x->curlft.packets >= x->lft.hard_packet_limit) {

0 commit comments

Comments
 (0)