Commit 0aa3be7b authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni

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

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>
parent af4c733b
...@@ -65,7 +65,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb) ...@@ -65,7 +65,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)
u32 *buf; u32 *buf;
int i; int i;
if (sk->sk_state == TCP_LISTEN) { if (READ_ONCE(sk->sk_state) == TCP_LISTEN) {
spin_lock(&sk->sk_receive_queue.lock); spin_lock(&sk->sk_receive_queue.lock);
attr = nla_reserve(nlskb, UNIX_DIAG_ICONS, attr = nla_reserve(nlskb, UNIX_DIAG_ICONS,
...@@ -103,7 +103,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb) ...@@ -103,7 +103,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)
{ {
struct unix_diag_rqlen rql; 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_rqueue = sk->sk_receive_queue.qlen;
rql.udiag_wqueue = sk->sk_max_ack_backlog; rql.udiag_wqueue = sk->sk_max_ack_backlog;
} else { } else {
...@@ -136,7 +136,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r ...@@ -136,7 +136,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r
rep = nlmsg_data(nlh); rep = nlmsg_data(nlh);
rep->udiag_family = AF_UNIX; rep->udiag_family = AF_UNIX;
rep->udiag_type = sk->sk_type; rep->udiag_type = sk->sk_type;
rep->udiag_state = sk->sk_state; rep->udiag_state = READ_ONCE(sk->sk_state);
rep->pad = 0; rep->pad = 0;
rep->udiag_ino = sk_ino; rep->udiag_ino = sk_ino;
sock_diag_save_cookie(sk, rep->udiag_cookie); sock_diag_save_cookie(sk, rep->udiag_cookie);
...@@ -215,7 +215,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -215,7 +215,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
sk_for_each(sk, &net->unx.table.buckets[slot]) { sk_for_each(sk, &net->unx.table.buckets[slot]) {
if (num < s_num) if (num < s_num)
goto next; goto next;
if (!(req->udiag_states & (1 << sk->sk_state))) if (!(req->udiag_states & (1 << READ_ONCE(sk->sk_state))))
goto next; goto next;
if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk), if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk),
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment