Commit faf489e6 authored by Kuniyuki Iwashima's avatar Kuniyuki Iwashima Committed by Paolo Abeni
Browse files

af_unix: Set sk_peer_pid/sk_peer_cred locklessly for new socket.



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: default avatarKuniyuki Iwashima <kuniyu@amazon.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8647ece4
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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: