configfs: fix a deadlock in configfs_symlink()
authorAl Viro <viro@zeniv.linux.org.uk>
Sat, 3 Aug 2019 15:51:18 +0000 (11:51 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 12 Nov 2019 18:15:51 +0000 (19:15 +0100)
commitfa33be192ea775c7bf77dca0562f05c2cbf06f5e
tree52f9629f1e7c0ed0a50e8d1fc346b577c15fefbc
parent49824b5c875087a52672b0c8e8ecbefe6f773532
configfs: fix a deadlock in configfs_symlink()

commit 351e5d869e5ac10cb40c78b5f2d7dfc816ad4587 upstream.

Configfs abuses symlink(2).  Unlike the normal filesystems, it
wants the target resolved at symlink(2) time, like link(2) would've
done.  The problem is that ->symlink() is called with the parent
directory locked exclusive, so resolving the target inside the
->symlink() is easily deadlocked.

Short of really ugly games in sys_symlink() itself, all we can
do is to unlock the parent before resolving the target and
relock it after.  However, that invalidates the checks done
by the caller of ->symlink(), so we have to
* check that dentry is still where it used to be
(it couldn't have been moved, but it could've been unhashed)
* recheck that it's still negative (somebody else
might've successfully created a symlink with the same name
while we were looking the target up)
* recheck the permissions on the parent directory.

Cc: stable@vger.kernel.org
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/configfs/symlink.c