diff options
| author | Greg Kroah-Hartman <gregkh@google.com> | 2021-10-09 13:42:14 +0200 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@google.com> | 2021-10-09 13:42:14 +0200 |
| commit | b8841c043898aca3016c3f0432be5332fb3f9b17 (patch) | |
| tree | 7d938835bbde9d177aa3346d31d753220ae8a951 /net/unix/af_unix.c | |
| parent | 908f942eb5a641a982f78aee19cea4a344631920 (diff) | |
| parent | 1392fe82d7fba00ba4a8e01968935f2b2085d5a4 (diff) | |
Merge 4.4.288 into android-4.4-p
Changes in 4.4.288
af_unix: fix races in sk_peer_pid and sk_peer_cred accesses
xen-netback: correct success/error reporting for the SKB-with-fraglist case
sparc64: fix pci_iounmap() when CONFIG_PCI is not set
ext2: fix sleeping in atomic bugs on error
scsi: sd: Free scsi_disk device via put_device()
usb: testusb: Fix for showing the connection speed
libata: Add ATA_HORKAGE_NO_NCQ_ON_ATI for Samsung 860 and 870 SSD.
Linux 4.4.288
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Id6d93b8ff677b720c77d0f1384141464e0aaf1e8
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index cb9911dcafdb..242d170991b4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -594,20 +594,42 @@ static void unix_release_sock(struct sock *sk, int embrion) static void init_peercred(struct sock *sk) { - put_pid(sk->sk_peer_pid); - if (sk->sk_peer_cred) - put_cred(sk->sk_peer_cred); + const struct cred *old_cred; + struct pid *old_pid; + + 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(); + spin_unlock(&sk->sk_peer_lock); + + put_pid(old_pid); + put_cred(old_cred); } static void copy_peercred(struct sock *sk, struct sock *peersk) { - put_pid(sk->sk_peer_pid); - if (sk->sk_peer_cred) - put_cred(sk->sk_peer_cred); + const struct cred *old_cred; + struct pid *old_pid; + + 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); + } + old_pid = sk->sk_peer_pid; + old_cred = sk->sk_peer_cred; 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); + + put_pid(old_pid); + put_cred(old_cred); } static int unix_listen(struct socket *sock, int backlog) |
