Commit 22e5751b authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni

af_unix: Don't use spin_lock_nested() in copy_peercred().

When (AF_UNIX, SOCK_STREAM) socket connect()s to a listening socket,
the listener's sk_peer_pid/sk_peer_cred are copied to the client in
copy_peercred().

Then, two sk_peer_locks are held there; one is client's and another
is listener's.

However, the latter is not needed because we hold the listner's
unix_state_lock() there and unix_listen() cannot update the cred
concurrently.

Let's drop the unnecessary spin_lock() and use the bare spin_lock()
for the client to protect concurrent read by getsockopt(SO_PEERCRED).
Signed-off-by: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent e4bd881d
...@@ -772,19 +772,12 @@ static void update_peercred(struct sock *sk) ...@@ -772,19 +772,12 @@ static void update_peercred(struct sock *sk)
static void copy_peercred(struct sock *sk, struct sock *peersk) static void copy_peercred(struct sock *sk, struct sock *peersk)
{ {
if (sk < peersk) { lockdep_assert_held(&unix_sk(peersk)->lock);
spin_lock(&sk->sk_peer_lock);
spin_lock_nested(&peersk->sk_peer_lock, SINGLE_DEPTH_NESTING);
} else {
spin_lock(&peersk->sk_peer_lock);
spin_lock_nested(&sk->sk_peer_lock, SINGLE_DEPTH_NESTING);
}
sk->sk_peer_pid = get_pid(peersk->sk_peer_pid); spin_lock(&sk->sk_peer_lock);
sk->sk_peer_pid = get_pid(peersk->sk_peer_pid);
sk->sk_peer_cred = get_cred(peersk->sk_peer_cred); sk->sk_peer_cred = get_cred(peersk->sk_peer_cred);
spin_unlock(&sk->sk_peer_lock); spin_unlock(&sk->sk_peer_lock);
spin_unlock(&peersk->sk_peer_lock);
} }
static int unix_listen(struct socket *sock, int backlog) static int unix_listen(struct socket *sock, int backlog)
......
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