| From 9f949630b4e5476d430d7d485ae8b1e9a2750556 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Tue, 29 Oct 2019 10:54:44 -0700 |
| Subject: [PATCH] net: annotate lockless accesses to sk->sk_napi_id |
| |
| commit ee8d153d46a3b98c064ee15c0c0a3bbf1450e5a1 upstream. |
| |
| We already annotated most accesses to sk->sk_napi_id |
| |
| We missed sk_mark_napi_id() and sk_mark_napi_id_once() |
| which might be called without socket lock held in UDP stack. |
| |
| KCSAN reported : |
| BUG: KCSAN: data-race in udpv6_queue_rcv_one_skb / udpv6_queue_rcv_one_skb |
| |
| write to 0xffff888121c6d108 of 4 bytes by interrupt on cpu 0: |
| sk_mark_napi_id include/net/busy_poll.h:125 [inline] |
| __udpv6_queue_rcv_skb net/ipv6/udp.c:571 [inline] |
| udpv6_queue_rcv_one_skb+0x70c/0xb40 net/ipv6/udp.c:672 |
| udpv6_queue_rcv_skb+0xb5/0x400 net/ipv6/udp.c:689 |
| udp6_unicast_rcv_skb.isra.0+0xd7/0x180 net/ipv6/udp.c:832 |
| __udp6_lib_rcv+0x69c/0x1770 net/ipv6/udp.c:913 |
| udpv6_rcv+0x2b/0x40 net/ipv6/udp.c:1015 |
| ip6_protocol_deliver_rcu+0x22a/0xbe0 net/ipv6/ip6_input.c:409 |
| ip6_input_finish+0x30/0x50 net/ipv6/ip6_input.c:450 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip6_input+0x177/0x190 net/ipv6/ip6_input.c:459 |
| dst_input include/net/dst.h:442 [inline] |
| ip6_rcv_finish+0x110/0x140 net/ipv6/ip6_input.c:76 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ipv6_rcv+0x1a1/0x1b0 net/ipv6/ip6_input.c:284 |
| __netif_receive_skb_one_core+0xa7/0xe0 net/core/dev.c:5010 |
| __netif_receive_skb+0x37/0xf0 net/core/dev.c:5124 |
| process_backlog+0x1d3/0x420 net/core/dev.c:5955 |
| napi_poll net/core/dev.c:6392 [inline] |
| net_rx_action+0x3ae/0xa90 net/core/dev.c:6460 |
| |
| write to 0xffff888121c6d108 of 4 bytes by interrupt on cpu 1: |
| sk_mark_napi_id include/net/busy_poll.h:125 [inline] |
| __udpv6_queue_rcv_skb net/ipv6/udp.c:571 [inline] |
| udpv6_queue_rcv_one_skb+0x70c/0xb40 net/ipv6/udp.c:672 |
| udpv6_queue_rcv_skb+0xb5/0x400 net/ipv6/udp.c:689 |
| udp6_unicast_rcv_skb.isra.0+0xd7/0x180 net/ipv6/udp.c:832 |
| __udp6_lib_rcv+0x69c/0x1770 net/ipv6/udp.c:913 |
| udpv6_rcv+0x2b/0x40 net/ipv6/udp.c:1015 |
| ip6_protocol_deliver_rcu+0x22a/0xbe0 net/ipv6/ip6_input.c:409 |
| ip6_input_finish+0x30/0x50 net/ipv6/ip6_input.c:450 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip6_input+0x177/0x190 net/ipv6/ip6_input.c:459 |
| dst_input include/net/dst.h:442 [inline] |
| ip6_rcv_finish+0x110/0x140 net/ipv6/ip6_input.c:76 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ipv6_rcv+0x1a1/0x1b0 net/ipv6/ip6_input.c:284 |
| __netif_receive_skb_one_core+0xa7/0xe0 net/core/dev.c:5010 |
| __netif_receive_skb+0x37/0xf0 net/core/dev.c:5124 |
| process_backlog+0x1d3/0x420 net/core/dev.c:5955 |
| |
| Reported by Kernel Concurrency Sanitizer on: |
| CPU: 1 PID: 10890 Comm: syz-executor.0 Not tainted 5.4.0-rc3+ #0 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 |
| |
| Fixes: e68b6e50fa35 ("udp: enable busy polling for all sockets") |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Reported-by: syzbot <syzkaller@googlegroups.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/include/net/busy_poll.h b/include/net/busy_poll.h |
| index 127a5c4e3699..86e028388bad 100644 |
| --- a/include/net/busy_poll.h |
| +++ b/include/net/busy_poll.h |
| @@ -122,7 +122,7 @@ static inline void skb_mark_napi_id(struct sk_buff *skb, |
| static inline void sk_mark_napi_id(struct sock *sk, const struct sk_buff *skb) |
| { |
| #ifdef CONFIG_NET_RX_BUSY_POLL |
| - sk->sk_napi_id = skb->napi_id; |
| + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); |
| #endif |
| sk_rx_queue_set(sk, skb); |
| } |
| @@ -132,8 +132,8 @@ static inline void sk_mark_napi_id_once(struct sock *sk, |
| const struct sk_buff *skb) |
| { |
| #ifdef CONFIG_NET_RX_BUSY_POLL |
| - if (!sk->sk_napi_id) |
| - sk->sk_napi_id = skb->napi_id; |
| + if (!READ_ONCE(sk->sk_napi_id)) |
| + WRITE_ONCE(sk->sk_napi_id, skb->napi_id); |
| #endif |
| } |
| |
| -- |
| 2.7.4 |
| |