--- /dev/null
+From 38f7bd94a97b542de86a2be9229289717e33a7a4 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 1 Sep 2016 14:56:49 -0700
+Subject: Revert "af_unix: Fix splice-bind deadlock"
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 38f7bd94a97b542de86a2be9229289717e33a7a4 upstream.
+
+This reverts commit c845acb324aa85a39650a14e7696982ceea75dc1.
+
+It turns out that it just replaces one deadlock with another one: we can
+still get the wrong lock ordering with the readlock due to overlayfs
+calling back into the filesystem layer and still taking the vfs locks
+after the readlock.
+
+The proper solution ends up being to just split the readlock into two
+pieces: the bind lock (taken *outside* the vfs locks) and the IO lock
+(taken *inside* the filesystem locks). The two locks are independent
+anyway.
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Reviewed-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/unix/af_unix.c | 68 +++++++++++++++++++++--------------------------------
+ 1 file changed, 27 insertions(+), 41 deletions(-)
+
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -940,20 +940,32 @@ fail:
+ return NULL;
+ }
+
+-static int unix_mknod(struct dentry *dentry, struct path *path, umode_t mode,
+- struct path *res)
++static int unix_mknod(const char *sun_path, umode_t mode, struct path *res)
+ {
+- int err;
+-
+- err = security_path_mknod(path, dentry, mode, 0);
++ struct dentry *dentry;
++ struct path path;
++ int err = 0;
++ /*
++ * Get the parent directory, calculate the hash for last
++ * component.
++ */
++ dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
++ err = PTR_ERR(dentry);
++ if (IS_ERR(dentry))
++ return err;
++
++ /*
++ * All right, let's create it.
++ */
++ err = security_path_mknod(&path, dentry, mode, 0);
+ if (!err) {
+- err = vfs_mknod(d_inode(path->dentry), dentry, mode, 0);
++ err = vfs_mknod(d_inode(path.dentry), dentry, mode, 0);
+ if (!err) {
+- res->mnt = mntget(path->mnt);
++ res->mnt = mntget(path.mnt);
+ res->dentry = dget(dentry);
+ }
+ }
+-
++ done_path_create(&path, dentry);
+ return err;
+ }
+
+@@ -964,12 +976,10 @@ static int unix_bind(struct socket *sock
+ struct unix_sock *u = unix_sk(sk);
+ struct sockaddr_un *sunaddr = (struct sockaddr_un *)uaddr;
+ char *sun_path = sunaddr->sun_path;
+- int err, name_err;
++ int err;
+ unsigned int hash;
+ struct unix_address *addr;
+ struct hlist_head *list;
+- struct path path;
+- struct dentry *dentry;
+
+ err = -EINVAL;
+ if (sunaddr->sun_family != AF_UNIX)
+@@ -985,34 +995,14 @@ static int unix_bind(struct socket *sock
+ goto out;
+ addr_len = err;
+
+- name_err = 0;
+- dentry = NULL;
+- if (sun_path[0]) {
+- /* Get the parent directory, calculate the hash for last
+- * component.
+- */
+- dentry = kern_path_create(AT_FDCWD, sun_path, &path, 0);
+-
+- if (IS_ERR(dentry)) {
+- /* delay report until after 'already bound' check */
+- name_err = PTR_ERR(dentry);
+- dentry = NULL;
+- }
+- }
+-
+ err = mutex_lock_interruptible(&u->readlock);
+ if (err)
+- goto out_path;
++ goto out;
+
+ err = -EINVAL;
+ if (u->addr)
+ goto out_up;
+
+- if (name_err) {
+- err = name_err == -EEXIST ? -EADDRINUSE : name_err;
+- goto out_up;
+- }
+-
+ err = -ENOMEM;
+ addr = kmalloc(sizeof(*addr)+addr_len, GFP_KERNEL);
+ if (!addr)
+@@ -1023,11 +1013,11 @@ static int unix_bind(struct socket *sock
+ addr->hash = hash ^ sk->sk_type;
+ atomic_set(&addr->refcnt, 1);
+
+- if (dentry) {
+- struct path u_path;
++ if (sun_path[0]) {
++ struct path path;
+ umode_t mode = S_IFSOCK |
+ (SOCK_INODE(sock)->i_mode & ~current_umask());
+- err = unix_mknod(dentry, &path, mode, &u_path);
++ err = unix_mknod(sun_path, mode, &path);
+ if (err) {
+ if (err == -EEXIST)
+ err = -EADDRINUSE;
+@@ -1035,9 +1025,9 @@ static int unix_bind(struct socket *sock
+ goto out_up;
+ }
+ addr->hash = UNIX_HASH_SIZE;
+- hash = d_backing_inode(dentry)->i_ino & (UNIX_HASH_SIZE - 1);
++ hash = d_backing_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE-1);
+ spin_lock(&unix_table_lock);
+- u->path = u_path;
++ u->path = path;
+ list = &unix_socket_table[hash];
+ } else {
+ spin_lock(&unix_table_lock);
+@@ -1060,10 +1050,6 @@ out_unlock:
+ spin_unlock(&unix_table_lock);
+ out_up:
+ mutex_unlock(&u->readlock);
+-out_path:
+- if (dentry)
+- done_path_create(&path, dentry);
+-
+ out:
+ return err;
+ }