| From 8f963115bff3ec748505cb414d4b3e3d4557e6e4 Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Wed, 30 Oct 2019 13:00:04 -0700 |
| Subject: [PATCH] net: annotate accesses to sk->sk_incoming_cpu |
| |
| commit 7170a977743b72cf3eb46ef6ef89885dc7ad3621 upstream. |
| |
| This socket field can be read and written by concurrent cpus. |
| |
| Use READ_ONCE() and WRITE_ONCE() annotations to document this, |
| and avoid some compiler 'optimizations'. |
| |
| KCSAN reported : |
| |
| BUG: KCSAN: data-race in tcp_v4_rcv / tcp_v4_rcv |
| |
| write to 0xffff88812220763c of 4 bytes by interrupt on cpu 0: |
| sk_incoming_cpu_update include/net/sock.h:953 [inline] |
| tcp_v4_rcv+0x1b3c/0x1bb0 net/ipv4/tcp_ipv4.c:1934 |
| ip_protocol_deliver_rcu+0x4d/0x420 net/ipv4/ip_input.c:204 |
| ip_local_deliver_finish+0x110/0x140 net/ipv4/ip_input.c:231 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip_local_deliver+0x133/0x210 net/ipv4/ip_input.c:252 |
| dst_input include/net/dst.h:442 [inline] |
| ip_rcv_finish+0x121/0x160 net/ipv4/ip_input.c:413 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip_rcv+0x18f/0x1a0 net/ipv4/ip_input.c:523 |
| __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 |
| __do_softirq+0x115/0x33f kernel/softirq.c:292 |
| do_softirq_own_stack+0x2a/0x40 arch/x86/entry/entry_64.S:1082 |
| do_softirq.part.0+0x6b/0x80 kernel/softirq.c:337 |
| do_softirq kernel/softirq.c:329 [inline] |
| __local_bh_enable_ip+0x76/0x80 kernel/softirq.c:189 |
| |
| read to 0xffff88812220763c of 4 bytes by interrupt on cpu 1: |
| sk_incoming_cpu_update include/net/sock.h:952 [inline] |
| tcp_v4_rcv+0x181a/0x1bb0 net/ipv4/tcp_ipv4.c:1934 |
| ip_protocol_deliver_rcu+0x4d/0x420 net/ipv4/ip_input.c:204 |
| ip_local_deliver_finish+0x110/0x140 net/ipv4/ip_input.c:231 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip_local_deliver+0x133/0x210 net/ipv4/ip_input.c:252 |
| dst_input include/net/dst.h:442 [inline] |
| ip_rcv_finish+0x121/0x160 net/ipv4/ip_input.c:413 |
| NF_HOOK include/linux/netfilter.h:305 [inline] |
| NF_HOOK include/linux/netfilter.h:299 [inline] |
| ip_rcv+0x18f/0x1a0 net/ipv4/ip_input.c:523 |
| __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 |
| __do_softirq+0x115/0x33f kernel/softirq.c:292 |
| run_ksoftirqd+0x46/0x60 kernel/softirq.c:603 |
| smpboot_thread_fn+0x37d/0x4a0 kernel/smpboot.c:165 |
| |
| Reported by Kernel Concurrency Sanitizer on: |
| CPU: 1 PID: 16 Comm: ksoftirqd/1 Not tainted 5.4.0-rc3+ #0 |
| Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 |
| |
| 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/sock.h b/include/net/sock.h |
| index 526de911cd91..8e6e348017f3 100644 |
| --- a/include/net/sock.h |
| +++ b/include/net/sock.h |
| @@ -949,8 +949,8 @@ static inline void sk_incoming_cpu_update(struct sock *sk) |
| { |
| int cpu = raw_smp_processor_id(); |
| |
| - if (unlikely(sk->sk_incoming_cpu != cpu)) |
| - sk->sk_incoming_cpu = cpu; |
| + if (unlikely(READ_ONCE(sk->sk_incoming_cpu) != cpu)) |
| + WRITE_ONCE(sk->sk_incoming_cpu, cpu); |
| } |
| |
| static inline void sock_rps_record_flow_hash(__u32 hash) |
| diff --git a/net/core/sock.c b/net/core/sock.c |
| index 3d54153b8325..97e4e1d14691 100644 |
| --- a/net/core/sock.c |
| +++ b/net/core/sock.c |
| @@ -1121,7 +1121,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, |
| break; |
| } |
| case SO_INCOMING_CPU: |
| - sk->sk_incoming_cpu = val; |
| + WRITE_ONCE(sk->sk_incoming_cpu, val); |
| break; |
| |
| case SO_CNX_ADVICE: |
| @@ -1470,7 +1470,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, |
| break; |
| |
| case SO_INCOMING_CPU: |
| - v.val = sk->sk_incoming_cpu; |
| + v.val = READ_ONCE(sk->sk_incoming_cpu); |
| break; |
| |
| case SO_MEMINFO: |
| diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c |
| index c4503073248b..f19cf93d160f 100644 |
| --- a/net/ipv4/inet_hashtables.c |
| +++ b/net/ipv4/inet_hashtables.c |
| @@ -240,7 +240,7 @@ static inline int compute_score(struct sock *sk, struct net *net, |
| return -1; |
| |
| score = sk->sk_family == PF_INET ? 2 : 1; |
| - if (sk->sk_incoming_cpu == raw_smp_processor_id()) |
| + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
| score++; |
| } |
| return score; |
| diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c |
| index 665f26e32d77..7b8ce13661c5 100644 |
| --- a/net/ipv4/udp.c |
| +++ b/net/ipv4/udp.c |
| @@ -399,7 +399,7 @@ static int compute_score(struct sock *sk, struct net *net, |
| return -1; |
| score += 4; |
| |
| - if (sk->sk_incoming_cpu == raw_smp_processor_id()) |
| + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
| score++; |
| return score; |
| } |
| diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c |
| index b2a55f300318..df28da487303 100644 |
| --- a/net/ipv6/inet6_hashtables.c |
| +++ b/net/ipv6/inet6_hashtables.c |
| @@ -105,7 +105,7 @@ static inline int compute_score(struct sock *sk, struct net *net, |
| return -1; |
| |
| score = 1; |
| - if (sk->sk_incoming_cpu == raw_smp_processor_id()) |
| + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
| score++; |
| } |
| return score; |
| diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c |
| index f0b5edd861d0..9011a750f74f 100644 |
| --- a/net/ipv6/udp.c |
| +++ b/net/ipv6/udp.c |
| @@ -145,7 +145,7 @@ static int compute_score(struct sock *sk, struct net *net, |
| return -1; |
| score++; |
| |
| - if (sk->sk_incoming_cpu == raw_smp_processor_id()) |
| + if (READ_ONCE(sk->sk_incoming_cpu) == raw_smp_processor_id()) |
| score++; |
| |
| return score; |
| -- |
| 2.7.4 |
| |