Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 45ad9f9a authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Greg Kroah-Hartman
Browse files

af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.



[ Upstream commit 0aa3be7b3e1f8f997312cc4705f8165e02806f8f ]

While dumping AF_UNIX sockets via UNIX_DIAG, sk->sk_state is read
locklessly.

Let's use READ_ONCE() there.

Note that the result could be inconsistent if the socket is dumped
during the state change.  This is common for other SOCK_DIAG and
similar interfaces.

Fixes: c9da99e6 ("unix_diag: Fixup RQLEN extension report")
Fixes: 2aac7a2c ("unix_diag: Pending connections IDs NLA")
Fixes: 45a96b9b ("unix_diag: Dumping all sockets core")
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 54d5a52b
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
	u32 *buf;
	int i;

	if (sk->sk_state == TCP_LISTEN) {
	if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
		spin_lock(&sk->sk_receive_queue.lock);

		attr = nla_reserve(nlskb, UNIX_DIAG_ICONS,
@@ -102,7 +102,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
{
	struct unix_diag_rqlen rql;

	if (sk->sk_state == TCP_LISTEN) {
	if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
		rql.udiag_rqueue = sk->sk_receive_queue.qlen;
		rql.udiag_wqueue = sk->sk_max_ack_backlog;
	} else {
@@ -135,7 +135,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
	rep = nlmsg_data(nlh);
	rep->udiag_family = AF_UNIX;
	rep->udiag_type = sk->sk_type;
	rep->udiag_state = sk->sk_state;
	rep->udiag_state = READ_ONCE(sk->sk_state);
	rep->pad = 0;
	rep->udiag_ino = sk_ino;
	sock_diag_save_cookie(sk, rep->udiag_cookie);
@@ -218,7 +218,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
				continue;
			if (num < s_num)
				goto next;
			if (!(req->udiag_states & (1 << sk->sk_state)))
			if (!(req->udiag_states & (1 << READ_ONCE(sk->sk_state))))
				goto next;
			if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk),
					 NETLINK_CB(cb->skb).portid,