From patchwork Fri Feb 21 13:13:00 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985513 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 E7A1F20F068 for ; Fri, 21 Feb 2025 13:13:35 +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=1740143616; cv=none; b=EwTHRaUJgCwYjfontvaNXi4wiJ12LZmHMy1JYCC8APYnzWcbG6FOaSlsOZSK2wKz6Aq6cOMA5dZy16mDqj/FDfyCXbnr35bJfKgx0eWk9FQ9rtRnQXYIJVEArXhTUGkw3sjhLw/iKpvmhbf2Eiqwfh68S1wFsv/8OJh/To9m4HM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143616; c=relaxed/simple; bh=dJR5WjmY7M49v87cFPq7tV8h5trgLQiGlHMFv6ValbY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=p4+7DtyhzNN/7WY684ehz/Puqtzwn+Zy02+gAsCs4909v2Ng4tC/2+6oGC/wLp597bzr212Cw/14YItD/GyLmx/Uu9BVihnvEJDvjpvRHunFFNk5dEyaXW3zQFUH33gW7JZdaV0QRzhGfNawT1VbqloYBR999tpRXSZa+/dn8EY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=q36boZgX; 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="q36boZgX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D935EC4CEE6; Fri, 21 Feb 2025 13:13:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143615; bh=dJR5WjmY7M49v87cFPq7tV8h5trgLQiGlHMFv6ValbY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=q36boZgXIK++lVaMYDVPBEeIp86v83QutEVCiftYaqfmN5jctXGAYDKZU9Cd3hQ/V VHXmMeyIl50juwypSv7ET57rN+k5daxgeiDdy+WgCpAF44YRSAd4s7vwqVdUxnHX0C kI9b+kHfAZ5c9/jkG4mGlyVvI/+akB7osxOhAawa+9riw/YLFXntuwxX/d0gHPfVp5 uoccThD61ipQNAIH3CZRlb/g5PWFA9oT/PG1vrt4OUp2l3zZTf9UL9KRMaUt59XFel WQHE92cVuCu3B3qlSVZFNuJNJndTwopvZ8+Oc9pe+cWyOyIs2wY48T4AWUCnTYse0r UDmdJmi64AVqA== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:00 +0100 Subject: [PATCH RFC 01/16] fs: record sequence number of origin mount namespace Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-1-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=1906; i=brauner@kernel.org; h=from:subject:message-id; bh=dJR5WjmY7M49v87cFPq7tV8h5trgLQiGlHMFv6ValbY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP5lOfPugbkdEzrNfLWjk89vaHPc+9cip3an1skD4 efnTtmg2FHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRR7cZGWa8fMRgJ3Zl2vS/ +8I+Wjrs/L1905Od1w8/ZF15Wy3926FjDH94Em9b83qqTpm+cv8yY578N+I3NieUHHl+VcO18Xq axDJOAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Store the sequence number of the mount namespace the anonymous mount namespace has been created from. This information will be used in follow-up patches. Signed-off-by: Christian Brauner --- fs/mount.h | 1 + fs/namespace.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index ffb613cdfeee..820a79f1f735 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -20,6 +20,7 @@ struct mnt_namespace { wait_queue_head_t poll; struct rcu_head mnt_ns_rcu; }; + u64 seq_origin; /* Sequence number of origin mount namespace */ u64 event; unsigned int nr_mounts; /* # of mounts in the namespace */ unsigned int pending_mounts; diff --git a/fs/namespace.c b/fs/namespace.c index a3ed3f2980cb..9bcfb405b02b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2853,15 +2853,28 @@ static int do_loopback(struct path *path, const char *old_name, static struct file *open_detached_copy(struct path *path, bool recursive) { - struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; - struct mnt_namespace *ns = alloc_mnt_ns(user_ns, true); + struct mnt_namespace *ns, *mnt_ns = current->nsproxy->mnt_ns, *src_mnt_ns; + struct user_namespace *user_ns = mnt_ns->user_ns; struct mount *mnt, *p; struct file *file; + ns = alloc_mnt_ns(user_ns, true); if (IS_ERR(ns)) return ERR_CAST(ns); namespace_lock(); + + /* + * Record the sequence number of the source mount namespace. + * This needs to hold namespace_sem to ensure that the mount + * doesn't get attached. + */ + src_mnt_ns = real_mount(path->mnt)->mnt_ns; + if (is_anon_ns(src_mnt_ns)) + ns->seq_origin = src_mnt_ns->seq_origin; + else + ns->seq_origin = src_mnt_ns->seq; + mnt = __do_loopback(path, recursive); if (IS_ERR(mnt)) { namespace_unlock(); From patchwork Fri Feb 21 13:13:01 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985514 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 17DFF20E71C for ; Fri, 21 Feb 2025 13:13:37 +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=1740143618; cv=none; b=qQ8a5NWk0A/rUAo4Cfy9rrzJvVAkOEejXwitPl4MEpXlF2nbyIDtJc71Hk6yT3NRPVwIpk2CtksAaku65dULj3mUH5Yj3mhPeSxH4dPRk53WJY+hqWy9OlqDR0O/sgp669vB8vnda0qcOZe2+ZcAYfLmaz6daSRAZyTpX7VFvxM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143618; c=relaxed/simple; bh=sUx1KsWjN5QnSOgaKX8WVsvVMrJf1Jc/YDPu/z6mW28=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H2kYxXDzWXB4LnwZIXgVIdm9AadGMs6qeJAPl4KrrCcIecFWKwQGZNFC7s8CmXsBKUp8/zcdWFjwckiEYFPVWGeK0GKd6/uT90qlhD4qI1YKmtDjASmVJqWDGsykOokyW23F1Stosdts/Qw/ZzS5eTEw8b9R/qlhRkKUb/dSDTA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UpkLgh7V; 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="UpkLgh7V" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D70E3C4CEE7; Fri, 21 Feb 2025 13:13:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143617; bh=sUx1KsWjN5QnSOgaKX8WVsvVMrJf1Jc/YDPu/z6mW28=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UpkLgh7VjBHgkBRcrRK+O+jzFVRh9CE/JhQ/A0r/0AhZ08NLbD3k8yR/XEzdBhWRy xtgX+OC89Eg4FXZPINxIPw9Rh+ADlD28h8W7XyV4fwgXHjncJGFVKDvJNd8ol0Nbg9 hgeeiKDlflf9f1JWPnlshLBuAQyJ2Hl9IPbZpCvY4jfAZMrauwZdTGR8ZmRPUkvVMO aYdoxUcpsqegIcOP/bQbJjXU5flrI1d/PZg4JAEEo5E5E/MFynAu+N1FoKHdIrUQFI 160Z6g+1vdwPXmDSngg0r+S5bXwdwonmL7v+p7lr6pNAxRo65WxU91Lh0oImOu1e6W Qiw0+RCwwmZ9w== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:01 +0100 Subject: [PATCH RFC 02/16] fs: add mnt_ns_empty() helper Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-2-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=1624; i=brauner@kernel.org; h=from:subject:message-id; bh=sUx1KsWjN5QnSOgaKX8WVsvVMrJf1Jc/YDPu/z6mW28=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP51dskqowXmf/88aClQErqzrrBlbf+VgJsXmo1s2 B2Df7QbdZSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzk+g+G/9W+rdO6Ax817lO2 jHhy4Dtf/qnJ1vc4pmq7TGb+1MNnc4nhv8+VI10eHYLmB0QW/g/M5PH34Wv/eLMs7VuvFJu9X5U bJwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a helper that checks whether a give mount namespace is empty instead of open-coding the specific data structure check. This also be will be used in follow-up patches. Signed-off-by: Christian Brauner --- fs/mount.h | 5 +++++ fs/namespace.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index 820a79f1f735..e2501a724688 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -157,6 +157,11 @@ static inline bool mnt_ns_attached(const struct mount *mnt) return !RB_EMPTY_NODE(&mnt->mnt_node); } +static inline bool mnt_ns_empty(const struct mnt_namespace *ns) +{ + return RB_EMPTY_ROOT(&ns->mounts); +} + static inline void move_from_ns(struct mount *mnt, struct list_head *dt_list) { struct mnt_namespace *ns = mnt->mnt_ns; diff --git a/fs/namespace.c b/fs/namespace.c index 9bcfb405b02b..1d3b524ef878 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5313,7 +5313,7 @@ static int grab_requested_root(struct mnt_namespace *ns, struct path *root) * We have to find the first mount in our ns and use that, however it * may not exist, so handle that properly. */ - if (RB_EMPTY_ROOT(&ns->mounts)) + if (mnt_ns_empty(ns)) return -ENOENT; first = child = ns->root; @@ -5338,7 +5338,7 @@ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id, int err; /* Has the namespace already been emptied? */ - if (mnt_ns_id && RB_EMPTY_ROOT(&ns->mounts)) + if (mnt_ns_id && mnt_ns_empty(ns)) return -ENOENT; s->mnt = lookup_mnt_in_ns(mnt_id, ns); From patchwork Fri Feb 21 13:13:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985515 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 9723920F091 for ; Fri, 21 Feb 2025 13:13:39 +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=1740143619; cv=none; b=HJW7jvr7lKYoV63+mX7ob7zSnQxGBIbKMUXh66D/6W9QjSIuv4GGneZ3ORk4QuU5kUVETaC4bIUGPZQpe0hpL0kN0Tm4rVnyRzmkLBkzMfJ+JBZwFyD5kBjvW1aXgeFFhfy+f8b2zwIPo6jmvC6cvnklVpn1dGKatmerg+kKQYk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143619; c=relaxed/simple; bh=+75OobclMsUAC78+z348QwpL7cPx5/qLrICWd2I9zJo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=s9OkHTwmHmpFHbZtaCmubfXnEuZKhj1JLEkKvow7C9dEGJ0sT2DByGkYyPzDZ0i8FwxnRQvJanDK2dApv4LF8HuxBQM76VxdC5goGMxhH0TkgJTl7Ise9ypXKGC1Twrc8XblFqpaKdQDz/2cGl/hFHNVl4zQ19yPajsHSYcJ9Ds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FKxxjxj/; 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="FKxxjxj/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EAB65C4CEE4; Fri, 21 Feb 2025 13:13:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143619; bh=+75OobclMsUAC78+z348QwpL7cPx5/qLrICWd2I9zJo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FKxxjxj/MHNDHGx2LEpyRuct32x9NPW3Hrl45irRRWEKG7X12TXn9Gx+nljM89d8w ssr0hi+SKqgp1LpjhEPxyxQuc7DGjvzu5+9+z5G/oMW+fA0hIc6PH8FAW5BavjOtT+ sl6JUJVM95Dvumy5JsoljpGru7ajYRfYD2W8F656aDtaNNJHeZgJYxS5BbdX/2q1IE JdvtUuU/+3EzEd90oKXLEmcf4AIuoWW/brSrkOcuTu+eiFq/K9yMQG9wHMlX4lvpDT SyDrdeYrfch0Kej9AYQiLwuKcE0pEC/vrQMXwd6T2r0LCX5/UB3jCx8VEfNya0Fuss VUQ0toZuXF3ow== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:02 +0100 Subject: [PATCH RFC 03/16] fs: add assert for move_mount() Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-3-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=804; i=brauner@kernel.org; h=from:subject:message-id; bh=+75OobclMsUAC78+z348QwpL7cPx5/qLrICWd2I9zJo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP5luj/Nx6bkzl7fL6syTVyLNJIzFNUXcGn/nWUe4 bNz9i/vjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlILmFk6E5LjTLPtS/w57KQ jXDw86xfdPKV8VL/aYzrIzpKT3WYMTKcKCr7LHVKY8fTu36Piz6zZs2L3fb13GWTmZ+vHFnhM72 JEwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 After we've attached a detached mount tree the anonymous mount namespace must be empty. Add an assert and make this assumption explicit. Signed-off-by: Christian Brauner --- fs/namespace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 1d3b524ef878..7d0fa8ef8674 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3421,10 +3421,13 @@ static int do_move_mount(struct path *old_path, struct path *new_path, out: unlock_mount(mp); if (!err) { - if (attached) + if (attached) { mntput_no_expire(parent); - else + } else { + /* Make sure we notice when we leak mounts. */ + VFS_WARN_ON_ONCE(!mnt_ns_empty(ns)); free_mnt_ns(ns); + } } return err; } From patchwork Fri Feb 21 13:13:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985516 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 6914420B812 for ; Fri, 21 Feb 2025 13:13: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=1740143623; cv=none; b=pip7xv7LVH7PdL7Zz00Ft8Q0R31DCz9pG8FuOfgMRHls4wwzfIwNLH9IV9FW3I/JkubQzsUZjNLfDYagGOGlukl/va4xTKZzZMkjAhpkgEUtzK/SBQfEPM3EyoATQHH1KXEmjXf9+WZbQWkIzJWeGwG2JVWMvsHyS5JT46x5HLo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143623; c=relaxed/simple; bh=2ABkRpc3fT2dPlaRJehf3U9kSkKoclvFQ+Axz0gt9cQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nPrmcxMZSJ0X0EJk3DnBYQ2ErXH4FJ0h8GUFxwO6JvhAFvvgd7nZWZHhnFJ9dXwgO44iyt6RgexRRHZKgbW4ejql83lqmlpDH1Tkh5gcYP91gicCEciZyV0zCPqC7vlfi8PVuJc15XhE9D5G8R4tt/q5SPKp+jAcS0IBQ93rGnw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Jrq8iDn7; 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="Jrq8iDn7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 14F7EC4CEE4; Fri, 21 Feb 2025 13:13:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143621; bh=2ABkRpc3fT2dPlaRJehf3U9kSkKoclvFQ+Axz0gt9cQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Jrq8iDn7sGxbyP9YjutrkVMkxk/NuZEbaojUKRe8riGymb/5EUHdSrfQhrvV0aw3q mjMbkOOgl/o/+W53/QMzR2rrROLHZwQfJel2UWTsxFJiT7ZXxLMu47N+fcx244ifg4 FOlWzHXidZkO2O/bAi2ovPkocrurDuzSlHzxE9eKdW1iGtvnBHpKY2BaDTcEQ/aTPQ tmGBDxbQgUqQtzS+IzR9kbv8vRmHbq2klXAzT+M2xwKUVoXwVF+VfvnsnN7h5hnD25 zAwQ8vbtgrYmY75lrGNtFtbb5GzxHvOZXLcNZmZfAUdCHEEJ1vcvfwx7zjVj6YfM8q C/rHmGLycm/8Q== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:03 +0100 Subject: [PATCH RFC 04/16] fs: add fastpath for dissolve_on_fput() Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-4-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2505; i=brauner@kernel.org; h=from:subject:message-id; bh=2ABkRpc3fT2dPlaRJehf3U9kSkKoclvFQ+Axz0gt9cQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP61yejKDs7vXPKBjZ/YolV5Ljoej+hiaVd7Ilpgw Bmk63mqo5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCIBPxn+u5/p2/docTNnr4rQ hXO8pjciV9/cGOOdUZV/beFj3Wb9DQz/Y6/dfsHPanfibtl8tdA7Vr1xck2SV1IPzDh3/sYa9QZ HZgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Instead of acquiring the namespace semaphore and the mount lock everytime we close a file with FMODE_NEED_UNMOUNT set add a fastpath that checks whether we need to at all. Most of the time the caller will have attached the mount to the filesystem hierarchy and there's nothing to do. Signed-off-by: Christian Brauner --- fs/namespace.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 12 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 7d0fa8ef8674..2cffcda8a48e 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2246,22 +2246,57 @@ struct vfsmount *collect_mounts(const struct path *path) static void free_mnt_ns(struct mnt_namespace *); static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *, bool); +static inline bool must_dissolve(struct mnt_namespace *mnt_ns) +{ + /* + * This mount belonged to an anonymous mount namespace + * but was moved to a non-anonymous mount namespace and + * then unmounted. + */ + if (unlikely(!mnt_ns)) + return false; + + /* + * This mount belongs to a non-anonymous mount namespace + * and we know that such a mount can never transition to + * an anonymous mount namespace again. + */ + if (!is_anon_ns(mnt_ns)) { + /* + * A detached mount either belongs to an anonymous mount + * namespace or a non-anonymous mount namespace. It + * should never belong to something purely internal. + */ + VFS_WARN_ON_ONCE(mnt_ns == MNT_NS_INTERNAL); + return false; + } + + return true; +} + void dissolve_on_fput(struct vfsmount *mnt) { struct mnt_namespace *ns; - namespace_lock(); - lock_mount_hash(); - ns = real_mount(mnt)->mnt_ns; - if (ns) { - if (is_anon_ns(ns)) - umount_tree(real_mount(mnt), UMOUNT_CONNECTED); - else - ns = NULL; + struct mount *m = real_mount(mnt); + + scoped_guard(rcu) { + if (!must_dissolve(READ_ONCE(m->mnt_ns))) + return; } - unlock_mount_hash(); - namespace_unlock(); - if (ns) - free_mnt_ns(ns); + + scoped_guard(rwsem_write, &namespace_sem) { + ns = m->mnt_ns; + if (!must_dissolve(ns)) + return; + + lock_mount_hash(); + umount_tree(m, UMOUNT_CONNECTED); + unlock_mount_hash(); + } + + /* Make sure we notice when we leak mounts. */ + VFS_WARN_ON_ONCE(!mnt_ns_empty(ns)); + free_mnt_ns(ns); } void drop_collected_mounts(struct vfsmount *mnt) From patchwork Fri Feb 21 13:13:04 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985517 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 74A4420B812 for ; Fri, 21 Feb 2025 13:13:44 +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=1740143624; cv=none; b=pSV26DrLFRUAptzPE93HtY3hnDFIlkI5u0ZecSr04TRv4nEFQoi4bWLrva9gnMyxk0E+Jf6rtd9EymzBp8GPZcEdDXQv4qTup9dxEtjxWGj7GHXTx/6iwkg+LmRBkvJYazUmhS3oMdPaRudFafEMLFERsXLNjlCBoexfMbvSa2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143624; c=relaxed/simple; bh=S7vIZ3NberhRHRff0PuGILeschmdcS78Pf1BjJ8FqL0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=slqlwwTt6URtV7KdYQMJT4vRl8GvN9pisXkxFYxHsq+UCiuf6Ts3p5N1TieP8Xqb6gzfH2JCMAjZC8cI10pGwCmo0l8aoTQ7Pd5G1goWXIQ8RkoW6GBdOekjtH6ycoJmknqhf5mBNL1XaM3LQ6zbLoOYo+MYkaoMeXofznxvU2g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=E4yDhtb8; 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="E4yDhtb8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 675EAC4CED6; Fri, 21 Feb 2025 13:13:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143624; bh=S7vIZ3NberhRHRff0PuGILeschmdcS78Pf1BjJ8FqL0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=E4yDhtb8OFcvYzU5aAZFQV/dbmwowKvEpKjHkilYSVVwDttNMGboBbDSHlbteLgs3 V59944gF66dCfEKIjTnDgiI5aPA+bdfukemKNLHaBW75AgC2yLiWq4OfhV1a9x+wKG w5RZWTLNOH0gSOifUjkVYCSPjoX08sMMx7+mKuB09smSDK/Dqbdi/cCwUKFZMwhkWr FLPi9TmaE+rhzBxce4IyWVX+5DudXcKpttkPblf40GlWq+X6Qnz0t0E98o49EbUVDs Pyt+Ry8jKNiRwym088W3ob6sFnwS76UBSNEGxepCNJHGHlEZ0d4ormjXepUGbsg1Fp vOSJmxd3iupDg== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:04 +0100 Subject: [PATCH RFC 05/16] fs: add may_copy_tree() Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-5-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2274; i=brauner@kernel.org; h=from:subject:message-id; bh=S7vIZ3NberhRHRff0PuGILeschmdcS78Pf1BjJ8FqL0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP6lZ9F4olyi7A6vuTWHo0vcpDviap1pqU8ErXtXV 3/QzFjRUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMBGtI4wMJzvOLb3HE/797pRV 8U82uDd/4L2j08bzqy7HOD5g02GJD4wMh3mK5gjP4eZzLRFIueZ05vbZFXoKrYXyDYEzWyxE8/N YAQ== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a helper that verifies whether a caller may copy a given mount tree. Signed-off-by: Christian Brauner --- fs/namespace.c | 44 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 2cffcda8a48e..c61b9704499a 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2808,6 +2808,41 @@ static int do_change_type(struct path *path, int ms_flags) return err; } +/* may_copy_tree() - check if a mount tree can be copied + * @path: path to the mount tree to be copied + * + * This helper checks if the caller may copy the mount tree starting + * from @path->mnt. The caller may copy the mount tree under the + * following circumstances: + * + * (1) The caller is located in the mount namespace of the mount tree. + * This also implies that the mount does not belong to an anonymous + * mount namespace. + * (2) The caller tries to copy an nfs mount referring to a mount + * namespace, i.e., the caller is trying to copy a mount namespace + * entry from nsfs. + * (3) The caller tries to copy a pidfs mount referring to a pidfd. + * + * Returns true if the mount tree can be copied, false otherwise. + */ +static inline bool may_copy_tree(struct path *path) +{ + struct mount *mnt = real_mount(path->mnt); + const struct dentry_operations *d_op; + + if (check_mnt(mnt)) + return true; + + d_op = path->dentry->d_op; + if (d_op == &ns_dentry_operations) + return true; + + if (d_op == &pidfs_dentry_operations) + return true; + + return false; +} + static struct mount *__do_loopback(struct path *old_path, int recurse) { struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt); @@ -2815,13 +2850,8 @@ static struct mount *__do_loopback(struct path *old_path, int recurse) if (IS_MNT_UNBINDABLE(old)) return mnt; - if (!check_mnt(old)) { - const struct dentry_operations *d_op = old_path->dentry->d_op; - - if (d_op != &ns_dentry_operations && - d_op != &pidfs_dentry_operations) - return mnt; - } + if (!may_copy_tree(old_path)) + return mnt; if (!recurse && has_locked_children(old, old_path->dentry)) return mnt; From patchwork Fri Feb 21 13:13:05 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985518 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 989CD20B812 for ; Fri, 21 Feb 2025 13:13:46 +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=1740143626; cv=none; b=GjuNDhwUXHIIKUIlyGj6X9i3No54kl6df13tctyYW2ayu7kMNHKItdRk8HUBusfuJlaG1unh6OArmUQ2R5Miet/PBt0/EE8v5pPXElUPQyHzmGz46510uU5b5FeCieNa0n6amItLLlmRCu9x3+0eG5KJ8WBx9ntsQD2w8dn3AFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143626; c=relaxed/simple; bh=fEWBF8PBCKozsKh88Dl8//ir62QTcHuXpifaV5Nu19c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j+onIWDfwuft44mEY/zDB3xHJQ004DubIdts/ATLXtJOSWqrcrHziyhdq+4pMVaYQ9X3B1sy5WkUri8BnML2OFvICf3qymfxjzOHGyqHjZLu+FUReA4Ds8GarnYTM5yKo4R4jt9pxPN7p1uHuUclzrBvSUYQ5uyYX+J0OWORcQQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FVz9Ysuc; 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="FVz9Ysuc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7C3EBC4CEE4; Fri, 21 Feb 2025 13:13:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143626; bh=fEWBF8PBCKozsKh88Dl8//ir62QTcHuXpifaV5Nu19c=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FVz9YsuceClZyFp8iad1UJVKSN7bOU284dvNNwVWeffp278qeaCgqqHehIlcNHst0 x2RU7gjp2Ps9+34Lv7g84HW4ESr2DWCmOzGsSy3OjAoXr9y2IGzl8jM0Uf5tZjlNbq lLDuy1u6IjdIVxam5lJcTHDnqRo9BCw0Cj+LaH8nHdbvcs6/rcrgU+2siJrPGhLD+e s5kEbsMwmfCKSvO3oPsd4hFQDovxftGi5OqbfMbl751FV7CnQ7juc2jwMh5lSJfjOy 2HjkJ1yC9E7PQ+2zl8cBqn0HfEFEB8ZuGYs4t60pXs2nLWSuF5/1Y3ZR5VlAh5UWJ1 e8zHPjvZzwyHQ== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:05 +0100 Subject: [PATCH RFC 06/16] fs: create detached mounts from detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-6-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=5082; i=brauner@kernel.org; h=from:subject:message-id; bh=fEWBF8PBCKozsKh88Dl8//ir62QTcHuXpifaV5Nu19c=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP610XMT/4zokNXGsuumP9vz9Zhq/2ebrzOYsrs9X C753lL+2lHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjAR41RGhj6R6VmCsu1X21In ypywP9pbqL0s6X1YzHKvxkn8qUy5ngz/bHRnzlfc9lzwptKNU4+OMXJJsh3Pu1y24Nq8lLvV71b GMgMA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add the ability to create detached mounts from detached mounts. Currently, detached mounts can only be created from attached mounts. This limitaton prevents various use-cases. For example, the ability to mount a subdirectory without ever having to make the whole filesystem visible first. The current permission model for the OPEN_TREE_CLONE flag of the open_tree() system call is: (1) Check that the caller is privileged over the owning user namespace of it's current mount namespace. (2) Check that the caller is located in the mount namespace of the mount it wants to create a detached copy of. While it is not strictly necessary to do it this way it is consistently applied in the new mount api. This model will also be used when allowing the creation of detached mount from another detached mount. The (1) requirement can simply be met by performing the same check as for the non-detached case, i.e., verify that the caller is privileged over its current mount namespace. To meet the (2) requirement it must be possible to infer the origin mount namespace that the anonymous mount namespace of the detached mount was created from. The origin mount namespace of an anonymous mount is the mount namespace that the mounts that were copied into the anonymous mount namespace originate from. The origin mount namespace of the anonymous mount namespace must be the same as the caller's mount namespace. To establish this the sequence number of the caller's mount namespace and the origin sequence number of the anonymous mount namespace are compared. The caller is always located in a non-anonymous mount namespace since anonymous mount namespaces cannot be setns()ed into. The caller's mount namespace will thus always have a valid sequence number. The owning namespace of any mount namespace, anonymous or non-anonymous, can never change. A mount attached to a non-anonymous mount namespace can never change mount namespace. If the sequence number of the non-anonymous mount namespace and the origin sequence number of the anonymous mount namespace match, the owning namespaces must match as well. Hence, the capability check on the owning namespace of the caller's mount namespace ensures that the caller has the ability to copy the mount tree. Signed-off-by: Christian Brauner --- fs/namespace.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/fs/namespace.c b/fs/namespace.c index c61b9704499a..66b9cea1cf66 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -998,6 +998,12 @@ static inline int check_mnt(struct mount *mnt) return mnt->mnt_ns == current->nsproxy->mnt_ns; } +static inline bool check_anonymous_mnt(struct mount *mnt) +{ + return is_anon_ns(mnt->mnt_ns) && + mnt->mnt_ns->seq_origin == current->nsproxy->mnt_ns->seq; +} + /* * vfsmount lock must be held for write */ @@ -2822,6 +2828,32 @@ static int do_change_type(struct path *path, int ms_flags) * namespace, i.e., the caller is trying to copy a mount namespace * entry from nsfs. * (3) The caller tries to copy a pidfs mount referring to a pidfd. + * (4) The caller is trying to copy a mount tree that belongs to an + * anonymous mount namespace. + * + * For that to be safe, this helper enforces that the origin mount + * namespace the anonymous mount namespace was created from is the + * same as the caller's mount namespace by comparing the sequence + * numbers. + * + * This is not strictly necessary. The current semantics of the new + * mount api enforce that the caller must be located in the same + * mount namespace as the mount tree it interacts with. Using the + * origin sequence number preserves these semantics even for + * anonymous mount namespaces. However, one could envision extending + * the api to directly operate across mount namespace if needed. + * + * The ownership of a non-anonymous mount namespace such as the + * caller's cannot change. + * => We know that the caller's mount namespace is stable. + * + * If the origin sequence number of the anonymous mount namespace is + * the same as the sequence number of the caller's mount namespace. + * => The owning namespaces are the same. + * + * ==> The earlier capability check on the owning namespace of the + * caller's mount namespace ensures that the caller has the + * ability to copy the mount tree. * * Returns true if the mount tree can be copied, false otherwise. */ @@ -2840,9 +2872,13 @@ static inline bool may_copy_tree(struct path *path) if (d_op == &pidfs_dentry_operations) return true; - return false; + if (!is_mounted(path->mnt)) + return false; + + return check_anonymous_mnt(mnt); } + static struct mount *__do_loopback(struct path *old_path, int recurse) { struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt); From patchwork Fri Feb 21 13:13:06 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985519 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 D78F920FAB4 for ; Fri, 21 Feb 2025 13:13:48 +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=1740143628; cv=none; b=I3h+dA18ipixY0ZgnzUVT5dMUDBJcLLibc6xDhMBtIFvKdvPvqRG7UmsbEX6H9tdC4vDpzAdH3UeazJFZVYaxv1/ndMhXBWnewYlQGuvSPGWNDg54TT+Bf/kElpNbAG8mmPg6uFLnCviAK4y10blxBEw3ehH1acDGOY5NWhb1LY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143628; c=relaxed/simple; bh=EpU9vR3iTxPrntp01yjIB1gXH0Ycl2lD2v7cQkn5z3k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KD3wGxBRKZUHY7n+3EwHhV75wCRxKKbhfbEgrnZXOe39fiDdKVAEHNiHojm+otvzlbRo47mfwCI7Q8bTXiRe8wLIPekWlQUcvRtggB86M+PCfUxTFwtO9T13jTkKTHK9PSJGUwHA5QdKb6e4TawiaJpUidc8XzZnWNOeRmVWcm0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XRUUBBOk; 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="XRUUBBOk" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B4B24C4CED6; Fri, 21 Feb 2025 13:13:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143628; bh=EpU9vR3iTxPrntp01yjIB1gXH0Ycl2lD2v7cQkn5z3k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=XRUUBBOkTOP7YyYjRbo6onC9Ejuwu1LygyxLlb2hWsgC+xwRPhF26XqL2SGYwcw1c FvkH4HCusd/CR7zJx/Vm7PMqQOP9K+z4YYYSnbSTJuIIwhE3yrPTn/h6UZVjgpqZeC UCYDqbLyv1Ti2CALg06oocSsS72f3E0koUQfG2RONXIt8QyTJgwCC5qnjyY3F+LZ6Q bAMou/S32duwEPENk/7XaAxSlslI0QHocV7O8CkL1pme8X7EzDFLgympr94gieC4bJ gYgr0YueZC5YEfk51PlgzkhcSFQB8IMrrVUwy2Du/16MKnWL14d9OrfC7hPnNAqgIm tOrXtSezshRfg== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:06 +0100 Subject: [PATCH RFC 07/16] selftests: create detached mounts from detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-7-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=11831; i=brauner@kernel.org; h=from:subject:message-id; bh=EpU9vR3iTxPrntp01yjIB1gXH0Ycl2lD2v7cQkn5z3k=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP41xavy3t8oU7b/ejeXcVS5iv6zCP+0vequveOhs kMpp1fHd5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzkxglGhruCxZGOT9Yce1Ew aX/s0m/x9zQfPDne/PQyZ+f7KNngl6UM/53vR34XN7cO2DhVuSzVaa7Oo8kS9lcOLjfZfD+hc/L +3WwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 283 +++++++++++++++++++++ 1 file changed, 283 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 70f65eb320a7..885d98f2d889 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -126,6 +126,26 @@ #endif #endif +#ifndef __NR_move_mount + #if defined __alpha__ + #define __NR_move_mount 539 + #elif defined _MIPS_SIM + #if _MIPS_SIM == _MIPS_SIM_ABI32 /* o32 */ + #define __NR_move_mount 4429 + #endif + #if _MIPS_SIM == _MIPS_SIM_NABI32 /* n32 */ + #define __NR_move_mount 6429 + #endif + #if _MIPS_SIM == _MIPS_SIM_ABI64 /* n64 */ + #define __NR_move_mount 5429 + #endif + #elif defined __ia64__ + #define __NR_move_mount (428 + 1024) + #else + #define __NR_move_mount 429 + #endif +#endif + #ifndef MOUNT_ATTR_IDMAP #define MOUNT_ATTR_IDMAP 0x00100000 #endif @@ -157,6 +177,51 @@ 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; @@ -397,6 +462,10 @@ FIXTURE_SETUP(mount_setattr) ASSERT_EQ(mkdir("/tmp/B/BB", 0777), 0); + ASSERT_EQ(mkdir("/tmp/target1", 0777), 0); + + ASSERT_EQ(mkdir("/tmp/target2", 0777), 0); + ASSERT_EQ(mount("testing", "/tmp/B/BB", "tmpfs", MS_NOATIME | MS_NODEV, "size=100000,mode=700"), 0); @@ -1506,4 +1575,218 @@ TEST_F(mount_setattr, mount_attr_nosymfollow) ASSERT_EQ(close(fd), 0); } +TEST_F(mount_setattr, open_tree_detached) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /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 + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + fd_tree_subdir = sys_open_tree(fd_tree_base, "A/AA", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_subdir, 0); + /* + * /AA testing tmpfs + * `-/AA/B testing tmpfs + * `-/AA/B/BB testing tmpfs + */ + ASSERT_EQ(statx(fd_tree_subdir, "B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_subdir, "B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + ASSERT_EQ(move_mount(fd_tree_subdir, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + /* + * /tmp/target1 testing tmpfs + * `-/tmp/target1/B testing tmpfs + * `-/tmp/target1/B/BB testing tmpfs + */ + ASSERT_EQ(statx(-EBADF, "/tmp/target1", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target1/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target1/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + ASSERT_EQ(move_mount(fd_tree_base, "", -EBADF, "/tmp/target2", MOVE_MOUNT_F_EMPTY_PATH), 0); + /* + * /tmp/target2 testing tmpfs + * |-/tmp/target2/A testing tmpfs + * | `-/tmp/target2/A/AA testing tmpfs + * | `-/tmp/target2/A/AA/B testing tmpfs + * | `-/tmp/target2/A/AA/B/BB testing tmpfs + * `-/tmp/target2/B testing ramfs + */ + ASSERT_EQ(statx(-EBADF, "/tmp/target2", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target2/A", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target2/A/AA", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target2/A/AA/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target2/A/AA/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(-EBADF, "/tmp/target2/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + EXPECT_EQ(close(fd_tree_base), 0); + EXPECT_EQ(close(fd_tree_subdir), 0); +} + +TEST_F(mount_setattr, open_tree_detached_fail) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /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 + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + ASSERT_EQ(unshare(CLONE_NEWNS), 0); + + /* + * The origin mount namespace of the anonymous mount namespace + * of @fd_tree_base doesn't match the caller's mount namespace + * anymore so creation of another detached mounts must fail. + */ + fd_tree_subdir = sys_open_tree(fd_tree_base, "A/AA", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_LT(fd_tree_subdir, 0); + ASSERT_EQ(errno, EINVAL); +} + +TEST_F(mount_setattr, open_tree_detached_fail2) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /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 + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + EXPECT_EQ(create_and_enter_userns(), 0); + + /* + * The caller entered a new user namespace. They will have + * CAP_SYS_ADMIN in this user namespace. However, they're still + * located in a mount namespace that is owned by an ancestor + * user namespace in which they hold no privilege. Creating a + * detached mount must thus fail. + */ + fd_tree_subdir = sys_open_tree(fd_tree_base, "A/AA", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_LT(fd_tree_subdir, 0); + ASSERT_EQ(errno, EPERM); +} + +TEST_F(mount_setattr, open_tree_detached_fail3) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /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 + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_EQ(statx(fd_tree_base, "A/AA/B/BB", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + EXPECT_EQ(prepare_unpriv_mountns(), 0); + + /* + * The caller entered a new mount namespace. They will have + * CAP_SYS_ADMIN in the owning user namespace of their mount + * namespace. + * + * However, the origin mount namespace of the anonymous mount + * namespace of @fd_tree_base doesn't match the caller's mount + * namespace anymore so creation of another detached mounts must + * fail. + */ + fd_tree_subdir = sys_open_tree(fd_tree_base, "A/AA", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_LT(fd_tree_subdir, 0); + ASSERT_EQ(errno, EINVAL); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:07 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985520 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 DE286211489 for ; Fri, 21 Feb 2025 13:13:50 +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=1740143630; cv=none; b=dsmUYwnSjsoPSTQIm+2RI0M87yNyZIOxvyH+XQMx5q9J8ne7wiGf6wCyh/LX7Iz+GwiTCFFSWAP6mAgGuM2s4CEVqkGg5tUiqtfum81sMwxWi+VPlLtd0cKDnkr3nlnWB2noJXyNG7lhzKuJwi1tJSM1luvNrBWA/HuHWFIIVD8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143630; c=relaxed/simple; bh=yuDWZ9+eDo5W/hiMFBgT4qAe2LTa/3e3Mq/F6p8d4bQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DxVUOdILkuw6zZzLipUpCMQkqeZj9TZ97igVVlFBxSiUthVeRsDTKmm70IbY0Pi7O8yhylVlBdBLU3buptxO6EoYNKP7woT8BL4uUeLPAX4apDHWvc+mtf10vQV8x2/XOVJaQPGOLjyb6zepEwYdY/Q4JKRjGjBJE2acGH4pbKY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ho5HW5Ju; 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="ho5HW5Ju" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D3BA6C4CEE7; Fri, 21 Feb 2025 13:13:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143630; bh=yuDWZ9+eDo5W/hiMFBgT4qAe2LTa/3e3Mq/F6p8d4bQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ho5HW5Ju9zv9pigO9266YkZkYQSRAM/FubCzQ661BtUM2Ix0R5oQxe2I241lj8hnl EcH1X5g3auAJGPXa0v80fLGNc6lz5wc9zQylPyCJm8fvOgQyYLZCrHCvv7YUxJYEDQ nJPZSO2VR8BzKvH+w+Kn5C1cl3/Y7dCPuyXSWbpIhBaQxS/IipwpeCSBmq1i7JSSgS BlOC7rRaekc9edf3xM9APshdqGZG2CrWQr6Fd3SnfWIFkX4tgUEyVXfMQsiJuNIbun LmYF9il6NhLUr0gO3krMX37v0z09QHDQHSDYFzig9G4rHQ08U7w8/Zw5bsn7uGvmW3 Vn86gmyke3deg== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:07 +0100 Subject: [PATCH RFC 08/16] fs: support getname_maybe_null() in move_mount() Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-8-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=5677; i=brauner@kernel.org; h=from:subject:message-id; bh=yuDWZ9+eDo5W/hiMFBgT4qAe2LTa/3e3Mq/F6p8d4bQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP51o2fRokMrfhjbLZl2u5D95Jy/wUdjl0p2XGmPn Mz0d87Fhx2lLAxiXAyyYoosDu0m4XLLeSo2G2VqwMxhZQIZwsDFKQATqbrN8FdmfcLsBz+KH94+ 09eu7Cl1Qfts/PmVvpx+iwsWqXyL457PyLCnf0aPePsunhSxhkV/W6M26543O2llu6pLX/SSQX2 kCRcA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Allow move_mount() to work with NULL path arguments. Signed-off-by: Christian Brauner --- fs/namespace.c | 93 +++++++++++++++++++++++++++++++++++------------------- include/linux/fs.h | 1 + 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 66b9cea1cf66..612f73481d35 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2465,6 +2465,7 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt) enum mnt_tree_flags_t { MNT_TREE_MOVE = BIT(0), MNT_TREE_BENEATH = BIT(1), + MNT_TREE_PROPAGATION = BIT(2), }; /** @@ -3434,8 +3435,8 @@ static int can_move_mount_beneath(const struct path *from, return 0; } -static int do_move_mount(struct path *old_path, struct path *new_path, - bool beneath) +static int do_move_mount(struct path *old_path, + struct path *new_path, enum mnt_tree_flags_t flags) { struct mnt_namespace *ns; struct mount *p; @@ -3443,8 +3444,7 @@ static int do_move_mount(struct path *old_path, struct path *new_path, struct mount *parent; struct mountpoint *mp, *old_mp; int err; - bool attached; - enum mnt_tree_flags_t flags = 0; + bool attached, beneath = flags & MNT_TREE_BENEATH; mp = do_lock_mount(new_path, beneath); if (IS_ERR(mp)) @@ -3545,7 +3545,7 @@ static int do_move_mount_old(struct path *path, const char *old_name) if (err) return err; - err = do_move_mount(&old_path, path, false); + err = do_move_mount(&old_path, path, 0); path_put(&old_path); return err; } @@ -4386,6 +4386,21 @@ SYSCALL_DEFINE3(fsmount, int, fs_fd, unsigned int, flags, return ret; } +static inline int vfs_move_mount(struct path *from_path, struct path *to_path, + enum mnt_tree_flags_t mflags) +{ + int ret; + + ret = security_move_mount(from_path, to_path); + if (ret) + return ret; + + if (mflags & MNT_TREE_PROPAGATION) + return do_set_group(from_path, to_path); + + return do_move_mount(from_path, to_path, mflags); +} + /* * Move a mount from one place to another. In combination with * fsopen()/fsmount() this is used to install a new mount and in combination @@ -4399,8 +4414,12 @@ SYSCALL_DEFINE5(move_mount, int, to_dfd, const char __user *, to_pathname, unsigned int, flags) { - struct path from_path, to_path; - unsigned int lflags; + struct path to_path __free(path_put) = {}; + struct path from_path __free(path_put) = {}; + struct filename *to_name __free(putname) = NULL; + struct filename *from_name __free(putname) = NULL; + unsigned int lflags, uflags; + enum mnt_tree_flags_t mflags = 0; int ret = 0; if (!may_mount()) @@ -4413,43 +4432,51 @@ SYSCALL_DEFINE5(move_mount, (MOVE_MOUNT_BENEATH | MOVE_MOUNT_SET_GROUP)) return -EINVAL; - /* If someone gives a pathname, they aren't permitted to move - * from an fd that requires unmount as we can't get at the flag - * to clear it afterwards. - */ + if (flags & MOVE_MOUNT_SET_GROUP) mflags |= MNT_TREE_PROPAGATION; + if (flags & MOVE_MOUNT_BENEATH) mflags |= MNT_TREE_BENEATH; + lflags = 0; if (flags & MOVE_MOUNT_F_SYMLINKS) lflags |= LOOKUP_FOLLOW; if (flags & MOVE_MOUNT_F_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; - if (flags & MOVE_MOUNT_F_EMPTY_PATH) lflags |= LOOKUP_EMPTY; - - ret = user_path_at(from_dfd, from_pathname, lflags, &from_path); - if (ret < 0) - return ret; + if (flags & MOVE_MOUNT_F_EMPTY_PATH) uflags = AT_EMPTY_PATH; + from_name = getname_maybe_null(from_pathname, uflags); + if (IS_ERR(from_name)) + return PTR_ERR(from_name); lflags = 0; if (flags & MOVE_MOUNT_T_SYMLINKS) lflags |= LOOKUP_FOLLOW; if (flags & MOVE_MOUNT_T_AUTOMOUNTS) lflags |= LOOKUP_AUTOMOUNT; - if (flags & MOVE_MOUNT_T_EMPTY_PATH) lflags |= LOOKUP_EMPTY; + if (flags & MOVE_MOUNT_T_EMPTY_PATH) uflags = AT_EMPTY_PATH; + to_name = getname_maybe_null(to_pathname, uflags); + if (IS_ERR(to_name)) + return PTR_ERR(to_name); + + if (!to_name && to_dfd >= 0) { + CLASS(fd_raw, f_to)(to_dfd); + if (fd_empty(f_to)) + return -EBADF; + + to_path = fd_file(f_to)->f_path; + path_get(&to_path); + } else { + ret = filename_lookup(to_dfd, to_name, lflags, &to_path, NULL); + if (ret) + return ret; + } - ret = user_path_at(to_dfd, to_pathname, lflags, &to_path); - if (ret < 0) - goto out_from; + if (!from_name && from_dfd >= 0) { + CLASS(fd_raw, f_from)(from_dfd); + if (fd_empty(f_from)) + return -EBADF; - ret = security_move_mount(&from_path, &to_path); - if (ret < 0) - goto out_to; + return vfs_move_mount(&fd_file(f_from)->f_path, &to_path, mflags); + } - if (flags & MOVE_MOUNT_SET_GROUP) - ret = do_set_group(&from_path, &to_path); - else - ret = do_move_mount(&from_path, &to_path, - (flags & MOVE_MOUNT_BENEATH)); + ret = filename_lookup(from_dfd, from_name, lflags, &from_path, NULL); + if (ret) + return ret; -out_to: - path_put(&to_path); -out_from: - path_put(&from_path); - return ret; + return vfs_move_mount(&from_path, &to_path, mflags); } /* diff --git a/include/linux/fs.h b/include/linux/fs.h index e71d58c7f59c..7e9df867538d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2855,6 +2855,7 @@ static inline struct filename *getname_maybe_null(const char __user *name, int f return __getname_maybe_null(name); } extern void putname(struct filename *name); +DEFINE_FREE(putname, struct filename *, if (!IS_ERR_OR_NULL(_T)) putname(_T)) extern int finish_open(struct file *file, struct dentry *dentry, int (*open)(struct inode *, struct file *)); From patchwork Fri Feb 21 13:13:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985521 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 E95EC2116ED for ; Fri, 21 Feb 2025 13:13:52 +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=1740143633; cv=none; b=KsLoHzqjwV/fO9rx0NpwzX9w1fmki54JEjOH8JjeFJt2TO5DhL5to6h7WYgjTC2VsooC7UR5v6E1hAe/xidnKXEIeKVXwLgogSf/Vt+ZcFbxLPotLmTY8x3fED6p+1Cm8/gCZ+x0a6pBuQbXxl8jY0nfu25RkC4PSvzXc196nfM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143633; c=relaxed/simple; bh=4mn5sqjIh2I8TbK20gfMxw4oSuvjmtmIZUUFqH+UwpI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A/0A76uOCT5bZAPjBEPL2RAy0mlq3PMRCWShT8JLE+1NV+Sc2nQjUtsTPiVO4v9uA1rBzwATbx8yKjFmMirHAvmbX3aCU2AOUdyq1WFarkOsUTa4dEqXQG6Wm9y9VeTRRedRe66SwbNrFHCQQ/qM6LWrIcrwcn1DdjfbndRUidk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MDtJ4pZi; 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="MDtJ4pZi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D4529C4CED6; Fri, 21 Feb 2025 13:13:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143632; bh=4mn5sqjIh2I8TbK20gfMxw4oSuvjmtmIZUUFqH+UwpI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MDtJ4pZiOI8UzOaiQMhHiW+lRmK8RwGQsT9VAAaFDub6UMd3tvs5VFYg5ubnREWAN YZPOKhgMhmMXiQbhDysy6LpS/YCfLoJl/hNgvWj7YXFbskP+SuU4lVQy+wV2d++GPc 2pGWY2xWrcV0B90+kQbzFgZC51WlXj1fpRm6c3SkF2rqUfH6bRdYoOgVYcahqYcIUw lgNxvbVc2//OZyEYpgJAjKSQVdiWg02dJOASG13lpulC1w6iDIWAZJa18FBxFuY2TZ WZrsB266/2CzppbOXKE3fu+Yk/LM4wmsYbECWOmDSSTsXRWw/BrJFvI9YDBRp5+Bew QLXNFle2iz92w== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:08 +0100 Subject: [PATCH RFC 09/16] fs: mount detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-9-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=6075; i=brauner@kernel.org; h=from:subject:message-id; bh=4mn5sqjIh2I8TbK20gfMxw4oSuvjmtmIZUUFqH+UwpI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP51p6zIR4Ah52lOBROHX432zPJFVe3du3zKvoQY/ VGNNhPvKGVhEONikBVTZHFoNwmXW85TsdkoUwNmDisTyBAGLk4BmIh+AsNf0YOOt5ZHBa1UV+UQ MO4qubRg5uWPa6rPi/3Zs23zGpartxj+F6rFCqhZbPeRtey/GtLzM/uuTP/9625TOnQeqofs4Cz mAAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Currently, detached mounts can only be mounted onto attached mounts. This limitation makes it impossible to assemble a new private rootfs and move it into place. That's an extremely powerful concept for container and service workloads that we should support. Right now, a detached tree must be created, attached, then it can gain additional mounts and then it can either be moved (if it doesn't reside under a shared mount) or a detached mount created again. Lift this restriction. In order to allow mounting detached mounts onto other detached mounts the same permission model used for creating detached mounts from detached mounts can be used: (1) Check that the caller is privileged over the owning user namespace of it's current mount namespace. (2) Check that the caller is located in the mount namespace of the mount it wants to create a detached copy of. The origin mount namespace of the anonymous mount namespace must be the same as the caller's mount namespace. To establish this the sequence number of the caller's mount namespace and the origin sequence number of the anonymous mount namespace are compared. The caller is always located in a non-anonymous mount namespace since anonymous mount namespaces cannot be setns()ed into. The caller's mount namespace will thus always have a valid sequence number. The owning namespace of any mount namespace, anonymous or non-anonymous, can never change. A mount attached to a non-anonymous mount namespace can never change mount namespace. If the sequence number of the non-anonymous mount namespace and the origin sequence number of the anonymous mount namespace match, the owning namespaces must match as well. Hence, the capability check on the owning namespace of the caller's mount namespace ensures that the caller has the ability to attach the mount tree. Signed-off-by: Christian Brauner --- fs/namespace.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 612f73481d35..0242d0dc6b47 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2295,6 +2295,24 @@ void dissolve_on_fput(struct vfsmount *mnt) if (!must_dissolve(ns)) return; + /* + * After must_dissolve() we know that this is a detached + * mount in an anonymous mount namespace. + * + * Now when mnt_has_parent() reports that this mount + * tree has a parent, we know that this anonymous mount + * tree has been moved to another anonymous mount + * namespace. + * + * So when closing this file we cannot unmount the mount + * tree. This will be done when the file referring to + * the root of the anonymous mount namespace will be + * closed (It could already be closed but it would sync + * on @namespace_sem and wait for us to finish.). + */ + if (mnt_has_parent(m)) + return; + lock_mount_hash(); umount_tree(m, UMOUNT_CONNECTED); unlock_mount_hash(); @@ -3435,6 +3453,54 @@ static int can_move_mount_beneath(const struct path *from, return 0; } +/* may_use_mount() - check if a mount tree can be used + * @mnt: vfsmount to be used + * + * This helper checks if the caller may use the mount tree starting + * from @path->mnt. The caller may use the mount tree under the + * following circumstances: + * + * (1) The caller is located in the mount namespace of the mount tree. + * This also implies that the mount does not belong to an anonymous + * mount namespace. + * (2) The caller is trying to use a mount tree that belongs to an + * anonymous mount namespace. + * + * For that to be safe, this helper enforces that the origin mount + * namespace the anonymous mount namespace was created from is the + * same as the caller's mount namespace by comparing the sequence + * numbers. + * + * The ownership of a non-anonymous mount namespace such as the + * caller's cannot change. + * => We know that the caller's mount namespace is stable. + * + * If the origin sequence number of the anonymous mount namespace is + * the same as the sequence number of the caller's mount namespace. + * => The owning namespaces are the same. + * + * ==> The earlier capability check on the owning namespace of the + * caller's mount namespace ensures that the caller has the + * ability to use the mount tree. + * + * Returns true if the mount tree can be used, false otherwise. + */ +static inline bool may_use_mount(struct mount *mnt) +{ + if (check_mnt(mnt)) + return true; + + /* + * Make sure that noone unmounted the target path or somehow + * managed to get their hands on something purely kernel + * internal. + */ + if (!is_mounted(&mnt->mnt)) + return false; + + return check_anonymous_mnt(mnt); +} + static int do_move_mount(struct path *old_path, struct path *new_path, enum mnt_tree_flags_t flags) { @@ -3460,8 +3526,14 @@ static int do_move_mount(struct path *old_path, ns = old->mnt_ns; err = -EINVAL; - /* The mountpoint must be in our namespace. */ - if (!check_mnt(p)) + 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... */ @@ -3472,6 +3544,16 @@ 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) + goto out; + if (old->mnt.mnt_flags & MNT_LOCKED) goto out; From patchwork Fri Feb 21 13:13:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985522 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 D75552116FB for ; Fri, 21 Feb 2025 13:13:54 +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=1740143634; cv=none; b=JmpVt0kAECXtBnQJMYz7KH4+qjcZ5fod6NeHlX3EA7akOfc4nGIeeNZ1bzP4KZy7yq8k/b5taWdX6pUfDb5HlD9Ms0wvSQGfbIPwytFvmwdj077ZUCIfOxqazuPRfzU7CenBJLxaNgZeLqE9LGgiKjWBWufQqhHW/mKE73OSF38= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143634; c=relaxed/simple; bh=9vWuRBLRV3+s9+qLggYdFzY5+/UjTMa+6MuyH5bEhlA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kF8/m1mG2p90NfTl6+j9+Fnp4mLrYuGvcF2xIWczbGX0NQMWqg+KQflLph5soaceSW8cSDGLzeKyb9wMpKGapUe4FnysEawn3nBauC/4jRMrwbbruYbTA8/hmAgRqWMcYymDxL+Cqx6hSeWBD20AWY9p4PVDPOUeTNTdWnr8bMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ECeZNgAg; 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="ECeZNgAg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D39D5C4CEE4; Fri, 21 Feb 2025 13:13:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143634; bh=9vWuRBLRV3+s9+qLggYdFzY5+/UjTMa+6MuyH5bEhlA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ECeZNgAg/Qg7MZ8eRzwUvY6zapPgIARGW7BIBkEuhdgy7PnK0irjxk4LAylBVC9fb /8pGyWQk7SbMJvhzq22rseWOCJ9PwIg8jq/DXAEsYiTCyEu1ZvBS9NpVTnn7uX4wFt XVqpkAtpwLNTn0goN75DljopTdUScbUk5W2vkiA5S5WtHC6wV3StIWhy5RkqcfomZf v61bV1JdRQPMwLNAZ0gniTE337y8lKMhhzBcoUd9uV30wP3klh22jZn9eo9QAV7/KP InjxvWy5dm/qXt4qiOlRztvfGfzmAHVpEV1b7XIO/BYz0D6laNYPdMVCB3ssGxgTbM OGuw4PvXh+KlA== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:09 +0100 Subject: [PATCH RFC 10/16] selftests: first test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-10-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2084; i=brauner@kernel.org; h=from:subject:message-id; bh=9vWuRBLRV3+s9+qLggYdFzY5+/UjTMa+6MuyH5bEhlA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP4V7qDSvywxljM28opa91vp3INGN62eHuq40+I67 XxAyyTnjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIloBzD8r7KMszKruprz5Osf 29MrRCeelUhK/pTv+cA19W/Hn/O+ogz/M+f3vxMPWt9+xaTd+tydbF2rbnkNxrqOiVONGU/d/Lq dCQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 885d98f2d889..0641d2e22e02 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -1789,4 +1789,44 @@ TEST_F(mount_setattr, open_tree_detached_fail3) ASSERT_EQ(errno, EINVAL); } +TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_then_close) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /mnt testing tmpfs + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + fd_tree_subdir = sys_open_tree(fd_tree_base, "", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_EMPTY_PATH | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_subdir, 0); + /* + * /mnt testing tmpfs + */ + ASSERT_EQ(statx(fd_tree_subdir, "A", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + /* + * /mnt testing tmpfs + * `-/mnt testing tmpfs + */ + ASSERT_EQ(move_mount(fd_tree_subdir, "", fd_tree_base, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + ASSERT_EQ(statx(fd_tree_subdir, "", AT_EMPTY_PATH, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + ASSERT_NE(move_mount(fd_tree_subdir, "", fd_tree_base, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + + EXPECT_EQ(close(fd_tree_base), 0); + EXPECT_EQ(close(fd_tree_subdir), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985523 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 13A6C21171C for ; Fri, 21 Feb 2025 13:13:56 +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=1740143637; cv=none; b=XkaEWG66HVzjmAD8g4/oPDbgN+9CIWUpJBoszV4vDlNlOSU05Af4UCcUJsrndCog5fzVoQ+v2qknC4NAPvBy2ajwi5YM1wvAnk+hbdQdXb6ix2rOEPQSOfqOC49M2tvbQefK56p9kHUA7h7BphM/VQXvtCGEIkpvlSY9KPSRhlI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143637; c=relaxed/simple; bh=7ES0SPMiRlraClgcS8merlzkxXeLOVw73ScNSfGlIBk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DwOsGaONLRY5wOoTWoMi9f+ZrEgTESUiD7Lg9ydx8B6psic5OLvmN0rSnhkqDC9W3kjQn922fVNiTeTg1PeTBG9onfQkX+jF5w8eQSW5sJw767F8R3Uar564X7EHeKIuM28dxwg8FDQrKysO864nYadhMGIRQF3OiVmec0itIVg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cfxrjahA; 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="cfxrjahA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1099C4CEE7; Fri, 21 Feb 2025 13:13:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143636; bh=7ES0SPMiRlraClgcS8merlzkxXeLOVw73ScNSfGlIBk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cfxrjahA2k91T0Wsb3BYNrDu1Ikp7ntI1Jp9KZMHdni9hwyzTD/oWVhfing795ULQ yyiwt5l2eSda0fWxseCaRRqA3XUtojCmqBSW2aLTdipLTwgJIH9SbPB7rGwgVRt9LP 5OOnaGcXnArQY/5OukY79XvbRJ9qucLlkfgWpOhwueJf8amz8ui169tYyVe6gWTgsw TyBaVtVjbSGGdkWBUR4XhLrppYqYJew9BJRSDARMjAdFa2ZbP5zDSmMf3Fau7MuSlA N4mbP4LZ4o5qqEcIuGJgbfSYX++LWyxsd3GqtIolaLuYkrFpww2dTCOPFQZ+hwreYc JlF1Oc4BuSqqg== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:10 +0100 Subject: [PATCH RFC 11/16] selftests: second test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-11-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2566; i=brauner@kernel.org; h=from:subject:message-id; bh=7ES0SPMiRlraClgcS8merlzkxXeLOVw73ScNSfGlIBk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP4dPUl+v958TR7m4hXlEbcWpCl9ZvSYzfmda6ltz drnP2dt7ihlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIhNuMDJMlDO6ndGR2P4h8 GieYLfDkM/eZ5rOCyXoHEsSz5Y5L/WNkuByuvtn0XJ9eymlLlYgj3ZksaZydwZ4TJx/NPjTrpFI 4PwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 0641d2e22e02..082fdf19a9be 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -1829,4 +1829,53 @@ TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_then_close) EXPECT_EQ(close(fd_tree_subdir), 0); } +TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_and_attach) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + __u64 mnt_id = 0; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + /* + * /mnt testing tmpfs + */ + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + fd_tree_subdir = sys_open_tree(fd_tree_base, "", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_EMPTY_PATH | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_subdir, 0); + /* + * /mnt testing tmpfs + */ + ASSERT_EQ(statx(fd_tree_subdir, "A", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + /* + * /mnt testing tmpfs + * `-/mnt testing tmpfs + */ + ASSERT_EQ(move_mount(fd_tree_subdir, "", fd_tree_base, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + ASSERT_EQ(statx(fd_tree_subdir, "", AT_EMPTY_PATH, STATX_MNT_ID_UNIQUE, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_TRUE(stx.stx_mask & STATX_MNT_ID_UNIQUE); + mnt_id = stx.stx_mnt_id; + + ASSERT_NE(move_mount(fd_tree_subdir, "", fd_tree_base, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + + ASSERT_EQ(move_mount(fd_tree_base, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + ASSERT_EQ(statx(-EBADF, "/tmp/target1", 0, STATX_MNT_ID_UNIQUE, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + ASSERT_TRUE(stx.stx_mask & STATX_MNT_ID_UNIQUE); + ASSERT_EQ(stx.stx_mnt_id, mnt_id); + + EXPECT_EQ(close(fd_tree_base), 0); + EXPECT_EQ(close(fd_tree_subdir), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985524 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 22B8C211A34 for ; Fri, 21 Feb 2025 13:13:58 +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=1740143639; cv=none; b=s0pc6Qsx26mG5NO9YXrd5bC8E6cT4EumcqCVkPbNwyb45CVv3aDPc3PS7BXegLhG1XYLuvQQj6cm3tB/S4paVVUV7Gknghs1oa12qjueQR8m/IDdpORfq/2bldYYj1QyHY0sSoXfXPxID8A9DYhwCL4gBf6jp6Gt230e1TCBEGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143639; c=relaxed/simple; bh=IdaZHoyqspeQIqWiK2q6Mp1xak8pva5nTXBx5vOkmFs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j9AgieRBuPue1lKJzbQGlvHUaEwuxz0q1iOdbbSA/IEACwm0+OYirTd4jUxdUhSRGnRAuh9ep1UOqHjH7BO+/Hk8mKDZ8F6h/UwzlxdmOm6bxcyMEOc+zk6tezRT+oN/vIVyyD3C9IplqVHgtJ1gXPvG82AZWTCbis1yiEK69a0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ampFzA+J; 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="ampFzA+J" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05C61C4CED6; Fri, 21 Feb 2025 13:13:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143638; bh=IdaZHoyqspeQIqWiK2q6Mp1xak8pva5nTXBx5vOkmFs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ampFzA+JdNXLBUrDMqtUAnKF37H3zwcuPJ8/6GujxU21eaoBSatzuYM2KeBZ4DM86 ADozZaaPyu++VO4OMi4jjqVN17qRfVnTHVpUDUqhwjtmlxu9VLNcNvledUz4FE8uc+ Pld+qjdkpGttgc2EbtOlKSxwUJxaXi7Wakb/MIJEJT7/o7CpV6hZDDDLnVq4F0hvnN j3EfL6+tFWPSWS8Eb+GwyGHANCEIueBT/opRyW5YB/JDmzRr76dtHrzFNV2SlxfJUo ekqi0i32eXmQbALKKB+hzDbLAuly/LbBm7RczsyRy8A4J+0gsvFCGqUwDz7/a85Rrx 4I54I2UWzmKcA== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:11 +0100 Subject: [PATCH RFC 12/16] selftests: third test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-12-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=1933; i=brauner@kernel.org; h=from:subject:message-id; bh=IdaZHoyqspeQIqWiK2q6Mp1xak8pva5nTXBx5vOkmFs=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP79SWgj3zqe78uvmrbzsctlTzwfrRH2c6v8tL8+L 6seW6SLdJSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzkjSbDP8MDKbsz1j+ZaKfZ vvjuZo0nluHr2Fj2mihHLVqreHo6syzD/3rvbwp3uy4fKkleXr11U+Xx7dfkf3Q6SEZceKlyd8W 6uxwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 31 ++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 082fdf19a9be..66eed84c6a01 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -1878,4 +1878,35 @@ TEST_F(mount_setattr, mount_detached_mount_on_detached_mount_and_attach) EXPECT_EQ(close(fd_tree_subdir), 0); } +TEST_F(mount_setattr, move_mount_detached_fail) +{ + int fd_tree_base = -EBADF, fd_tree_subdir = -EBADF; + struct statx stx; + + fd_tree_base = sys_open_tree(-EBADF, "/mnt", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_base, 0); + + /* Attach the mount to the caller's mount namespace. */ + ASSERT_EQ(move_mount(fd_tree_base, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + + ASSERT_EQ(statx(fd_tree_base, "A", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + fd_tree_subdir = sys_open_tree(-EBADF, "/tmp/B", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE); + ASSERT_GE(fd_tree_subdir, 0); + ASSERT_EQ(statx(fd_tree_subdir, "BB", 0, 0, &stx), 0); + ASSERT_FALSE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + /* Not allowed to move an attached mount to a detached mount. */ + ASSERT_NE(move_mount(fd_tree_base, "", fd_tree_subdir, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + ASSERT_EQ(errno, EINVAL); + + EXPECT_EQ(close(fd_tree_base), 0); + EXPECT_EQ(close(fd_tree_subdir), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985525 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 D78B6212B1B for ; Fri, 21 Feb 2025 13:14:00 +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=1740143640; cv=none; b=hlOUXtUd/Von6eBxj2nIBudjm/zvYOLHUXGyQkhg2eTIVCa54ibmefLAFbw9i1cfGAEZoHA9ufeOPiA5x3wuFWljpNcskueJ6taArOGvmUeZWgpPBHj5WhhyUNnPci/l9Gt/z8QJ1c93p2Joiuo0o5O5nYz0hFlT6adeXhhOZlk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143640; c=relaxed/simple; bh=r2N4D0GiQ07/7EMtDn1xGmcQj4DqX+f2azS2ymAhUhw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hhg5+2NeETl7fMJ9QQQ4ca0z7tVow37zMiCb0gLSpN/hnsmEOEHGY9CKSB4osoPvcU5esN+6/qvofar3DkJhZ0/CfSz3OamW/0oQeP3Kx+rEioDbnzp3erj66ygK19TDK8mV1S5+viIk71OTlMIT2SOVYi0I5v0VGhDwZu0clxk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=o2HaJpEn; 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="o2HaJpEn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0B389C4CEE4; Fri, 21 Feb 2025 13:13:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143640; bh=r2N4D0GiQ07/7EMtDn1xGmcQj4DqX+f2azS2ymAhUhw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=o2HaJpEn/YvAWWojmKyRSPYauC/EHY2vxFzz0FQ6vKsOlClgBnW97mBfmdTyFHTCb cpYxkQmuntg1M7jZpDqawV+G8jQ4EAtPf7ulBk/buePv7zuv40bMhL+qw59J0qQHMd x7XOqDwmxdyZ5p+DkYSWowYuMxOODxjKNh/3jYlbkEqm4XBaexqDK9cuRNcaW5/nAP 2WeL9yMquxfIB4X9zl4dGGY7GxVgTuYeC43mJRGFjyPu44Sx9in4KOqmIVbs+9U4gB kx4Pth02b3n2QtMvrpqHw+p+Ej2K9/ty9jTLPfgkmm5MKwE2y37JsNp+ijPCvX9B7x qjWZnAaLen+5Q== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:12 +0100 Subject: [PATCH RFC 13/16] selftests: fourth test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-13-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=1697; i=brauner@kernel.org; h=from:subject:message-id; bh=r2N4D0GiQ07/7EMtDn1xGmcQj4DqX+f2azS2ymAhUhw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP69Mk+wcfKF04xcb9wcGlZeeyCezn13emqx9Y8Cl 7qHJy+FdpSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExkWyXD/2SZvN1ntPdpFVhP U9ijkL79Zl7Xpmni4Y/0PuxaMUFX0Jfhf/n3qqBrAk9qw+akcUufcWG92x1/QdBIgzVKZ5+dp/8 5NgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 30 ++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 66eed84c6a01..0ee4e5b27c68 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -1909,4 +1909,34 @@ TEST_F(mount_setattr, move_mount_detached_fail) EXPECT_EQ(close(fd_tree_subdir), 0); } +TEST_F(mount_setattr, attach_detached_mount_then_umount_then_close) +{ + int fd_tree = -EBADF; + struct statx stx; + + 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(fd_tree, "A", 0, 0, &stx), 0); + /* We copied with AT_RECURSIVE so /mnt/A must be a mountpoint. */ + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + /* Attach the mount to the caller's mount namespace. */ + ASSERT_EQ(move_mount(fd_tree, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + + ASSERT_EQ(statx(-EBADF, "/tmp/target1", 0, 0, &stx), 0); + ASSERT_TRUE(stx.stx_attributes & STATX_ATTR_MOUNT_ROOT); + + ASSERT_EQ(umount2("/tmp/target1", MNT_DETACH), 0); + + /* + * This tests whether dissolve_on_fput() handles a NULL mount + * namespace correctly, i.e., that it doesn't splat. + */ + EXPECT_EQ(close(fd_tree), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985526 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 3685921018D for ; Fri, 21 Feb 2025 13:14:02 +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=1740143643; cv=none; b=W0FfI9UtypEu/3ElExZP4canrG4btaVTQsvGWnxAOTfUescrTd+Mxt5MAYAgHxoq5bPzrJie+27pfkWO/OBS2i7E2RY1TMLZeIPbfteyQOuEena7Oa6X46Oo5ypucBYBpQNEQ9mCxSYFhTo35IbQ9U/TguX0RdrzfOrwxKr97m4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143643; c=relaxed/simple; bh=CUM7AcjQ1bE0N/g/uXDnf5agWimRQMLUPaVINZNX1DU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mbzDtoQwrAmW0NxsXhHmO/u/CeTMsousuFJ02LKI6YtS8bxc47xc+wY0tK66mV9QPhYkggNfiqYVd2mmsPRXEst1LW+4w5AW6/PuQ8LyqLGjxigDUvIRsEgBVbQNm2+KqYo53L7ltPdmQeS1hWihhk039f4sPh4HVAkpmzrAZg8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LEB1SfyV; 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="LEB1SfyV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 19BF8C4CED6; Fri, 21 Feb 2025 13:14:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143642; bh=CUM7AcjQ1bE0N/g/uXDnf5agWimRQMLUPaVINZNX1DU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LEB1SfyVTNP/G/WJXJLByD3PlZClnsQEvkvfyHAk46wCJ1WnY6QyoZzYk3p7qvH/q g9a/e/ZqHVsd0Advy1kKUhxhMa6x73kK1McjI4bIb29wdeiG9gBBxFaBl10tzp6H3P 7GeSqkAz6SRp3u86UqdBQWYJz7ZZkTQI5Jayx+tkKQspyk12/1eIJl2Ao9nSmB9pED 9/mg3qwS8HkPkglIwzjSuNqBMkwChRCmSZF8eDpn5OY3zbR/7rY8r60nEO9orFFUeE ClVGqpbUIAB5brJ5BrrIYaB9efDGVNxFO95FVTA9wNvfUlHPGHGS+oObC4jnX3tGFS l/5rbXo6aRfvQ== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:13 +0100 Subject: [PATCH RFC 14/16] selftests: fifth test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-14-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=3683; i=brauner@kernel.org; h=from:subject:message-id; bh=CUM7AcjQ1bE0N/g/uXDnf5agWimRQMLUPaVINZNX1DU=; b=kA0DAAoWkcYbwGV43KIByyZiAGe4e/uhpEFef3iA6zVzsIcXbbtt4lmyCnr+VrCd42u0sKbqU Yh1BAAWCgAdFiEEQIc0Vx6nDHizMmkokcYbwGV43KIFAme4e/sACgkQkcYbwGV43KLZRQD/U2Nd N12yhLuxg0hTkZtQZx8Nc40DLV5i3w5QbKTgixIBAMA/K1/abcW8JALfV6yF9muJJV9GgDytR3X YYJA1auMH X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 78 ++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 0ee4e5b27c68..938c9e33ac00 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -1939,4 +1939,82 @@ TEST_F(mount_setattr, attach_detached_mount_then_umount_then_close) EXPECT_EQ(close(fd_tree), 0); } +TEST_F(mount_setattr, mount_detached1_onto_detached2_then_close_detached1_then_mount_detached2_onto_attached) +{ + int fd_tree1 = -EBADF, fd_tree2 = -EBADF; + + /* + * |-/mnt/A testing tmpfs + * `-/mnt/A/AA testing tmpfs + * `-/mnt/A/AA/B testing tmpfs + * `-/mnt/A/AA/B/BB testing tmpfs + */ + fd_tree1 = sys_open_tree(-EBADF, "/mnt/A", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree1, 0); + + /* + * `-/mnt/B testing ramfs + */ + fd_tree2 = sys_open_tree(-EBADF, "/mnt/B", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_EMPTY_PATH | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree2, 0); + + /* + * Move the source detached mount tree to the target detached + * mount tree. This will move all the mounts in the source mount + * tree from the source anonymous mount namespace to the target + * anonymous mount namespace. + * + * The source detached mount tree and the target detached mount + * tree now both refer to the same anonymous mount namespace. + * + * |-"" testing ramfs + * `-"" testing tmpfs + * `-""/AA testing tmpfs + * `-""/AA/B testing tmpfs + * `-""/AA/B/BB testing tmpfs + */ + ASSERT_EQ(move_mount(fd_tree1, "", fd_tree2, "", MOVE_MOUNT_F_EMPTY_PATH | MOVE_MOUNT_T_EMPTY_PATH), 0); + + /* + * The source detached mount tree @fd_tree1 is now an attached + * mount, i.e., it has a parent. Specifically, it now has the + * root mount of the mount tree of @fd_tree2 as its parent. + * + * That means we are no longer allowed to attach it as we only + * allow attaching the root of an anonymous mount tree, not + * random bits and pieces. Verify that the kernel enforces this. + */ + ASSERT_NE(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + + /* + * Closing the source detached mount tree must not unmount and + * free the shared anonymous mount namespace. The kernel will + * quickly yell at us because the anonymous mount namespace + * won't be empty when it's freed. + */ + EXPECT_EQ(close(fd_tree1), 0); + + /* + * Attach the mount tree to a non-anonymous mount namespace. + * This can only succeed if closing fd_tree1 had proper + * semantics and didn't cause the anonymous mount namespace to + * be freed. If it did this will trigger a UAF which will be + * visible on any KASAN enabled kernel. + * + * |-/tmp/target1 testing ramfs + * `-/tmp/target1 testing tmpfs + * `-/tmp/target1/AA testing tmpfs + * `-/tmp/target1/AA/B testing tmpfs + * `-/tmp/target1/AA/B/BB testing tmpfs + */ + ASSERT_EQ(move_mount(fd_tree2, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + EXPECT_EQ(close(fd_tree2), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985527 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 4467220B814 for ; Fri, 21 Feb 2025 13:14:04 +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=1740143645; cv=none; b=ZJrS9nQmgVk8rn6ykI+nyHcL/S5yxoBrftjhsniT/BWG4h/jQGZhe2FtkhNYxYcj62cSXOW0o/u6hrWys9TxnfLECiMOyMIcNl1UczqDVhSD6F1Wzs5i3dht8+WkZgI0OP0ntJHyfP3IvukmEsmkGCBco3vc9REhcRXWnAMHh4s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143645; c=relaxed/simple; bh=TikpQoOL5dJxg567LqT01WHKTVtVZgC7ie2DVaqsIHc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lhx4stf+YHXDT8pa/1wOU2wftgYBXj7A8W+iYM1GuzcqSrnI6vXrrD7ZbvLmrob+apZwmNr2qXtP0TNexFQfE8PjVXMlz8Q1/skRhSy7fQiJZYaQ1bxeIejkesd14VhRyvvkq13YS0MC871n28/gM6IFxUSrnqpgnjuqnRjrlI4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=EsaAmlXJ; 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="EsaAmlXJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F6EBC4CEE4; Fri, 21 Feb 2025 13:14:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143644; bh=TikpQoOL5dJxg567LqT01WHKTVtVZgC7ie2DVaqsIHc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=EsaAmlXJ/hfqvcN7nxNQpqnKOugsVMuoWjGyykXuY4V0my8NRTrAkvgBhmHixqkiy xwT/lOd9Fmz2fMP6LqxOl8YFPQKRI13XB1GMgF33D369wDuRflgSNZyIZ5wOLU3oEe Ge/m/L0a0r9JaKGzInQQwd+d935+jeOo3skye46qjCe4Rz6HfvOW1aITm6TMKthho0 8EzohL1iRXkMu1UatqzXLCRSNtnUqMx5Mp9E22pxwf28HNTmx0Gt3dV8eC86QvyyHs o99/DchSQ87WLmfAw5mI0sPx3XfJTY8Z68hME378jyMeSVaXNsCMaTeGGcoH5NXoeQ s9xrrs6JuRmcA== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:14 +0100 Subject: [PATCH RFC 15/16] selftests: sixth test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-15-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=2152; i=brauner@kernel.org; h=from:subject:message-id; bh=TikpQoOL5dJxg567LqT01WHKTVtVZgC7ie2DVaqsIHc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP7tyt09mTmp1U5ql5X0B/bOtDvtW9P3t50qCVl3v WijyFKejlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlsCmL47yuwcv7nma2JDivq gx+ZtczKvH5KeYZE9PcHPy9FL5Gd+Y/hf37ChKIEpQUL94TeOrp/mrDoB7M9BWU8Vt/6587afzq BlQkA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 938c9e33ac00..d2bf8b77df3f 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -2017,4 +2017,48 @@ TEST_F(mount_setattr, mount_detached1_onto_detached2_then_close_detached1_then_m EXPECT_EQ(close(fd_tree2), 0); } +TEST_F(mount_setattr, two_detached_mounts_referring_to_same_anonymous_mount_namespace) +{ + int fd_tree1 = -EBADF, fd_tree2 = -EBADF; + + /* + * Copy the following mount tree: + * + * |-/mnt/A testing tmpfs + * `-/mnt/A/AA testing tmpfs + * `-/mnt/A/AA/B testing tmpfs + * `-/mnt/A/AA/B/BB testing tmpfs + */ + fd_tree1 = sys_open_tree(-EBADF, "/mnt/A", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree1, 0); + + /* + * Create an O_PATH file descriptors with a separate struct file + * that refers to the same detached mount tree as @fd_tree1 + */ + fd_tree2 = sys_open_tree(fd_tree1, "", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_EMPTY_PATH | OPEN_TREE_CLOEXEC); + ASSERT_GE(fd_tree2, 0); + + /* + * Copy the following mount tree: + * + * |-/tmp/target1 testing tmpfs + * `-/tmp/target1/AA testing tmpfs + * `-/tmp/target1/AA/B testing tmpfs + * `-/tmp/target1/AA/B/BB testing tmpfs + */ + ASSERT_EQ(move_mount(fd_tree2, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + + /* + * This must fail as this would mean adding the same mount tree + * into the same mount tree. + */ + ASSERT_NE(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); +} + TEST_HARNESS_MAIN From patchwork Fri Feb 21 13:13:15 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 13985528 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 633BB111A8 for ; Fri, 21 Feb 2025 13:14:07 +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=1740143647; cv=none; b=SrBLgNPc+QcDvxbpR4w6h1VagnEcOCEpx+v/PSbASMZVE/7168zC3WL0va1kEnd1g8FWQEE9Ku5LG2qPHESO7Y+KPxDKfI0OIjm4bZ1wUHoKHUMRVtlmYBS2CHNeCWQk17gNBX5Bb4WcB593Xq6qlOO9p0h8WdYK2mbKs4QCj/g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1740143647; c=relaxed/simple; bh=1clxT3Zpmz6FTLemMwi5prQ4u2yWEBWniWHuv5h5jfg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qPweQekzVnS/XbA00CQ/wXaXVJ3b9Dfu5BrkefT3/NiXhsbs1hLom+7ntrPRiorWG3IIuW0EpAGaQtUwtXeZWUh8cShn0v+Q8+akGG4o81LDeqfR0YRP/2UcfJY+mV/z9jCspide781bxoFSrORUZPldaJZAIX7/shenrWB3LVo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VvW9l7hn; 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="VvW9l7hn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3D493C4CEE6; Fri, 21 Feb 2025 13:14:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1740143646; bh=1clxT3Zpmz6FTLemMwi5prQ4u2yWEBWniWHuv5h5jfg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=VvW9l7hn7oRsjVbePc8HdtcZQJedS9L/XiO97bRFhX5JuE3KI7DsR9M1Y8AtQh5fY r1nn97ZJAnf6FLglrfx4dlkvG9C7mBA966Xe9jGPIpPkCY+v3URwH5cT9f7prMRvyO 6s2sGiwEoMr6XbxyUEVLGUC3em8fqTxqwXNxV6WlmFnMXJIBupzWIAmFYIPZqUkJu4 YbWBeJtBODwJjuUmTGF3niAbAbpdLTi1WlPxQ+d30Xb4f00SY07W1m69T8s0cTN4Fz JMfojlaiols/7KsLXSlTxidkgwqo1v3Y8AUfrz9ZR+rLrCmxiA0t/nEFYZrspDdji4 d4GGD7K5kMXMg== From: Christian Brauner Date: Fri, 21 Feb 2025 14:13:15 +0100 Subject: [PATCH RFC 16/16] selftests: seventh test for mounting detached mounts onto detached mounts Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250221-brauner-open_tree-v1-16-dbcfcb98c676@kernel.org> References: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@kernel.org> In-Reply-To: <20250221-brauner-open_tree-v1-0-dbcfcb98c676@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-d23a9 X-Developer-Signature: v=1; a=openpgp-sha256; l=1961; i=brauner@kernel.org; h=from:subject:message-id; bh=1clxT3Zpmz6FTLemMwi5prQ4u2yWEBWniWHuv5h5jfg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMaTvqP496Vhc6vNGRYm7Lsq/rL785Dh/95pb6pzi/1tE9 YyXGIc87ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjI8mCG/0FdFxql9d5/fvZ6 8nMmm4di/XH/A9s/bEtQM7ef6G3afIzhn/1945OSH6x53/p77vFI2R61g3Um7yWdBau6FKy5tr9 W4QQA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a test to verify that detached mounts behave correctly. Signed-off-by: Christian Brauner --- .../selftests/mount_setattr/mount_setattr_test.c | 36 ++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index d2bf8b77df3f..1e0508cb5c2d 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -2061,4 +2061,40 @@ TEST_F(mount_setattr, two_detached_mounts_referring_to_same_anonymous_mount_name ASSERT_NE(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); } +TEST_F(mount_setattr, two_detached_subtrees_of_same_anonymous_mount_namespace) +{ + int fd_tree1 = -EBADF, fd_tree2 = -EBADF; + + /* + * Copy the following mount tree: + * + * |-/mnt/A testing tmpfs + * `-/mnt/A/AA testing tmpfs + * `-/mnt/A/AA/B testing tmpfs + * `-/mnt/A/AA/B/BB testing tmpfs + */ + fd_tree1 = sys_open_tree(-EBADF, "/mnt/A", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_RECURSIVE | OPEN_TREE_CLOEXEC | + OPEN_TREE_CLONE); + ASSERT_GE(fd_tree1, 0); + + /* + * Create an O_PATH file descriptors with a separate struct file that + * refers to a subtree of the same detached mount tree as @fd_tree1 + */ + fd_tree2 = sys_open_tree(fd_tree1, "AA", + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW | + AT_EMPTY_PATH | OPEN_TREE_CLOEXEC); + ASSERT_GE(fd_tree2, 0); + + /* + * This must fail as it is only possible to attach the root of a + * detached mount tree. + */ + ASSERT_NE(move_mount(fd_tree2, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); + + ASSERT_EQ(move_mount(fd_tree1, "", -EBADF, "/tmp/target1", MOVE_MOUNT_F_EMPTY_PATH), 0); +} + TEST_HARNESS_MAIN