]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 12:48:41 +0000 (13:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 Nov 2018 12:48:41 +0000 (13:48 +0100)
added patches:
af_unix-move-unix_mknod-out-of-bindlock.patch

queue-3.18/af_unix-move-unix_mknod-out-of-bindlock.patch [new file with mode: 0644]
queue-3.18/series

diff --git a/queue-3.18/af_unix-move-unix_mknod-out-of-bindlock.patch b/queue-3.18/af_unix-move-unix_mknod-out-of-bindlock.patch
new file mode 100644 (file)
index 0000000..0e6aa77
--- /dev/null
@@ -0,0 +1,93 @@
+From 0fb44559ffd67de8517098b81f675fa0210f13f0 Mon Sep 17 00:00:00 2001
+From: WANG Cong <xiyou.wangcong@gmail.com>
+Date: Mon, 23 Jan 2017 11:17:35 -0800
+Subject: af_unix: move unix_mknod() out of bindlock
+
+From: WANG Cong <xiyou.wangcong@gmail.com>
+
+commit 0fb44559ffd67de8517098b81f675fa0210f13f0 upstream.
+
+Dmitry reported a deadlock scenario:
+
+unix_bind() path:
+u->bindlock ==> sb_writer
+
+do_splice() path:
+sb_writer ==> pipe->mutex ==> u->bindlock
+
+In the unix_bind() code path, unix_mknod() does not have to
+be done with u->bindlock held, since it is a pure fs operation,
+so we can just move unix_mknod() out.
+
+Reported-by: Dmitry Vyukov <dvyukov@google.com>
+Tested-by: Dmitry Vyukov <dvyukov@google.com>
+Cc: Rainer Weikusat <rweikusat@mobileactivedefense.com>
+Cc: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Petr Vorel <pvorel@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/unix/af_unix.c |   27 ++++++++++++++++-----------
+ 1 file changed, 16 insertions(+), 11 deletions(-)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -980,6 +980,7 @@ static int unix_bind(struct socket *sock
+       unsigned int hash;
+       struct unix_address *addr;
+       struct hlist_head *list;
++      struct path path = { NULL, NULL };
+       err = -EINVAL;
+       if (sunaddr->sun_family != AF_UNIX)
+@@ -995,9 +996,20 @@ static int unix_bind(struct socket *sock
+               goto out;
+       addr_len = err;
++      if (sun_path[0]) {
++              umode_t mode = S_IFSOCK |
++                     (SOCK_INODE(sock)->i_mode & ~current_umask());
++              err = unix_mknod(sun_path, mode, &path);
++              if (err) {
++                      if (err == -EEXIST)
++                              err = -EADDRINUSE;
++                      goto out;
++              }
++      }
++
+       err = mutex_lock_interruptible(&u->readlock);
+       if (err)
+-              goto out;
++              goto out_put;
+       err = -EINVAL;
+       if (u->addr)
+@@ -1014,16 +1026,6 @@ static int unix_bind(struct socket *sock
+       atomic_set(&addr->refcnt, 1);
+       if (sun_path[0]) {
+-              struct path path;
+-              umode_t mode = S_IFSOCK |
+-                     (SOCK_INODE(sock)->i_mode & ~current_umask());
+-              err = unix_mknod(sun_path, mode, &path);
+-              if (err) {
+-                      if (err == -EEXIST)
+-                              err = -EADDRINUSE;
+-                      unix_release_addr(addr);
+-                      goto out_up;
+-              }
+               addr->hash = UNIX_HASH_SIZE;
+               hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1);
+               spin_lock(&unix_table_lock);
+@@ -1050,6 +1052,9 @@ out_unlock:
+       spin_unlock(&unix_table_lock);
+ out_up:
+       mutex_unlock(&u->readlock);
++out_put:
++      if (err)
++              path_put(&path);
+ out:
+       return err;
+ }
index 039a4f2f2d01285e550f3cb0f43c3090d3b7167b..8b91adcbab326edcc18c30513d7661f664cd8170 100644 (file)
@@ -79,3 +79,4 @@ scsi-ufs-fix-race-between-clock-gating-and-devfreq-scaling-work.patch
 scsi-qla2xxx-do-not-queue-commands-when-unloading.patch
 tty-wipe-buffer.patch
 tty-wipe-buffer-if-not-echoing-data.patch
+af_unix-move-unix_mknod-out-of-bindlock.patch