Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: add {READ|WRITE}_ONCE() annotations on ->rskq_accept_head

reqsk_queue_empty() is called from inet_csk_listen_poll() while
other cpus might write ->rskq_accept_head value.

Use {READ|WRITE}_ONCE() to avoid compiler tricks
and potential KCSAN splats.

Fixes: fff1f3001cc5 ("tcp: add a spinlock to protect struct request_sock_queue")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>

authored by

Eric Dumazet and committed by
Jakub Kicinski
60b173ca 503978ac

+4 -4
+1 -1
drivers/xen/pvcalls-back.c
··· 775 775 mappass->reqcopy = *req; 776 776 icsk = inet_csk(mappass->sock->sk); 777 777 queue = &icsk->icsk_accept_queue; 778 - data = queue->rskq_accept_head != NULL; 778 + data = READ_ONCE(queue->rskq_accept_head) != NULL; 779 779 if (data) { 780 780 mappass->reqcopy.cmd = 0; 781 781 ret = 0;
+2 -2
include/net/request_sock.h
··· 185 185 186 186 static inline bool reqsk_queue_empty(const struct request_sock_queue *queue) 187 187 { 188 - return queue->rskq_accept_head == NULL; 188 + return READ_ONCE(queue->rskq_accept_head) == NULL; 189 189 } 190 190 191 191 static inline struct request_sock *reqsk_queue_remove(struct request_sock_queue *queue, ··· 197 197 req = queue->rskq_accept_head; 198 198 if (req) { 199 199 sk_acceptq_removed(parent); 200 - queue->rskq_accept_head = req->dl_next; 200 + WRITE_ONCE(queue->rskq_accept_head, req->dl_next); 201 201 if (queue->rskq_accept_head == NULL) 202 202 queue->rskq_accept_tail = NULL; 203 203 }
+1 -1
net/ipv4/inet_connection_sock.c
··· 934 934 req->sk = child; 935 935 req->dl_next = NULL; 936 936 if (queue->rskq_accept_head == NULL) 937 - queue->rskq_accept_head = req; 937 + WRITE_ONCE(queue->rskq_accept_head, req); 938 938 else 939 939 queue->rskq_accept_tail->dl_next = req; 940 940 queue->rskq_accept_tail = req;