]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
af_unix: Don't use spin_lock_nested() in copy_peercred().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Thu, 20 Jun 2024 20:56:23 +0000 (13:56 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 25 Jun 2024 09:10:19 +0000 (11:10 +0200)
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: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/unix/af_unix.c

index 3d0ace7ca0177886bf5517ed3ac292e5381c22b1..103a7909cb1a82b4ed47c2354221cfab1ff9e6c4 100644 (file)
@@ -772,19 +772,12 @@ static void update_peercred(struct sock *sk)
 
 static void copy_peercred(struct sock *sk, struct sock *peersk)
 {
-       if (sk < peersk) {
-               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);
-       }
+       lockdep_assert_held(&unix_sk(peersk)->lock);
 
-       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);
-
        spin_unlock(&sk->sk_peer_lock);
-       spin_unlock(&peersk->sk_peer_lock);
 }
 
 static int unix_listen(struct socket *sock, int backlog)