]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Thu, 20 Jun 2024 20:56:21 +0000 (13:56 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 25 Jun 2024 09:10:18 +0000 (11:10 +0200)
init_peercred() is called in 3 places:

  1. socketpair() : both sockets
  2. connect()    : child socket
  3. listen()     : listening socket

The first two need not hold sk_peer_lock because no one can
touch the socket.

Let's set cred/pid without holding lock for the two cases and
rename the old init_peercred() to update_peercred() to properly
reflect the use case.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/unix/af_unix.c

index 89675879038d381b36dc87d7a61a7fa98c82925c..d11664c2faad0ff76159ce40145e76fecdfc21d7 100644 (file)
@@ -750,6 +750,12 @@ static void unix_release_sock(struct sock *sk, int embrion)
 }
 
 static void init_peercred(struct sock *sk)
+{
+       sk->sk_peer_pid = get_pid(task_tgid(current));
+       sk->sk_peer_cred = get_current_cred();
+}
+
+static void update_peercred(struct sock *sk)
 {
        const struct cred *old_cred;
        struct pid *old_pid;
@@ -757,8 +763,7 @@ static void init_peercred(struct sock *sk)
        spin_lock(&sk->sk_peer_lock);
        old_pid = sk->sk_peer_pid;
        old_cred = sk->sk_peer_cred;
-       sk->sk_peer_pid  = get_pid(task_tgid(current));
-       sk->sk_peer_cred = get_current_cred();
+       init_peercred(sk);
        spin_unlock(&sk->sk_peer_lock);
 
        put_pid(old_pid);
@@ -810,7 +815,7 @@ static int unix_listen(struct socket *sock, int backlog)
        WRITE_ONCE(sk->sk_state, TCP_LISTEN);
 
        /* set credentials so connect can copy them */
-       init_peercred(sk);
+       update_peercred(sk);
        err = 0;
 
 out_unlock: