From nobody Tue Dec 16 19:53:34 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 56237E732CD for ; Thu, 28 Sep 2023 13:03:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232650AbjI1NDp (ORCPT ); Thu, 28 Sep 2023 09:03:45 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57096 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232632AbjI1NDb (ORCPT ); Thu, 28 Sep 2023 09:03:31 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D0431A4 for ; Thu, 28 Sep 2023 06:01:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695906115; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=SWtEP6obDhInT9MlruX+BXNPufUR3rJf8VMpuhorm70=; b=fh78fpIMcBy1zXbGkflppcGWCeCkqFBP0kTxoMqzQlzNIPdhgBj5fJ03//nLT28b1vLbO4 AQ8e/XNUryLl/bKhg/lusrUCOAVBzigMPBevxC7qPQyGJbSSLv/Vzx2rkxnHyLkdfYhgoP 3lSxpHy8xKejvrnDS9PBH68d2iAib/Y= Received: from mail-ej1-f69.google.com (mail-ej1-f69.google.com [209.85.218.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-341-53Ij-TTEOpK98XF728qHXg-1; Thu, 28 Sep 2023 09:01:53 -0400 X-MC-Unique: 53Ij-TTEOpK98XF728qHXg-1 Received: by mail-ej1-f69.google.com with SMTP id a640c23a62f3a-9ae12311183so1115296366b.2 for ; Thu, 28 Sep 2023 06:01:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695906112; x=1696510912; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SWtEP6obDhInT9MlruX+BXNPufUR3rJf8VMpuhorm70=; b=nkZpNCX5Y7rLHxdY1yHjsZ78VvIxhjiXU21SUBGzeeTWhZO2NVjq3Hm1ijS1sTM0wL 6yskOoasdiQQIPqau6wmCdnrot+8vI4aJsTp9B0Ou9aamUfU+DSwbBA4loTg1edSa3In pTr/l2nJjjiJvoKMZHrpXO2OSTN1uOY0pi+3oT7MpkLMzngKKlIZeJDAWcK4vJ8aMOKr PJUEiXWUElJcCc86/3oFtgaTGc/3AVlkc8YHqsaiNoZ5FzoyDvlmgIZ/XulHGnd3d4+Y AwTlplhQX2Xc+nz2TgeHmPn6frx5SdDi2A3Z7FdmZpzDLPjW/mq+e2MjTH2R5Z7OqvLu +yeg== X-Gm-Message-State: AOJu0YxnhcIAJEhezuWjpNr1TsVNIIwpih8aLMcVk8DPNZbgJfo7ZSNG oQG6uD9DnSLWfeYo0wsuBg7i03Xw3ShkLeD0bXNgTwlAF3PtV6cWQGK9OQGj9tpsITUOkyDi5JP DjK01N9lllCX3KUj2JPYVH1D5 X-Received: by 2002:a17:907:7886:b0:9ae:3a68:93e8 with SMTP id ku6-20020a170907788600b009ae3a6893e8mr1305775ejc.14.1695906111917; Thu, 28 Sep 2023 06:01:51 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEz3pbGNaGsGXLxS4Ox+9nimNMZDSlGuOBBQFpgwBh7j/cbtDjr7ZFe8TndKXVmt+ywY7dOTA== X-Received: by 2002:a17:907:7886:b0:9ae:3a68:93e8 with SMTP id ku6-20020a170907788600b009ae3a6893e8mr1305753ejc.14.1695906111560; Thu, 28 Sep 2023 06:01:51 -0700 (PDT) Received: from maszat.piliscsaba.szeredi.hu (94-21-53-31.pool.digikabel.hu. [94.21.53.31]) by smtp.gmail.com with ESMTPSA id v6-20020a170906380600b0099c53c4407dsm10784863ejc.78.2023.09.28.06.01.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 06:01:50 -0700 (PDT) From: Miklos Szeredi To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-man@vger.kernel.org, linux-security-module@vger.kernel.org, Karel Zak , Ian Kent , David Howells , Linus Torvalds , Al Viro , Christian Brauner , Amir Goldstein , Matthew House , Florian Weimer , Arnd Bergmann Subject: [PATCH v3 1/4] add unique mount ID Date: Thu, 28 Sep 2023 15:01:43 +0200 Message-ID: <20230928130147.564503-2-mszeredi@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230928130147.564503-1-mszeredi@redhat.com> References: <20230928130147.564503-1-mszeredi@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" If a mount is released then its mnt_id can immediately be reused. This is bad news for user interfaces that want to uniquely identify a mount. Implementing a unique mount ID is trivial (use a 64bit counter). Unfortunately userspace assumes 32bit size and would overflow after the counter reaches 2^32. Introduce a new 64bit ID alongside the old one. Initialize the counter to 2^32, this guarantees that the old and new IDs are never mixed up. Signed-off-by: Miklos Szeredi --- fs/mount.h | 3 ++- fs/namespace.c | 4 ++++ fs/stat.c | 9 +++++++-- include/uapi/linux/stat.h | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/fs/mount.h b/fs/mount.h index 130c07c2f8d2..a14f762b3f29 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -72,7 +72,8 @@ struct mount { struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks; __u32 mnt_fsnotify_mask; #endif - int mnt_id; /* mount identifier */ + int mnt_id; /* mount identifier, reused */ + u64 mnt_id_unique; /* mount ID unique until reboot */ int mnt_group_id; /* peer group identifier */ int mnt_expiry_mark; /* true if marked for expiry */ struct hlist_head mnt_pins; diff --git a/fs/namespace.c b/fs/namespace.c index e157efc54023..e02bc5f41c7b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -68,6 +68,9 @@ static u64 event; static DEFINE_IDA(mnt_id_ida); static DEFINE_IDA(mnt_group_ida); =20 +/* Don't allow confusion with old 32bit mount ID */ +static atomic64_t mnt_id_ctr =3D ATOMIC64_INIT(1ULL << 32); + static struct hlist_head *mount_hashtable __read_mostly; static struct hlist_head *mountpoint_hashtable __read_mostly; static struct kmem_cache *mnt_cache __read_mostly; @@ -131,6 +134,7 @@ static int mnt_alloc_id(struct mount *mnt) if (res < 0) return res; mnt->mnt_id =3D res; + mnt->mnt_id_unique =3D atomic64_inc_return(&mnt_id_ctr); return 0; } =20 diff --git a/fs/stat.c b/fs/stat.c index 6e60389d6a15..e61e0172e191 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -280,8 +280,13 @@ static int vfs_statx(int dfd, struct filename *filenam= e, int flags, =20 error =3D vfs_getattr(&path, stat, request_mask, flags); =20 - stat->mnt_id =3D real_mount(path.mnt)->mnt_id; - stat->result_mask |=3D STATX_MNT_ID; + if (request_mask & STATX_MNT_ID_UNIQUE) { + stat->mnt_id =3D real_mount(path.mnt)->mnt_id_unique; + stat->result_mask |=3D STATX_MNT_ID_UNIQUE; + } else { + stat->mnt_id =3D real_mount(path.mnt)->mnt_id; + stat->result_mask |=3D STATX_MNT_ID; + } =20 if (path.mnt->mnt_root =3D=3D path.dentry) stat->attributes |=3D STATX_ATTR_MOUNT_ROOT; diff --git a/include/uapi/linux/stat.h b/include/uapi/linux/stat.h index 7cab2c65d3d7..2f2ee82d5517 100644 --- a/include/uapi/linux/stat.h +++ b/include/uapi/linux/stat.h @@ -154,6 +154,7 @@ struct statx { #define STATX_BTIME 0x00000800U /* Want/got stx_btime */ #define STATX_MNT_ID 0x00001000U /* Got stx_mnt_id */ #define STATX_DIOALIGN 0x00002000U /* Want/got direct I/O alignment info = */ +#define STATX_MNT_ID_UNIQUE 0x00004000U /* Want/got extended stx_mount_id = */ =20 #define STATX__RESERVED 0x80000000U /* Reserved for future struct statx e= xpansion */ =20 --=20 2.41.0 From nobody Tue Dec 16 19:53:34 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A1E8E732CA for ; Thu, 28 Sep 2023 13:03:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232657AbjI1NDr (ORCPT ); Thu, 28 Sep 2023 09:03:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57158 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232635AbjI1NDc (ORCPT ); Thu, 28 Sep 2023 09:03:32 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EBB671AE for ; Thu, 28 Sep 2023 06:02:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695906120; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=mK7muDvbuwqZAV3QEAYNGQadrKd1oX00byk/Uab1QWg=; b=ZQBqEd9Rq7UGxh1aTUMi87m1cBJhXv8gjEYeRgEssbTG9b+4+csfqeNFmPXegxs0pswt4p oSsv0nF88YJwONC/PlN4GeZJk3NqNe811tNriWMjUN8YkBruXZWnNccJm4h2mPOS/xhstH 0ex2W3QspjJI+sE/AuWJuMe/Dx45nL8= Received: from mail-ej1-f72.google.com (mail-ej1-f72.google.com [209.85.218.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-287-e-lAOJ04Ml2PeObYHocLzg-1; Thu, 28 Sep 2023 09:01:56 -0400 X-MC-Unique: e-lAOJ04Ml2PeObYHocLzg-1 Received: by mail-ej1-f72.google.com with SMTP id a640c23a62f3a-99c8bbc902eso1134549966b.1 for ; Thu, 28 Sep 2023 06:01:55 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695906114; x=1696510914; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=mK7muDvbuwqZAV3QEAYNGQadrKd1oX00byk/Uab1QWg=; b=oQ5U/ANnE6cckF//tx5PjHJZ2BdgErX0ywhT5lXk68/YF8M/74j9z0sI9QfmMqTY+a vVJc3vH+lGws5FxHh4kFcSXl8kHQf4evE5n61zwvZLuu6iDQ/lp6q4sv2/AKGyze8F+s 73SqL2guIMFLKD1YCHzlg5D21ryhu+6bmc9U4Bh23/w0IaetN0leVgmZUamkgo+diIoi Z3azowanmLp0GdX5dqof+uivgXuEE6jke9KKwHO+Wh7tJ0ziuSPOrDOS4UZ6AAgbliyx DBGn3QfWbAg/0k56BleTTEC2F/H6vh65dRxDmr6Qc0+feWvRVFeZ5EMDf/ccktAngPFb /qfQ== X-Gm-Message-State: AOJu0YxDE1/rytH8Vpe+1Hcwov/GovdYBmNFU29NGByU14pwJXCiJG4D COsUvfRHTrKQWN4BkY/JSR1HW3zt/5khCF+ZNB2J4cIVwMy+oxp8jI5vdecRe9W7Jvyn2Pqz9hG iXdV3x4xCIXdKiQ1wA117otSj X-Received: by 2002:a17:906:319a:b0:9ae:7943:b0ff with SMTP id 26-20020a170906319a00b009ae7943b0ffmr1409860ejy.27.1695906114326; Thu, 28 Sep 2023 06:01:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFJjQiIjJVuDS3g32mRy//SH9vwKSEPCf6FjkZoTcZfx77rovjUrCRFJp0QcgV0Zb3CqzJbMg== X-Received: by 2002:a17:906:319a:b0:9ae:7943:b0ff with SMTP id 26-20020a170906319a00b009ae7943b0ffmr1409778ejy.27.1695906113300; Thu, 28 Sep 2023 06:01:53 -0700 (PDT) Received: from maszat.piliscsaba.szeredi.hu (94-21-53-31.pool.digikabel.hu. [94.21.53.31]) by smtp.gmail.com with ESMTPSA id v6-20020a170906380600b0099c53c4407dsm10784863ejc.78.2023.09.28.06.01.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 06:01:52 -0700 (PDT) From: Miklos Szeredi To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-man@vger.kernel.org, linux-security-module@vger.kernel.org, Karel Zak , Ian Kent , David Howells , Linus Torvalds , Al Viro , Christian Brauner , Amir Goldstein , Matthew House , Florian Weimer , Arnd Bergmann Subject: [PATCH v3 2/4] namespace: extract show_path() helper Date: Thu, 28 Sep 2023 15:01:44 +0200 Message-ID: <20230928130147.564503-3-mszeredi@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230928130147.564503-1-mszeredi@redhat.com> References: <20230928130147.564503-1-mszeredi@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" To be used by the statmount(2) syscall as well. Signed-off-by: Miklos Szeredi --- fs/internal.h | 2 ++ fs/namespace.c | 9 +++++++++ fs/proc_namespace.c | 10 +++------- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/fs/internal.h b/fs/internal.h index d64ae03998cc..0c4f4cf2ff5a 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -83,6 +83,8 @@ int path_mount(const char *dev_name, struct path *path, const char *type_page, unsigned long flags, void *data_page); int path_umount(struct path *path, int flags); =20 +int show_path(struct seq_file *m, struct dentry *root); + /* * fs_struct.c */ diff --git a/fs/namespace.c b/fs/namespace.c index e02bc5f41c7b..c3a41200fe70 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4678,6 +4678,15 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char = __user *, path, return err; } =20 +int show_path(struct seq_file *m, struct dentry *root) +{ + if (root->d_sb->s_op->show_path) + return root->d_sb->s_op->show_path(m, root); + + seq_dentry(m, root, " \t\n\\"); + return 0; +} + static void __init init_mount_tree(void) { struct vfsmount *mnt; diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 250eb5bf7b52..5638ad419f52 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c @@ -142,13 +142,9 @@ static int show_mountinfo(struct seq_file *m, struct v= fsmount *mnt) =20 seq_printf(m, "%i %i %u:%u ", r->mnt_id, r->mnt_parent->mnt_id, MAJOR(sb->s_dev), MINOR(sb->s_dev)); - if (sb->s_op->show_path) { - err =3D sb->s_op->show_path(m, mnt->mnt_root); - if (err) - goto out; - } else { - seq_dentry(m, mnt->mnt_root, " \t\n\\"); - } + err =3D show_path(m, mnt->mnt_root); + if (err) + goto out; seq_putc(m, ' '); =20 /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ --=20 2.41.0 From nobody Tue Dec 16 19:53:34 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52A16E732C8 for ; Thu, 28 Sep 2023 13:04:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232607AbjI1NEK (ORCPT ); Thu, 28 Sep 2023 09:04:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232605AbjI1NEI (ORCPT ); Thu, 28 Sep 2023 09:04:08 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEEA71BC for ; Thu, 28 Sep 2023 06:02:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695906140; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tVM4vTWFn4I5wl/Ns/ji6K+zCuq5d/aWhjyPG/bsZNM=; b=GOLTpU5CZsUpvNEOajg2PYIRTjuW3nVCXXmmYmcVaZlU7OVcgDmlNIs7gyOp+sq2ypcqa5 ida3r+MHVD6kNXKQNpbsF7YgtGFehvh0kBdOSnL0sE+YxxkkWqJEuxrVbGSBpdPSKdkicV zNVOSPZYJ/rU5Rl0aWi9fgrmH/OpW6w= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-437-FLL8-_ifPPmsjCK58mDvJg-1; Thu, 28 Sep 2023 09:02:18 -0400 X-MC-Unique: FLL8-_ifPPmsjCK58mDvJg-1 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-4053d832d51so105098585e9.0 for ; Thu, 28 Sep 2023 06:02:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695906137; x=1696510937; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tVM4vTWFn4I5wl/Ns/ji6K+zCuq5d/aWhjyPG/bsZNM=; b=Vht9g+mGt2hD6YPc/IdFmM/qc8PYdJJLwisQFJruagPJKvAepPF+rOwZMp0qUX/J74 GKe0Cy+ySbklyoq7A6GCsil8G3Xup2OcxEQf3eHJUzkCiJLb+iPY8r4aHbLo8smOPCdm N8tOQ7VP60Tb9FGjbimZj5AN1OS5i+8wXb1ckvAilpMFDfzSluyb2PM5pwH4BESw01B7 rNQS+7QPygxW4Id3mj2y+VZPpwbP5aBf41TcZEaBPqvekUjrIy0LVaiz5YjcwjZNL6dt xQ2mjouPyldV7pIlX50YUdh5Ag5ABUVKo6HTaKyieXWFxZ//JGS8a1L+bRRioxeM+qPn 4L5Q== X-Gm-Message-State: AOJu0YzdxuqzuBP7FYIv4eboqUI1X9a+wz7WO0Wi0YK1OXOc6xvTpdYz KMfeCUnCj8xKJon3zRJ9adHd2M6KgviC+VOhz5ZWjApouBrz5LENwWMf5kCKe5ScHpVns1kYzIo sA40I+YnmNkJf7iLyvVMV1TBs X-Received: by 2002:a17:906:29e:b0:9b0:552c:b36c with SMTP id 30-20020a170906029e00b009b0552cb36cmr1168253ejf.21.1695906116392; Thu, 28 Sep 2023 06:01:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFj0Vi09eIzprfVw38fz/8j9wZpbBsM0WwbMMqDlXyZ+kJqaPE8hFUAjvFPJpBmA1s3I9qgPA== X-Received: by 2002:a17:906:29e:b0:9b0:552c:b36c with SMTP id 30-20020a170906029e00b009b0552cb36cmr1168217ejf.21.1695906115881; Thu, 28 Sep 2023 06:01:55 -0700 (PDT) Received: from maszat.piliscsaba.szeredi.hu (94-21-53-31.pool.digikabel.hu. [94.21.53.31]) by smtp.gmail.com with ESMTPSA id v6-20020a170906380600b0099c53c4407dsm10784863ejc.78.2023.09.28.06.01.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 06:01:54 -0700 (PDT) From: Miklos Szeredi To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-man@vger.kernel.org, linux-security-module@vger.kernel.org, Karel Zak , Ian Kent , David Howells , Linus Torvalds , Al Viro , Christian Brauner , Amir Goldstein , Matthew House , Florian Weimer , Arnd Bergmann Subject: [PATCH v3 3/4] add statmount(2) syscall Date: Thu, 28 Sep 2023 15:01:45 +0200 Message-ID: <20230928130147.564503-4-mszeredi@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230928130147.564503-1-mszeredi@redhat.com> References: <20230928130147.564503-1-mszeredi@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add a way to query attributes of a single mount instead of having to parse the complete /proc/$PID/mountinfo, which might be huge. Lookup the mount the new 64bit mount ID. If a mount needs to be queried based on path, then statx(2) can be used to first query the mount ID belonging to the path. Design is based on a suggestion by Linus: "So I'd suggest something that is very much like "statfsat()", which gets a buffer and a length, and returns an extended "struct statfs" *AND* just a string description at the end." The interface closely mimics that of statx. Handle ASCII attributes by appending after the end of the structure (as per above suggestion). Pointers to strings are stored in u64 members to make the structure the same regardless of pointer size. Strings are nul terminated. Link: https://lore.kernel.org/all/CAHk-=3Dwh5YifP7hzKSbwJj94+DZ2czjrZsczy6G= BimiogZws=3Drg@mail.gmail.com/ Signed-off-by: Miklos Szeredi --- arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + fs/namespace.c | 283 +++++++++++++++++++++++++ fs/statfs.c | 1 + include/linux/syscalls.h | 5 + include/uapi/asm-generic/unistd.h | 5 +- include/uapi/linux/mount.h | 56 +++++ 7 files changed, 351 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index 2d0b1bd866ea..317b1320ad18 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -457,3 +457,4 @@ 450 i386 set_mempolicy_home_node sys_set_mempolicy_home_node 451 i386 cachestat sys_cachestat 452 i386 fchmodat2 sys_fchmodat2 +454 i386 statmount sys_statmount diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index 1d6eee30eceb..7312c440978f 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -375,6 +375,7 @@ 451 common cachestat sys_cachestat 452 common fchmodat2 sys_fchmodat2 453 64 map_shadow_stack sys_map_shadow_stack +454 common statmount sys_statmount =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/fs/namespace.c b/fs/namespace.c index c3a41200fe70..3326ba2b2810 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4687,6 +4687,289 @@ int show_path(struct seq_file *m, struct dentry *ro= ot) return 0; } =20 +static struct vfsmount *lookup_mnt_in_ns(u64 id, struct mnt_namespace *ns) +{ + struct mount *mnt; + struct vfsmount *res =3D NULL; + + lock_ns_list(ns); + list_for_each_entry(mnt, &ns->list, mnt_list) { + if (!mnt_is_cursor(mnt) && id =3D=3D mnt->mnt_id_unique) { + res =3D &mnt->mnt; + break; + } + } + unlock_ns_list(ns); + return res; +} + +struct stmt_state { + struct statmnt __user *const buf; + size_t const bufsize; + struct vfsmount *const mnt; + u64 const mask; + struct seq_file seq; + struct path root; + struct statmnt sm; + size_t pos; + int err; +}; + +typedef int (*stmt_func_t)(struct stmt_state *); + +static int stmt_string_seq(struct stmt_state *s, stmt_func_t func) +{ + size_t rem =3D s->bufsize - s->pos - sizeof(s->sm); + struct seq_file *seq =3D &s->seq; + int ret; + + seq->count =3D 0; + seq->size =3D min(seq->size, rem); + seq->buf =3D kvmalloc(seq->size, GFP_KERNEL_ACCOUNT); + if (!seq->buf) + return -ENOMEM; + + ret =3D func(s); + if (ret) + return ret; + + if (seq_has_overflowed(seq)) { + if (seq->size =3D=3D rem) + return -EOVERFLOW; + seq->size *=3D 2; + if (seq->size > MAX_RW_COUNT) + return -ENOMEM; + kvfree(seq->buf); + return 0; + } + + /* Done */ + return 1; +} + +static void stmt_string(struct stmt_state *s, u64 mask, stmt_func_t func, + u32 *str) +{ + int ret =3D s->pos + sizeof(s->sm) >=3D s->bufsize ? -EOVERFLOW : 0; + struct statmnt *sm =3D &s->sm; + struct seq_file *seq =3D &s->seq; + + if (s->err || !(s->mask & mask)) + return; + + seq->size =3D PAGE_SIZE; + while (!ret) + ret =3D stmt_string_seq(s, func); + + if (ret < 0) { + s->err =3D ret; + } else { + seq->buf[seq->count++] =3D '\0'; + if (copy_to_user(s->buf->str + s->pos, seq->buf, seq->count)) { + s->err =3D -EFAULT; + } else { + *str =3D s->pos; + s->pos +=3D seq->count; + } + } + kvfree(seq->buf); + sm->mask |=3D mask; +} + +static void stmt_numeric(struct stmt_state *s, u64 mask, stmt_func_t func) +{ + if (s->err || !(s->mask & mask)) + return; + + s->err =3D func(s); + s->sm.mask |=3D mask; +} + +static u64 mnt_to_attr_flags(struct vfsmount *mnt) +{ + unsigned int mnt_flags =3D READ_ONCE(mnt->mnt_flags); + u64 attr_flags =3D 0; + + if (mnt_flags & MNT_READONLY) + attr_flags |=3D MOUNT_ATTR_RDONLY; + if (mnt_flags & MNT_NOSUID) + attr_flags |=3D MOUNT_ATTR_NOSUID; + if (mnt_flags & MNT_NODEV) + attr_flags |=3D MOUNT_ATTR_NODEV; + if (mnt_flags & MNT_NOEXEC) + attr_flags |=3D MOUNT_ATTR_NOEXEC; + if (mnt_flags & MNT_NODIRATIME) + attr_flags |=3D MOUNT_ATTR_NODIRATIME; + if (mnt_flags & MNT_NOSYMFOLLOW) + attr_flags |=3D MOUNT_ATTR_NOSYMFOLLOW; + + if (mnt_flags & MNT_NOATIME) + attr_flags |=3D MOUNT_ATTR_NOATIME; + else if (mnt_flags & MNT_RELATIME) + attr_flags |=3D MOUNT_ATTR_RELATIME; + else + attr_flags |=3D MOUNT_ATTR_STRICTATIME; + + if (is_idmapped_mnt(mnt)) + attr_flags |=3D MOUNT_ATTR_IDMAP; + + return attr_flags; +} + +static u64 mnt_to_propagation_flags(struct mount *m) +{ + u64 propagation =3D 0; + + if (IS_MNT_SHARED(m)) + propagation |=3D MS_SHARED; + if (IS_MNT_SLAVE(m)) + propagation |=3D MS_SLAVE; + if (IS_MNT_UNBINDABLE(m)) + propagation |=3D MS_UNBINDABLE; + if (!propagation) + propagation |=3D MS_PRIVATE; + + return propagation; +} + +static int stmt_sb_basic(struct stmt_state *s) +{ + struct super_block *sb =3D s->mnt->mnt_sb; + + s->sm.sb_dev_major =3D MAJOR(sb->s_dev); + s->sm.sb_dev_minor =3D MINOR(sb->s_dev); + s->sm.sb_magic =3D sb->s_magic; + s->sm.sb_flags =3D sb->s_flags & (SB_RDONLY|SB_SYNCHRONOUS|SB_DIRSYNC|SB_= LAZYTIME); + + return 0; +} + +static int stmt_mnt_basic(struct stmt_state *s) +{ + struct mount *m =3D real_mount(s->mnt); + + s->sm.mnt_id =3D m->mnt_id_unique; + s->sm.mnt_parent_id =3D m->mnt_parent->mnt_id_unique; + s->sm.mnt_id_old =3D m->mnt_id; + s->sm.mnt_parent_id_old =3D m->mnt_parent->mnt_id; + s->sm.mnt_attr =3D mnt_to_attr_flags(&m->mnt); + s->sm.mnt_propagation =3D mnt_to_propagation_flags(m); + s->sm.mnt_peer_group =3D IS_MNT_SHARED(m) ? m->mnt_group_id : 0; + s->sm.mnt_master =3D IS_MNT_SLAVE(m) ? m->mnt_master->mnt_group_id : 0; + + return 0; +} + +static int stmt_propagate_from(struct stmt_state *s) +{ + struct mount *m =3D real_mount(s->mnt); + + if (!IS_MNT_SLAVE(m)) + return 0; + + s->sm.propagate_from =3D get_dominating_id(m, ¤t->fs->root); + + return 0; +} + +static int stmt_mnt_root(struct stmt_state *s) +{ + struct seq_file *seq =3D &s->seq; + int err =3D show_path(seq, s->mnt->mnt_root); + + if (!err && !seq_has_overflowed(seq)) { + seq->buf[seq->count] =3D '\0'; + seq->count =3D string_unescape_inplace(seq->buf, UNESCAPE_OCTAL); + } + return err; +} + +static int stmt_mnt_point(struct stmt_state *s) +{ + struct vfsmount *mnt =3D s->mnt; + struct path mnt_path =3D { .dentry =3D mnt->mnt_root, .mnt =3D mnt }; + int err =3D seq_path_root(&s->seq, &mnt_path, &s->root, ""); + + return err =3D=3D SEQ_SKIP ? 0 : err; +} + +static int stmt_fs_type(struct stmt_state *s) +{ + struct seq_file *seq =3D &s->seq; + struct super_block *sb =3D s->mnt->mnt_sb; + + seq_puts(seq, sb->s_type->name); + return 0; +} + +static int do_statmount(struct stmt_state *s) +{ + struct statmnt *sm =3D &s->sm; + struct mount *m =3D real_mount(s->mnt); + size_t copysize =3D min_t(size_t, s->bufsize, sizeof(*sm)); + int err; + + err =3D security_sb_statfs(s->mnt->mnt_root); + if (err) + return err; + + if (!capable(CAP_SYS_ADMIN) && + !is_path_reachable(m, m->mnt.mnt_root, &s->root)) + return -EPERM; + + stmt_numeric(s, STMT_SB_BASIC, stmt_sb_basic); + stmt_numeric(s, STMT_MNT_BASIC, stmt_mnt_basic); + stmt_numeric(s, STMT_PROPAGATE_FROM, stmt_propagate_from); + stmt_string(s, STMT_FS_TYPE, stmt_fs_type, &sm->fs_type); + stmt_string(s, STMT_MNT_ROOT, stmt_mnt_root, &sm->mnt_root); + stmt_string(s, STMT_MNT_POINT, stmt_mnt_point, &sm->mnt_point); + + if (s->err) + return s->err; + + /* Return the number of bytes copied to the buffer */ + sm->size =3D copysize + s->pos; + + if (copy_to_user(s->buf, sm, copysize)) + return -EFAULT; + + return 0; +} + +SYSCALL_DEFINE4(statmount, const struct __mount_arg __user *, req, + struct statmnt __user *, buf, size_t, bufsize, + unsigned int, flags) +{ + struct vfsmount *mnt; + struct __mount_arg kreq; + int ret; + + if (flags) + return -EINVAL; + + if (copy_from_user(&kreq, req, sizeof(kreq))) + return -EFAULT; + + down_read(&namespace_sem); + mnt =3D lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns); + ret =3D -ENOENT; + if (mnt) { + struct stmt_state s =3D { + .mask =3D kreq.request_mask, + .buf =3D buf, + .bufsize =3D bufsize, + .mnt =3D mnt, + }; + + get_fs_root(current->fs, &s.root); + ret =3D do_statmount(&s); + path_put(&s.root); + } + up_read(&namespace_sem); + + return ret; +} + static void __init init_mount_tree(void) { struct vfsmount *mnt; diff --git a/fs/statfs.c b/fs/statfs.c index 96d1c3edf289..cc774c2e2c9a 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "internal.h" =20 static int flags_by_mnt(int mnt_flags) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 22bc6bc147f8..ba371024d902 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -74,6 +74,8 @@ struct landlock_ruleset_attr; enum landlock_rule_type; struct cachestat_range; struct cachestat; +struct statmnt; +struct __mount_arg; =20 #include #include @@ -408,6 +410,9 @@ asmlinkage long sys_statfs64(const char __user *path, s= ize_t sz, asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user *buf); asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf); +asmlinkage long sys_statmount(const struct __mount_arg __user *req, + struct statmnt __user *buf, size_t bufsize, + unsigned int flags); asmlinkage long sys_truncate(const char __user *path, long length); asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); #if BITS_PER_LONG =3D=3D 32 diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index abe087c53b4b..8f034e934a2e 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -823,8 +823,11 @@ __SYSCALL(__NR_cachestat, sys_cachestat) #define __NR_fchmodat2 452 __SYSCALL(__NR_fchmodat2, sys_fchmodat2) =20 +#define __NR_statmount 454 +__SYSCALL(__NR_statmount, sys_statmount) + #undef __NR_syscalls -#define __NR_syscalls 453 +#define __NR_syscalls 455 =20 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index bb242fdcfe6b..d2c988ab526b 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -138,4 +138,60 @@ struct mount_attr { /* List of all mount_attr versions. */ #define MOUNT_ATTR_SIZE_VER0 32 /* sizeof first published struct */ =20 + +/* + * Structure for getting mount/superblock/filesystem info with statmount(2= ). + * + * The interface is similar to statx(2): individual fields or groups can be + * selected with the @mask argument of statmount(). Kernel will set the @= mask + * field according to the supported fields. + * + * If string fields are selected, then the caller needs to pass a buffer t= hat + * has space after the fixed part of the structure. Nul terminated string= s are + * copied there and offsets relative to @str are stored in the relevant fi= elds. + * If the buffer is too small, then EOVERFLOW is returned. The actually u= sed + * size is returned in @size. + */ +struct statmnt { + __u32 size; /* Total size, including strings */ + __u32 __spare1; + __u64 mask; /* What results were written */ + __u32 sb_dev_major; /* Device ID */ + __u32 sb_dev_minor; + __u64 sb_magic; /* ..._SUPER_MAGIC */ + __u32 sb_flags; /* MS_{RDONLY,SYNCHRONOUS,DIRSYNC,LAZYTIME} */ + __u32 fs_type; /* [str] Filesystem type */ + __u64 mnt_id; /* Unique ID of mount */ + __u64 mnt_parent_id; /* Unique ID of parent (for root =3D=3D mnt_id) */ + __u32 mnt_id_old; /* Reused IDs used in proc/.../mountinfo */ + __u32 mnt_parent_id_old; + __u64 mnt_attr; /* MOUNT_ATTR_... */ + __u64 mnt_propagation; /* MS_{SHARED,SLAVE,PRIVATE,UNBINDABLE} */ + __u64 mnt_peer_group; /* ID of shared peer group */ + __u64 mnt_master; /* Mount receives propagation from this ID */ + __u64 propagate_from; /* Propagation from in current namespace */ + __u32 mnt_root; /* [str] Root of mount relative to root of fs */ + __u32 mnt_point; /* [str] Mountpoint relative to current root */ + __u64 __spare2[50]; + char str[]; /* Variable size part containing strings */ +}; + +/* + * To be used on the kernel ABI only for passing 64bit arguments to statmo= unt(2) + */ +struct __mount_arg { + __u64 mnt_id; + __u64 request_mask; +}; + +/* + * @mask bits for statmount(2) + */ +#define STMT_SB_BASIC 0x00000001U /* Want/got sb_... */ +#define STMT_MNT_BASIC 0x00000002U /* Want/got mnt_... */ +#define STMT_PROPAGATE_FROM 0x00000004U /* Want/got propagate_from */ +#define STMT_MNT_ROOT 0x00000008U /* Want/got mnt_root */ +#define STMT_MNT_POINT 0x00000010U /* Want/got mnt_point */ +#define STMT_FS_TYPE 0x00000020U /* Want/got fs_type */ + #endif /* _UAPI_LINUX_MOUNT_H */ --=20 2.41.0 From nobody Tue Dec 16 19:53:34 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6D033E732CF for ; Thu, 28 Sep 2023 13:04:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232686AbjI1NEV (ORCPT ); Thu, 28 Sep 2023 09:04:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42010 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232633AbjI1NEL (ORCPT ); Thu, 28 Sep 2023 09:04:11 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32D771B1 for ; Thu, 28 Sep 2023 06:02:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1695906121; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jtqyeIwabSbVK1kFbfunjeS3nfTCDCzse/xUKnJCfCQ=; b=ezenC/8OZ+lsq/ViwuRX+jCxl4zhEvRws9PyCDnLnQEOCGqu09YLrXp7ONzWvph6GHGfU9 FEox1SDIWUtNgWW/6N8yJh9LyO1PHI5Pdgjed/6amxaI691B3sYb1TxR+RfmEFXBBmrV8W uKddNE0addcfRle9XnCFPizsReISW/o= Received: from mail-ej1-f70.google.com (mail-ej1-f70.google.com [209.85.218.70]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-656-ebA6uAr8NgeEWiDFTqhbtg-1; Thu, 28 Sep 2023 09:01:59 -0400 X-MC-Unique: ebA6uAr8NgeEWiDFTqhbtg-1 Received: by mail-ej1-f70.google.com with SMTP id a640c23a62f3a-9ae686dafedso1100637766b.3 for ; Thu, 28 Sep 2023 06:01:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695906118; x=1696510918; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jtqyeIwabSbVK1kFbfunjeS3nfTCDCzse/xUKnJCfCQ=; b=beS8bbYkH1gHCfUSIAr6YKYhCptMTI3OuEQufHVRD341IKpdQ0OB/2FAbi6UHsppvl icZO07qV2r4xAouectHxSGeOHkbiedbVmNwxZR0vcH02BQFtWYWRDYpWb/anUpGlP7Bp pS9AC6A76AORAwIyKq/moc3gpVql+ix+XDApd28OmUOZOErpLkdpFBnIIsDGys1YmJO1 Dr42WSKo5Te0ze/CLtIgxpitCyd67CicM09WKO8BvMHts83OzZIx9Bz3IbBh7ZIHh+8k pZCVIrGOOozeUVmPMWoEs1hOUZQ4sy8KBzlie2TMpjQQCdjDEKvTm4TL8y2HpCz9gJX1 H7QA== X-Gm-Message-State: AOJu0YxWKI2IAriYg30Pkpbj8u5V9acdEISCOcVFxp4qwSlQOi8s4rrE a1KUlA5mX1avc548TWnTNESwxkMM8CWc8qyspWLpYkkM7yjdUrojYuZ2GIimUlBmAG//EfzH+6s 9gOaD6u1KkLu9VvkZa2TWy8WH X-Received: by 2002:a17:906:108f:b0:9ae:5202:e611 with SMTP id u15-20020a170906108f00b009ae5202e611mr1106326eju.14.1695906118324; Thu, 28 Sep 2023 06:01:58 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFL2k7VUiwqQ4h1L34lrXi/2ULqRDnR0xeWeBBIS648cMooHMQ+75ulk8bGyXx/u2Ycxg8vZw== X-Received: by 2002:a17:906:108f:b0:9ae:5202:e611 with SMTP id u15-20020a170906108f00b009ae5202e611mr1106306eju.14.1695906118057; Thu, 28 Sep 2023 06:01:58 -0700 (PDT) Received: from maszat.piliscsaba.szeredi.hu (94-21-53-31.pool.digikabel.hu. [94.21.53.31]) by smtp.gmail.com with ESMTPSA id v6-20020a170906380600b0099c53c4407dsm10784863ejc.78.2023.09.28.06.01.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 06:01:56 -0700 (PDT) From: Miklos Szeredi To: linux-fsdevel@vger.kernel.org Cc: linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-man@vger.kernel.org, linux-security-module@vger.kernel.org, Karel Zak , Ian Kent , David Howells , Linus Torvalds , Al Viro , Christian Brauner , Amir Goldstein , Matthew House , Florian Weimer , Arnd Bergmann Subject: [PATCH v3 4/4] add listmount(2) syscall Date: Thu, 28 Sep 2023 15:01:46 +0200 Message-ID: <20230928130147.564503-5-mszeredi@redhat.com> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20230928130147.564503-1-mszeredi@redhat.com> References: <20230928130147.564503-1-mszeredi@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Add way to query the children of a particular mount. This is a more flexible way to iterate the mount tree than having to parse the complete /proc/self/mountinfo. Lookup the mount by the new 64bit mount ID. If a mount needs to be queried based on path, then statx(2) can be used to first query the mount ID belonging to the path. Return an array of new (64bit) mount ID's. Without privileges only mounts are listed which are reachable from the task's root. Signed-off-by: Miklos Szeredi --- arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + fs/namespace.c | 69 ++++++++++++++++++++++++++ include/linux/syscalls.h | 3 ++ include/uapi/asm-generic/unistd.h | 5 +- include/uapi/linux/mount.h | 3 ++ 6 files changed, 81 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index 317b1320ad18..65e0185b47a9 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -458,3 +458,4 @@ 451 i386 cachestat sys_cachestat 452 i386 fchmodat2 sys_fchmodat2 454 i386 statmount sys_statmount +455 i386 listmount sys_listmount diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index 7312c440978f..a1b3ce7d22cc 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -376,6 +376,7 @@ 452 common fchmodat2 sys_fchmodat2 453 64 map_shadow_stack sys_map_shadow_stack 454 common statmount sys_statmount +455 common listmount sys_listmount =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/fs/namespace.c b/fs/namespace.c index 3326ba2b2810..050e2d2af110 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4970,6 +4970,75 @@ SYSCALL_DEFINE4(statmount, const struct __mount_arg = __user *, req, return ret; } =20 +static long do_listmount(struct vfsmount *mnt, u64 __user *buf, size_t buf= size, + const struct path *root, unsigned int flags) +{ + struct mount *r, *m =3D real_mount(mnt); + struct path rootmnt =3D { + .mnt =3D root->mnt, + .dentry =3D root->mnt->mnt_root + }; + long ctr =3D 0; + bool reachable_only =3D true; + int err; + + err =3D security_sb_statfs(mnt->mnt_root); + if (err) + return err; + + if (flags & LISTMOUNT_UNREACHABLE) { + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + reachable_only =3D false; + } + + if (reachable_only && !is_path_reachable(m, mnt->mnt_root, &rootmnt)) + return capable(CAP_SYS_ADMIN) ? 0 : -EPERM; + + list_for_each_entry(r, &m->mnt_mounts, mnt_child) { + if (reachable_only && + !is_path_reachable(r, r->mnt.mnt_root, root)) + continue; + + if (ctr >=3D bufsize) + return -EOVERFLOW; + if (put_user(r->mnt_id_unique, buf + ctr)) + return -EFAULT; + ctr++; + if (ctr < 0) + return -ERANGE; + } + return ctr; +} + +SYSCALL_DEFINE4(listmount, const struct __mount_arg __user *, req, + u64 __user *, buf, size_t, bufsize, unsigned int, flags) +{ + struct __mount_arg kreq; + struct vfsmount *mnt; + struct path root; + long err; + + if (flags & ~LISTMOUNT_UNREACHABLE) + return -EINVAL; + + if (copy_from_user(&kreq, req, sizeof(kreq))) + return -EFAULT; + + down_read(&namespace_sem); + mnt =3D lookup_mnt_in_ns(kreq.mnt_id, current->nsproxy->mnt_ns); + err =3D -ENOENT; + if (mnt) { + get_fs_root(current->fs, &root); + err =3D do_listmount(mnt, buf, bufsize, &root, flags); + path_put(&root); + } + up_read(&namespace_sem); + + return err; +} + + static void __init init_mount_tree(void) { struct vfsmount *mnt; diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index ba371024d902..38f3da7e04d1 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -413,6 +413,9 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t s= z, asmlinkage long sys_statmount(const struct __mount_arg __user *req, struct statmnt __user *buf, size_t bufsize, unsigned int flags); +asmlinkage long sys_listmount(const struct __mount_arg __user *req, + u64 __user *buf, size_t bufsize, + unsigned int flags); asmlinkage long sys_truncate(const char __user *path, long length); asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); #if BITS_PER_LONG =3D=3D 32 diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index 8f034e934a2e..8df6a747e21a 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -826,8 +826,11 @@ __SYSCALL(__NR_fchmodat2, sys_fchmodat2) #define __NR_statmount 454 __SYSCALL(__NR_statmount, sys_statmount) =20 +#define __NR_listmount 455 +__SYSCALL(__NR_listmount, sys_listmount) + #undef __NR_syscalls -#define __NR_syscalls 455 +#define __NR_syscalls 456 =20 /* * 32 bit systems traditionally used different diff --git a/include/uapi/linux/mount.h b/include/uapi/linux/mount.h index d2c988ab526b..7aa9916659d2 100644 --- a/include/uapi/linux/mount.h +++ b/include/uapi/linux/mount.h @@ -194,4 +194,7 @@ struct __mount_arg { #define STMT_MNT_POINT 0x00000010U /* Want/got mnt_point */ #define STMT_FS_TYPE 0x00000020U /* Want/got fs_type */ =20 +/* listmount(2) flags */ +#define LISTMOUNT_UNREACHABLE 0x01 /* List unreachable mounts too */ + #endif /* _UAPI_LINUX_MOUNT_H */ --=20 2.41.0