From patchwork Tue Feb 25 10:15:46 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13989727 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 12DCC260A29 for ; Tue, 25 Feb 2025 10:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478602; cv=none; b=isZQZVK9GRh775tL+z1s5oLc5I7XIr3D1qQ+UIyEvWzL8NY6/UbLxOOmIAsue55VbzORZn4UbA60tIdVPOubI3LkyqwOVUmPFkAJu7xRYj4YQZkekLkvTeFyAf9hTw9GovayLZfbfpkkzYvDUxattuks76TC9VLR+6dKCZKyB6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478602; c=relaxed/simple; bh=aEmXCHQrohymmUvc9bEZGwPBYCZ1O6+W4FKAIe1hRkM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=B13XoSLgr5Wi42wxB7xgojEGXTtxBqma99bKVRFZG7qZjgxPYDhRU2Y7s93FGCNYaisW3yMqLO1t5UcK4d1hrOx42oLK2zD/X8V9jW3XllxKLT+mzKkLyo6TtBjS9ZoGldOk6Q4ARM02hMOaS9c3lN4AUSE7JoNUpoWqy6UE48Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pVDSQTiS; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pVDSQTiS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0A79EC4CEE7; Tue, 25 Feb 2025 10:16:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740478601; bh=aEmXCHQrohymmUvc9bEZGwPBYCZ1O6+W4FKAIe1hRkM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pVDSQTiSFFAK08MriAXDNstg8/5uEz3PKyUO7y4zY9RpP2KC6AkI5CXFu1PV3RVkh Q05A+XRlPKMbBVIqRbzYIkaUI5zSZE8ZAMmgG2vRkIPCc4OPLw4x1Qi8VFU0HsXsK0 xvJLXBnTifyfafTD8NbHFOqGgWWbCBB04FKZ7c2fOfMyi2eAp6+GhGRoP3sL6jrB+P rVU2DbKJuSY6PVEX8XDtV7HTh+Ry1WDub3/li566em83YQXe80kPThQs/w1HTPY9eQ 1UcnjHOZfxq58yIy9N4yqbG74G2zpbUfA5wdx6nETOQjDKDDRlwBP3F2VfvBuF19tN wQCzwk1aeeNAw== From: Christian Brauner Date: Tue, 25 Feb 2025 11:15:46 +0100 Subject: [PATCH 1/3] mount: handle mount propagation for detached mount trees Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250225-work-mount-propagation-v1-1-e6e3724500eb@kernel.org> References: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> In-Reply-To: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Al Viro , Miklos Szeredi , Jeff Layton , Josef Bacik , Seth Forshee , Christian Brauner X-Mailer: b4 0.15-dev-42535 X-Developer-Signature: v=1; a=openpgp-sha256; l=6739; i=brauner@kernel.org; h=from:subject:message-id; bh=aEmXCHQrohymmUvc9bEZGwPBYCZ1O6+W4FKAIe1hRkM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvndG6LoT5ue/rlUc4TKb2eW341hw6OW2be01F2mS5t 1dPmPKYd5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzk4DdGhg+WrZJrtDqcBLs2 X6tSDMldmXb/08FT/HdNwswelV0J12NkmFspM3HyLqvJdr9niYYHr5HSqKqW2BrTYBxVHN+ULRz GCwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 In commit ee2e3f50629f ("mount: fix mounting of detached mounts onto targets that reside on shared mounts") I fixed a bug where propagating the source mount tree of an anonymous mount namespace into a target mount tree of a non-anonymous mount namespace could be used to trigger an integer overflow in the non-anonymous mount namespace causing any new mounts to fail. The cause of this was that the propagation algorithm was unable to recognize mounts from the source mount tree that were already propagated into the target mount tree and then reappeared as propagation targets when walking the destination propagation mount tree. When fixing this I disabled mount propagation into anonymous mount namespaces. Make it possible for anonymous mount namespace to receive mount propagation events correctly. This is no also a correctness issue now that we allow mounting detached mount trees onto detached mount trees. Mark the source anonymous mount namespace with MNTNS_PROPAGATING indicating that all mounts belonging to this mount namespace are currently in the process of being propagated and make the propagation algorithm discard those if they appear as propagation targets. Signed-off-by: Christian Brauner --- fs/mount.h | 7 +++++++ fs/namespace.c | 42 +++++++++++++++++++++++++++--------------- fs/pnode.c | 10 +++++----- fs/pnode.h | 2 +- 4 files changed, 40 insertions(+), 21 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index e2501a724688..96862eba2246 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -5,6 +5,12 @@ #include #include +extern struct list_head notify_list; + +typedef __u32 __bitwise mntns_flags_t; + +#define MNTNS_PROPAGATING ((__force mntns_flags_t)(1 << 0)) + struct mnt_namespace { struct ns_common ns; struct mount * root; @@ -27,6 +33,7 @@ struct mnt_namespace { struct rb_node mnt_ns_tree_node; /* node in the mnt_ns_tree */ struct list_head mnt_ns_list; /* entry in the sequential list of mounts namespace */ refcount_t passive; /* number references not pinning @mounts */ + mntns_flags_t mntns_flags; } __randomize_layout; struct mnt_pcp { diff --git a/fs/namespace.c b/fs/namespace.c index f86a2b32c052..c0c48baf98a8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3534,13 +3534,6 @@ static int do_move_mount(struct path *old_path, if (!may_use_mount(p)) goto out; - /* - * Don't allow moving an attached mount tree to an anonymous - * mount tree. - */ - if (!is_anon_ns(ns) && is_anon_ns(p->mnt_ns)) - goto out; - /* The thing moved must be mounted... */ if (!is_mounted(&old->mnt)) goto out; @@ -3549,15 +3542,31 @@ static int do_move_mount(struct path *old_path, if (!(attached ? check_mnt(old) : is_anon_ns(ns))) goto out; - /* - * Ending up with two files referring to the root of the same - * anonymous mount namespace would cause an error as this would - * mean trying to move the same mount twice into the mount tree - * which would be rejected later. But be explicit about it right - * here. - */ - if (is_anon_ns(ns) && is_anon_ns(p->mnt_ns) && ns == p->mnt_ns) + if (is_anon_ns(ns)) { + /* + * Ending up with two files referring to the root of the + * same anonymous mount namespace would cause an error + * as this would mean trying to move the same mount + * twice into the mount tree which would be rejected + * later. But be explicit about it right here. + */ + if ((is_anon_ns(p->mnt_ns) && ns == p->mnt_ns)) + goto out; + + /* + * If this is an anonymous mount tree ensure that mount + * propagation can detect mounts that were just + * propagated to the target mount tree so we don't + * propagate onto them. + */ + ns->mntns_flags |= MNTNS_PROPAGATING; + } else if (is_anon_ns(p->mnt_ns)) { + /* + * Don't allow moving an attached mount tree to an + * anonymous mount tree. + */ goto out; + } if (old->mnt.mnt_flags & MNT_LOCKED) goto out; @@ -3601,6 +3610,9 @@ static int do_move_mount(struct path *old_path, if (err) goto out; + if (is_anon_ns(ns)) + ns->mntns_flags &= ~MNTNS_PROPAGATING; + /* if the mount is moved, it should no longer be expire * automatically */ list_del_init(&old->mnt_expire); diff --git a/fs/pnode.c b/fs/pnode.c index ef048f008bdd..6dd26ca96cdd 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -150,7 +150,7 @@ static struct mount *propagation_next(struct mount *m, struct mount *origin) { /* are there any slaves of this mount? */ - if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) + if (!IS_MNT_PROPAGATED(m) && !list_empty(&m->mnt_slave_list)) return first_slave(m); while (1) { @@ -174,7 +174,7 @@ static struct mount *skip_propagation_subtree(struct mount *m, * Advance m such that propagation_next will not return * the slaves of m. */ - if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) + if (!IS_MNT_PROPAGATED(m) && !list_empty(&m->mnt_slave_list)) m = last_slave(m); return m; @@ -185,7 +185,7 @@ static struct mount *next_group(struct mount *m, struct mount *origin) while (1) { while (1) { struct mount *next; - if (!IS_MNT_NEW(m) && !list_empty(&m->mnt_slave_list)) + if (!IS_MNT_PROPAGATED(m) && !list_empty(&m->mnt_slave_list)) return first_slave(m); next = next_peer(m); if (m->mnt_group_id == origin->mnt_group_id) { @@ -226,7 +226,7 @@ static int propagate_one(struct mount *m, struct mountpoint *dest_mp) struct mount *child; int type; /* skip ones added by this propagate_mnt() */ - if (IS_MNT_NEW(m)) + if (IS_MNT_PROPAGATED(m)) return 0; /* skip if mountpoint isn't covered by it */ if (!is_subdir(dest_mp->m_dentry, m->mnt.mnt_root)) @@ -380,7 +380,7 @@ bool propagation_would_overmount(const struct mount *from, if (!IS_MNT_SHARED(from)) return false; - if (IS_MNT_NEW(to)) + if (IS_MNT_PROPAGATED(to)) return false; if (to->mnt.mnt_root != mp->m_dentry) diff --git a/fs/pnode.h b/fs/pnode.h index 0b02a6393891..a81db78c0237 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,7 +12,7 @@ #define IS_MNT_SHARED(m) ((m)->mnt.mnt_flags & MNT_SHARED) #define IS_MNT_SLAVE(m) ((m)->mnt_master) -#define IS_MNT_NEW(m) (!(m)->mnt_ns || is_anon_ns((m)->mnt_ns)) +#define IS_MNT_PROPAGATED(m) (!(m)->mnt_ns || (m)->mnt_ns->mntns_flags & MNTNS_PROPAGATING) #define CLEAR_MNT_SHARED(m) ((m)->mnt.mnt_flags &= ~MNT_SHARED) #define IS_MNT_UNBINDABLE(m) ((m)->mnt.mnt_flags & MNT_UNBINDABLE) #define IS_MNT_MARKED(m) ((m)->mnt.mnt_flags & MNT_MARKED) From patchwork Tue Feb 25 10:15:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13989728 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 316A8260A29 for ; Tue, 25 Feb 2025 10:16:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478604; cv=none; b=sQegRjdyYiTyQ8ShW+cFqbDmr6nJNLOVnFJicizfFh7aEWrpxP0sKuyzirfFOTz2cBlYOuaapbh4mvCCRoifptwBAxsZxsZSLCxZM+EY1OgQSbgyMhFDCnO6WBWmaukt7PeN5ZW/7tvDVKsN6/0+9BMNNC0RZI/EPMNgTR+p6s0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478604; c=relaxed/simple; bh=jzgaL9QEFpgT1eLVjkZdeP1VLY3REOIuPXo96ADe/wY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YRr53bDveeRJZ2qYq8gsQ458pro9av4wL+4kH66crgPn5DmVaCvx2erzdUBvVal117twgDXw7VTbpLCXqkr8kyFs2xM5tX48FoBPASkY7yeNtwGKTIJcOTrVBW00aebft5vfzyCIwfFnKjLX7cNjqP24B9Cv5DPSuruNRMRp3IA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=J0Wh783J; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="J0Wh783J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0BA4BC4CEE2; Tue, 25 Feb 2025 10:16:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740478603; bh=jzgaL9QEFpgT1eLVjkZdeP1VLY3REOIuPXo96ADe/wY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=J0Wh783J3BPebhxUPuYnus+V6T07e3LRhudF9YijCiYzdr9MiMkx0goauNxFAACca 17yNGEP1XJ/QgcJlIld6nGz/+cIX0DaAdDx9yYsGEyEqcomQmVYCVzD3J5CwNuWvxh 2lAtU5rU7w5+Ftf+8bo9BY0fpQ2+4k9eBFrUlwpyzZri6/PAm7M5grq8JAAjlHY4Rx somA1+kD7ZrkwzdcpyZmoOLKa9zfhvszwTUniZdKzC1j4C8V5TPgHI42LZ8fQ/tBjd qOIfOynoacSUTOi6aTxsVZkSXOyf8G8/3QK2SmrwSpGhH1n34rsdTluNRSOnNO2UVR gWMMpLK+ZSSEQ== From: Christian Brauner Date: Tue, 25 Feb 2025 11:15:47 +0100 Subject: [PATCH 2/3] selftests: add test for detached mount tree propagation Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250225-work-mount-propagation-v1-2-e6e3724500eb@kernel.org> References: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> In-Reply-To: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Al Viro , Miklos Szeredi , Jeff Layton , Josef Bacik , Seth Forshee , Christian Brauner X-Mailer: b4 0.15-dev-42535 X-Developer-Signature: v=1; a=openpgp-sha256; l=3349; i=brauner@kernel.org; h=from:subject:message-id; bh=jzgaL9QEFpgT1eLVjkZdeP1VLY3REOIuPXo96ADe/wY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvndFqmfXwfS/n/otmjxKdE3WbDE4fXKi9zrjh2feGW Y9bduTM6yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiIaCkjw6nZIjtesMl8ZOad e+ygTNtOu91mPFf1o+rEL61adHLWrnZGhofPNBK3W3Vu/rVmhSPHRRO94vd6OqtiL3Tm/BdsPRk 4nREA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that detached mount trees receive propagation events. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 1e0508cb5c2d..33fa1f53fdf5 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -2097,4 +2097,74 @@ TEST_F(mount_setattr, two_detached_subtrees_of_same_anonymous_mount_namespace) ASSERT_EQ(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); } +TEST_F(mount_setattr, detached_tree_propagation) +{ + int fd_tree = -EBADF; + struct statx stx1, stx2, stx3, stx4; + + ASSERT_EQ(unshare(CLONE_NEWNS), 0); + ASSERT_EQ(mount(NULL, "/mnt", NULL, MS_REC | MS_SHARED, NULL), 0); + + /* + * Copy the following mount tree: + * + * /mnt testing tmpfs + * |-/mnt/A testing tmpfs + * | `-/mnt/A/AA testing tmpfs + * | `-/mnt/A/AA/B testing tmpfs + * | `-/mnt/A/AA/B/BB testing tmpfs + * `-/mnt/B testing ramfs + */ + fd_tree = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree, 0); + + ASSERT_EQ(statx(-EBADF, "/mnt/A", 0, 0, &stx1), 0); + ASSERT_EQ(statx(fd_tree, "A", 0, 0, &stx2), 0); + + /* + * Copying the mount namespace like done above doesn't alter the + * mounts in any way so the filesystem mounted on /mnt must be + * identical even though the mounts will differ. Use the device + * information to verify that. Note that tmpfs will have a 0 + * major number so comparing the major number is misleading. + */ + ASSERT_EQ(stx1.stx_dev_minor, stx2.stx_dev_minor); + + /* Mount a tmpfs filesystem over /mnt/A. */ + ASSERT_EQ(mount(NULL, "/mnt/A", "tmpfs", 0, NULL), 0); + + + ASSERT_EQ(statx(-EBADF, "/mnt/A", 0, 0, &stx3), 0); + ASSERT_EQ(statx(fd_tree, "A", 0, 0, &stx4), 0); + + /* + * A new filesystem has been mounted on top of /mnt/A which + * means that the device information will be different for any + * statx() that was taken from /mnt/A before the mount compared + * to one after the mount. + * + * Since we already now that the device information between the + * stx1 and stx2 samples are identical we also now that stx2 and + * stx3 device information will necessarily differ. + */ + ASSERT_NE(stx1.stx_dev_minor, stx3.stx_dev_minor); + + /* + * If mount propagation worked correctly then the tmpfs mount + * that was created after the mount namespace was unshared will + * have propagated onto /mnt/A in the detached mount tree. + * + * Verify that the device information for stx3 and stx4 are + * identical. It is already established that stx3 is different + * from both stx1 and stx2 sampled before the tmpfs mount was + * done so if stx3 and stx4 are identical the proof is done. + */ + ASSERT_EQ(stx3.stx_dev_minor, stx4.stx_dev_minor); + + EXPECT_EQ(close(fd_tree), 0); +} + TEST_HARNESS_MAIN From patchwork Tue Feb 25 10:15:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13989729 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4CF0114A4F0 for ; Tue, 25 Feb 2025 10:16:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478606; cv=none; b=tcP8uKZZ9TAOYzZC4Y3Whck2Cai0/xOGXJT4oIQ1z3h1uTWZGJ9XL955chuNzL6o5qwrVDSNQVVIB6nZl18LXxw8hQBe3lIW9lPmxgX98ram7UWQEMn/qjHBk7S1l3OnkIZk7bFwonnwgU82qazLlA1ywuH4jkuXWk3Z3Fk5wCs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740478606; c=relaxed/simple; bh=iPrR37BBXOx9IRo48W6rJpjeqaaJCo1O5tNwCbxmp1s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dDEhkDeXI4+HEymZP/4svpmFOw/cAeiBcKkqH4ka+0L6vYeZphJbc5V/WJ0dWXgZjoDNI3MUoH+n6ZzoWwlr+4znC6DWALn2ErMS8LoB2HEZB4+QKdkiFjwJaYcnKjATYh5h32iov0EEuadCA2l6OzodsM6n7SN0kV6XojfBznk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jJ1izVIK; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="jJ1izVIK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2063EC4CEE8; Tue, 25 Feb 2025 10:16:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740478605; bh=iPrR37BBXOx9IRo48W6rJpjeqaaJCo1O5tNwCbxmp1s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jJ1izVIKLFM+E5sAO6wmarQOtqEcJdxjUcOrlJl/OzF3EqnYP8zQQDaztkYggkMFr 3EkX+mjNukdXvpUjX6yW5n3nKM+Btio+PpCZbHzqcNiETzrVtDdIMPH0bjgcNNRLat +0ekbaKRZwyEPDBZtAtI2aOSDZ+FNQvphYzsBJrQHMTbBKOtSiIw0r8cQl2Ds2EXeH BwdNLoKIJc3Rt4FcYUMeBEQjSkhtlRPiYCR24e5Pl06+a0FbZu+afL8ptLrvxXE0VX rxoBTJnitz+lb2pSZOCsynxFPl5ptB8SpuGUTQTK4ceU7Ni9nfvq3nPDJqbbWXSCav flD3KV0yiaLTQ== From: Christian Brauner Date: Tue, 25 Feb 2025 11:15:48 +0100 Subject: [PATCH 3/3] selftests: test subdirectory mounting Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250225-work-mount-propagation-v1-3-e6e3724500eb@kernel.org> References: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> In-Reply-To: <20250225-work-mount-propagation-v1-0-e6e3724500eb@kernel.org> To: linux-fsdevel@vger.kernel.org Cc: Al Viro , Miklos Szeredi , Jeff Layton , Josef Bacik , Seth Forshee , Christian Brauner X-Mailer: b4 0.15-dev-42535 X-Developer-Signature: v=1; a=openpgp-sha256; l=3619; i=brauner@kernel.org; h=from:subject:message-id; bh=iPrR37BBXOx9IRo48W6rJpjeqaaJCo1O5tNwCbxmp1s=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvndFabbm6eYLfSise8UAO9XOK8zYfu+jXqV+z8OVlC QnrVc+qO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACby/Rojwxnl7h38BqozOldY /Oq+qdDyduLbXyJ/5HmXb5v7snJ3lzXDXzn7SZOSzOu/s9Z5nfn8n3/+qYOlZo07jj+r09d48u5 yBwMA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 This tests mounting a subdirectory without ever having to expose the filesystem to a non-anonymous mount namespace. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 81 ++++++++++------------ 1 file changed, 36 insertions(+), 45 deletions(-) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 33fa1f53fdf5..48a000cabc97 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -20,6 +20,7 @@ #include #include +#include "../filesystems/overlayfs/wrappers.h" #include "../kselftest_harness.h" #ifndef CLONE_NEWNS @@ -177,51 +178,6 @@ static inline int sys_open_tree(int dfd, const char *filename, unsigned int flag return syscall(__NR_open_tree, dfd, filename, flags); } -/* move_mount() flags */ -#ifndef MOVE_MOUNT_F_SYMLINKS -#define MOVE_MOUNT_F_SYMLINKS 0x00000001 /* Follow symlinks on from path */ -#endif - -#ifndef MOVE_MOUNT_F_AUTOMOUNTS -#define MOVE_MOUNT_F_AUTOMOUNTS 0x00000002 /* Follow automounts on from path */ -#endif - -#ifndef MOVE_MOUNT_F_EMPTY_PATH -#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004 /* Empty from path permitted */ -#endif - -#ifndef MOVE_MOUNT_T_SYMLINKS -#define MOVE_MOUNT_T_SYMLINKS 0x00000010 /* Follow symlinks on to path */ -#endif - -#ifndef MOVE_MOUNT_T_AUTOMOUNTS -#define MOVE_MOUNT_T_AUTOMOUNTS 0x00000020 /* Follow automounts on to path */ -#endif - -#ifndef MOVE_MOUNT_T_EMPTY_PATH -#define MOVE_MOUNT_T_EMPTY_PATH 0x00000040 /* Empty to path permitted */ -#endif - -#ifndef MOVE_MOUNT_SET_GROUP -#define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */ -#endif - -#ifndef MOVE_MOUNT_BENEATH -#define MOVE_MOUNT_BENEATH 0x00000200 /* Mount beneath top mount */ -#endif - -#ifndef MOVE_MOUNT__MASK -#define MOVE_MOUNT__MASK 0x00000377 -#endif - -static inline int sys_move_mount(int from_dfd, const char *from_pathname, - int to_dfd, const char *to_pathname, - unsigned int flags) -{ - return syscall(__NR_move_mount, from_dfd, from_pathname, to_dfd, - to_pathname, flags); -} - static ssize_t write_nointr(int fd, const void *buf, size_t count) { ssize_t ret; @@ -1789,6 +1745,41 @@ TEST_F(mount_setattr, open_tree_detached_fail3) ASSERT_EQ(errno, EINVAL); } +TEST_F(mount_setattr, open_tree_subfolder) +{ + int fd_context, fd_tmpfs, fd_tree; + + fd_context = sys_fsopen("tmpfs", 0); + ASSERT_GE(fd_context, 0); + + ASSERT_EQ(sys_fsconfig(fd_context, FSCONFIG_CMD_CREATE, NULL, NULL, 0), 0); + + fd_tmpfs = sys_fsmount(fd_context, 0, 0); + ASSERT_GE(fd_tmpfs, 0); + + EXPECT_EQ(close(fd_context), 0); + + ASSERT_EQ(mkdirat(fd_tmpfs, "subdir", 0755), 0); + + fd_tree = sys_open_tree(fd_tmpfs, "subdir", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree, 0); + + EXPECT_EQ(close(fd_tmpfs), 0); + + ASSERT_EQ(mkdirat(-EBADF, "/mnt/open_tree_subfolder", 0755), 0); + + ASSERT_EQ(sys_move_mount(fd_tree, "", -EBADF, "/mnt/open_tree_subfolder", MOVE_MOUNT_F_EMPTY_PATH), 0); + + EXPECT_EQ(close(fd_tree), 0); + + ASSERT_EQ(umount2("/mnt/open_tree_subfolder", 0), 0); + + EXPECT_EQ(rmdir("/mnt/open_tree_subfolder"), 0); +} + TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_then_close) { int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF;