From patchwork Tue Jun 1 13:55:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 12291361 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BCC9CC4708F for ; Tue, 1 Jun 2021 13:55:39 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 9DF1F613B6 for ; Tue, 1 Jun 2021 13:55:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234038AbhFAN5U (ORCPT ); Tue, 1 Jun 2021 09:57:20 -0400 Received: from mail.kernel.org ([198.145.29.99]:33130 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234021AbhFAN5T (ORCPT ); Tue, 1 Jun 2021 09:57:19 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 5EF4861376; Tue, 1 Jun 2021 13:55:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1622555738; bh=Kx5QYuSnYqBrwWf7jWxZdvP8QvEMt2pIqOD/zEeWFs4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OBZTSbQEsH+G255n3uPI5HX1XJlzIRWsOhqe1n4KMKtTfoMj+xMmqU1NiywtZPJL0 IPpfXlBSOnvvhC0I/Hul/P982KLotk+C0xPLJCvZQ+5myytnFVSa4+1q8QYrnBur9R 2unuqF14Fr58gtFTSUXs6IyR8s2xnn6Kg833mRHJUe5kf9asrzNrNYymf9IM79kFMD IviGzPSGH9H7xt/e7zocnkhk1Rtx/FcxS6NWMVfrdvoAi5NDnw52VQ72n696CsB+6g nCZh9+vBF6PUBYA8yrNNxIzs9/3Tt30qoW2B9pt5UXOVQWOY3FjQE8vEe5VQAvpopX Ervoxakg0vrlw== From: Christian Brauner To: linux-fsdevel@vger.kernel.org Cc: Christoph Hellwig , Al Viro , Mattias Nissler , Aleksa Sarai , Ross Zwisler , Christian Brauner Subject: [PATCH 1/2] mount: Support "nosymfollow" in new mount api Date: Tue, 1 Jun 2021 15:55:14 +0200 Message-Id: <20210601135515.126639-2-brauner@kernel.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210601135515.126639-1-brauner@kernel.org> References: <20210601135515.126639-1-brauner@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2412; h=from:subject; bh=yXlHfY3QsqyEM74cEU2jkg9QTPpW4jIcdB2YxT4Se6o=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMSRss7HPXHHtka39Ick3yS90/TPj8/Pnal+9qGEZsz75Xkkb F+/VjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgInMmsTwh2dKtfHN9+wX2i6btF/5fO 64+c8y4TNO7AtP62inFD3xW8XIcM2dd897C7OsmbzByi+n3nyuXJ9ltbj1Rqu2/9+Tq9X0uAA= X-Developer-Key: i=christian.brauner@ubuntu.com; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Christian Brauner Commit dab741e0e02b ("Add a "nosymfollow" mount option.") added support for the "nosymfollow" mount option allowing to block following symlinks when resolving paths. The mount option so far was only available in the old mount api. Make it available in the new mount api as well. Bonus is that it can be applied to a whole subtree not just a single mount. Cc: Christoph Hellwig Cc: Mattias Nissler Cc: Aleksa Sarai Cc: Al Viro Cc: Ross Zwisler Signed-off-by: Christian Brauner Reviewed-by: Ross Zwisler --- fs/namespace.c | 9 ++++++--- include/uapi/linux/mount.h | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index c3f1a78ba369..ab4174a3c802 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3464,9 +3464,10 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, return ret; } -#define FSMOUNT_VALID_FLAGS \ - (MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | \ - MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME | MOUNT_ATTR_NODIRATIME) +#define FSMOUNT_VALID_FLAGS \ + (MOUNT_ATTR_RDONLY | MOUNT_ATTR_NOSUID | MOUNT_ATTR_NODEV | \ + MOUNT_ATTR_NOEXEC | MOUNT_ATTR__ATIME | MOUNT_ATTR_NODIRATIME | \ + MOUNT_ATTR_NOSYMFOLLOW) #define MOUNT_SETATTR_VALID_FLAGS (FSMOUNT_VALID_FLAGS | MOUNT_ATTR_IDMAP) @@ -3487,6 +3488,8 @@ static unsigned int attr_flags_to_mnt_flags(u64 attr_flags) mnt_flags |= MNT_NOEXEC; if (attr_flags & MOUNT_ATTR_NODIRATIME) mnt_flags |= MNT_NODIRATIME; + if (attr_flags & MOUNT_ATTR_NOSYMFOLLOW) + mnt_flags |= MNT_NOSYMFOLLOW; return mnt_flags; } diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index e6524ead2b7b..dd7a166fdf9c 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -120,6 +120,7 @@ enum fsconfig_command { #define MOUNT_ATTR_STRICTATIME 0x00000020 /* - Always perform atime updates */ #define MOUNT_ATTR_NODIRATIME 0x00000080 /* Do not update directory access times */ #define MOUNT_ATTR_IDMAP 0x00100000 /* Idmap mount to @userns_fd in struct mount_attr. */ +#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 /* Do not follow symlinks */ /* * mount_setattr() From patchwork Tue Jun 1 13:55:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 12291363 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.4 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 316C7C4708F for ; Tue, 1 Jun 2021 13:55:42 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 0E301613B9 for ; Tue, 1 Jun 2021 13:55:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233871AbhFAN5W (ORCPT ); Tue, 1 Jun 2021 09:57:22 -0400 Received: from mail.kernel.org ([198.145.29.99]:33178 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234017AbhFAN5V (ORCPT ); Tue, 1 Jun 2021 09:57:21 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 96034613AE; Tue, 1 Jun 2021 13:55:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1622555740; bh=YzbBUwDeMWGiT0AR2Br7M/QG3lE0r08fL1CqkfOI1Sk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=aLMMrzseo+qKcvcJP7MxC9jTVFWdC93fXZeH5LMSuMV41JHqmfqeqsJbVf8K+mp17 uu6vT4YbTNQZqJ4bftJvrztPmX0WyaOjTAFgFoJpUT+TWCI960HSNtLbdb/W/SVNsC dJJSH54ypc6hpJTAUBVyrQDXosIkLO39zkYOM5gTvqazL7tHXrW2U0k1HKRcRfJYjC bd9CbosVBE4/ZTjkpu4vTGRz/jnI/3VOOKfSaSwTsyqIXVy6LECGCuqdXtRyCz6naU QWrRHwoQHWIfu1Dg2fFr+tKCFVLm0tIcneM8x+wEuHnrdcKEaCquWWVqSEqqAaTn2J BNYfqSHbOlqhw== From: Christian Brauner To: linux-fsdevel@vger.kernel.org Cc: Christoph Hellwig , Al Viro , Mattias Nissler , Aleksa Sarai , Ross Zwisler , Christian Brauner Subject: [PATCH 2/2] tests: test MOUNT_ATTR_NOSYMFOLLOW with mount_setattr() Date: Tue, 1 Jun 2021 15:55:15 +0200 Message-Id: <20210601135515.126639-3-brauner@kernel.org> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20210601135515.126639-1-brauner@kernel.org> References: <20210601135515.126639-1-brauner@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4769; h=from:subject; bh=cpwDOoxglal5Bq5peEgodqurmQKN4mTuqs3drqG2Izc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMSRss3HQTOZ9Me1x3jzD+U0tWyLat0w2+PTj27XPqstjJG7M XRCs3VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjAReUuGv5KXT85I+FVyp2Wj3IW4ey sUXf6XvInov/NbXUOmxEiCRYKR4fZXN16u8pQFeyZFaXsUX1mUq7sxO2/T1K1OGooT522r4wMA X-Developer-Key: i=christian.brauner@ubuntu.com; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org From: Christian Brauner Add tests to verify that MOUNT_ATTR_NOSYMFOLLOW is honored. Cc: Christoph Hellwig Cc: Mattias Nissler Cc: Aleksa Sarai Cc: Al Viro Cc: Ross Zwisler Signed-off-by: Christian Brauner Reviewed-by: Ross Zwisler --- .../mount_setattr/mount_setattr_test.c | 88 ++++++++++++++++++- 1 file changed, 85 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/mount_setattr/mount_setattr_test.c b/tools/testing/selftests/mount_setattr/mount_setattr_test.c index 4e94e566e040..f31205f04ee0 100644 --- a/tools/testing/selftests/mount_setattr/mount_setattr_test.c +++ b/tools/testing/selftests/mount_setattr/mount_setattr_test.c @@ -136,6 +136,10 @@ struct mount_attr { #define MOUNT_ATTR_IDMAP 0x00100000 #endif +#ifndef MOUNT_ATTR_NOSYMFOLLOW +#define MOUNT_ATTR_NOSYMFOLLOW 0x00200000 +#endif + static inline int sys_mount_setattr(int dfd, const char *path, unsigned int flags, struct mount_attr *attr, size_t size) { @@ -235,6 +239,10 @@ static int prepare_unpriv_mountns(void) return 0; } +#ifndef ST_NOSYMFOLLOW +#define ST_NOSYMFOLLOW 0x2000 /* do not follow symlinks */ +#endif + static int read_mnt_flags(const char *path) { int ret; @@ -245,9 +253,9 @@ static int read_mnt_flags(const char *path) if (ret != 0) return -EINVAL; - if (stat.f_flag & - ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC | ST_NOATIME | - ST_NODIRATIME | ST_RELATIME | ST_SYNCHRONOUS | ST_MANDLOCK)) + if (stat.f_flag & ~(ST_RDONLY | ST_NOSUID | ST_NODEV | ST_NOEXEC | + ST_NOATIME | ST_NODIRATIME | ST_RELATIME | + ST_SYNCHRONOUS | ST_MANDLOCK | ST_NOSYMFOLLOW)) return -EINVAL; mnt_flags = 0; @@ -269,6 +277,8 @@ static int read_mnt_flags(const char *path) mnt_flags |= MS_SYNCHRONOUS; if (stat.f_flag & ST_MANDLOCK) mnt_flags |= ST_MANDLOCK; + if (stat.f_flag & ST_NOSYMFOLLOW) + mnt_flags |= ST_NOSYMFOLLOW; return mnt_flags; } @@ -368,8 +378,13 @@ static bool mount_setattr_supported(void) FIXTURE(mount_setattr) { }; +#define NOSYMFOLLOW_TARGET "/mnt/A/AA/data" +#define NOSYMFOLLOW_SYMLINK "/mnt/A/AA/symlink" + FIXTURE_SETUP(mount_setattr) { + int fd = -EBADF; + if (!mount_setattr_supported()) SKIP(return, "mount_setattr syscall not supported"); @@ -412,6 +427,11 @@ FIXTURE_SETUP(mount_setattr) ASSERT_EQ(mount("testing", "/tmp/B/BB", "devpts", MS_RELATIME | MS_NOEXEC | MS_RDONLY, 0), 0); + + fd = creat(NOSYMFOLLOW_TARGET, O_RDWR | O_CLOEXEC); + ASSERT_GT(fd, 0); + ASSERT_EQ(symlink(NOSYMFOLLOW_TARGET, NOSYMFOLLOW_SYMLINK), 0); + ASSERT_EQ(close(fd), 0); } FIXTURE_TEARDOWN(mount_setattr) @@ -1421,4 +1441,66 @@ TEST_F(mount_setattr_idmapped, idmap_mount_tree_invalid) ASSERT_EQ(expected_uid_gid(open_tree_fd, "B/BB/b", 0, 0, 0), 0); } +TEST_F(mount_setattr, mount_attr_nosymfollow) +{ + int fd; + unsigned int old_flags = 0, new_flags = 0, expected_flags = 0; + struct mount_attr attr = { + .attr_set = MOUNT_ATTR_NOSYMFOLLOW, + }; + + if (!mount_setattr_supported()) + SKIP(return, "mount_setattr syscall not supported"); + + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); + ASSERT_GT(fd, 0); + ASSERT_EQ(close(fd), 0); + + old_flags = read_mnt_flags("/mnt/A"); + ASSERT_GT(old_flags, 0); + + ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0); + + expected_flags = old_flags; + expected_flags |= ST_NOSYMFOLLOW; + + new_flags = read_mnt_flags("/mnt/A"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA/B"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA/B/BB"); + ASSERT_EQ(new_flags, expected_flags); + + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); + ASSERT_LT(fd, 0); + ASSERT_EQ(errno, ELOOP); + + attr.attr_set &= ~MOUNT_ATTR_NOSYMFOLLOW; + attr.attr_clr |= MOUNT_ATTR_NOSYMFOLLOW; + + ASSERT_EQ(sys_mount_setattr(-1, "/mnt/A", AT_RECURSIVE, &attr, sizeof(attr)), 0); + + expected_flags &= ~ST_NOSYMFOLLOW; + new_flags = read_mnt_flags("/mnt/A"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA/B"); + ASSERT_EQ(new_flags, expected_flags); + + new_flags = read_mnt_flags("/mnt/A/AA/B/BB"); + ASSERT_EQ(new_flags, expected_flags); + + fd = open(NOSYMFOLLOW_SYMLINK, O_RDWR | O_CLOEXEC); + ASSERT_GT(fd, 0); + ASSERT_EQ(close(fd), 0); +} + TEST_HARNESS_MAIN