From: Greg Kroah-Hartman Date: Mon, 11 Nov 2019 08:48:29 +0000 (+0100) Subject: 5.3-stable patches X-Git-Tag: v4.4.201~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=92daf91c1099f247803a73ba8ffc2d3b99cf2053;p=thirdparty%2Fkernel%2Fstable-queue.git 5.3-stable patches added patches: configfs-fix-a-deadlock-in-configfs_symlink.patch --- diff --git a/queue-5.3/configfs-fix-a-deadlock-in-configfs_symlink.patch b/queue-5.3/configfs-fix-a-deadlock-in-configfs_symlink.patch new file mode 100644 index 00000000000..20896a9b8c8 --- /dev/null +++ b/queue-5.3/configfs-fix-a-deadlock-in-configfs_symlink.patch @@ -0,0 +1,81 @@ +From 351e5d869e5ac10cb40c78b5f2d7dfc816ad4587 Mon Sep 17 00:00:00 2001 +From: Al Viro +Date: Sat, 3 Aug 2019 11:51:18 -0400 +Subject: configfs: fix a deadlock in configfs_symlink() + +From: Al Viro + +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 +Signed-off-by: Christoph Hellwig +Signed-off-by: Greg Kroah-Hartman + +--- + fs/configfs/symlink.c | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +--- a/fs/configfs/symlink.c ++++ b/fs/configfs/symlink.c +@@ -143,11 +143,42 @@ int configfs_symlink(struct inode *dir, + !type->ct_item_ops->allow_link) + goto out_put; + ++ /* ++ * This is really sick. What they wanted was a hybrid of ++ * link(2) and symlink(2) - they wanted the target resolved ++ * at syscall time (as link(2) would've done), be a directory ++ * (which link(2) would've refused to do) *AND* be a deep ++ * fucking magic, making the target busy from rmdir POV. ++ * symlink(2) is nothing of that sort, and the locking it ++ * gets matches the normal symlink(2) semantics. Without ++ * attempts to resolve the target (which might very well ++ * not even exist yet) done prior to locking the parent ++ * directory. This perversion, OTOH, needs to resolve ++ * the target, which would lead to obvious deadlocks if ++ * attempted with any directories locked. ++ * ++ * Unfortunately, that garbage is userland ABI and we should've ++ * said "no" back in 2005. Too late now, so we get to ++ * play very ugly games with locking. ++ * ++ * Try *ANYTHING* of that sort in new code, and you will ++ * really regret it. Just ask yourself - what could a BOFH ++ * do to me and do I want to find it out first-hand? ++ * ++ * AV, a thoroughly annoyed bastard. ++ */ ++ inode_unlock(dir); + ret = get_target(symname, &path, &target_item, dentry->d_sb); ++ inode_lock(dir); + if (ret) + goto out_put; + +- ret = type->ct_item_ops->allow_link(parent_item, target_item); ++ if (dentry->d_inode || d_unhashed(dentry)) ++ ret = -EEXIST; ++ else ++ ret = inode_permission(dir, MAY_WRITE | MAY_EXEC); ++ if (!ret) ++ ret = type->ct_item_ops->allow_link(parent_item, target_item); + if (!ret) { + mutex_lock(&configfs_symlink_mutex); + ret = create_link(parent_item, target_item, dentry); diff --git a/queue-5.3/series b/queue-5.3/series index 47ccceca0db..7e3dc8be3c7 100644 --- a/queue-5.3/series +++ b/queue-5.3/series @@ -78,3 +78,4 @@ can-gs_usb-gs_can_open-prevent-memory-leak.patch can-dev-add-missing-of_node_put-after-calling-of_get_child_by_name.patch can-mcba_usb-fix-use-after-free-on-disconnect.patch can-peak_usb-fix-slab-info-leak.patch +configfs-fix-a-deadlock-in-configfs_symlink.patch