From nobody Sat Feb 7 06:20:32 2026 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 2E549271447; Wed, 22 Oct 2025 16:06:10 +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=1761149171; cv=none; b=cKoh8dputzKqaAHyP83MSinX6ZdapA0XQwueGN4S73uYbNwulMnYOL6AR8+A+52UX9jzBRvHVEiYPvET5sFzXSQ+hvS1aK7WJbl04+r+ScRqi9SXlxGFxxK9v/lB937uaeLyBjMPdh7eLIh0RnFQm4vpb+endnBR2Av2Yw8Zph0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149171; c=relaxed/simple; bh=wpu8fA7qXxdZSYnV2Wt9hfd/qe1FdRoJcNk3AI3VvA4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SxEO2f6J4N7ngG6CdsDufghRcVwRAykKoihgqp6zqsRVGB/3KHSqn71+nuMBeBMmnIblZxtAJP4ly8zneduPh+cRACqCyIYVqcG2uCm0cDQKamlNj5PQ4Ej0eYTWvhMkRJlab3Rij8u2lvg8lr3Xpi1WaTf0os5FTHh0MAbP+44= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=btjigmbW; 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="btjigmbW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E4333C4CEF7; Wed, 22 Oct 2025 16:06:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149170; bh=wpu8fA7qXxdZSYnV2Wt9hfd/qe1FdRoJcNk3AI3VvA4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=btjigmbWbbwN/3bEvge/X8OntVZSvuCtouD/CcLCCA5f4WL+TPqM1epg2qMtdO0+j wExyt/vuybMhyQKkgdowgY6goi7WtBSN0BZtw+ih0ARBRXAyJ69Ec5ZKMtadfDh0FX c8BCngOpmPutY3nQCmJvk7SLIGvHOGZGcCR7ITUoEnHbhkNyGV52XDddnIq7I1+OIG 8s/jOCpGrCmJcCJrNDDXgFVIx94635duYQtibiKeX8Fql+Cg0MI84RduX3PmJEjZy1 bBKgycneTjV0dYFOoMCnUz8E84uYectJXpzN3srHBeXssDYk031Dz8s6uECkHlqYjf ylINKMnwXB8uA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:39 +0200 Subject: [PATCH v2 01/63] libfs: allow to specify s_d_flags Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-1-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1073; i=brauner@kernel.org; h=from:subject:message-id; bh=wpu8fA7qXxdZSYnV2Wt9hfd/qe1FdRoJcNk3AI3VvA4=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhy7t4Ds/mVCZO+zND//TxarpLt5DMPsUONswKn7 hZlX9vs3VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjARhVZGhpV3F29za+zhfN5x 9Dov7/Yox+jqW2klgcnlrxZ87vv75hzDP+37zP2Cezj1uyO0tfbv+7LawWvlzJ8Tlnblc8j5LA7 fww4A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Make it possible for pseudo filesystems to specify default dentry flags. Signed-off-by: Christian Brauner --- fs/libfs.c | 1 + include/linux/pseudo_fs.h | 1 + 2 files changed, 2 insertions(+) diff --git a/fs/libfs.c b/fs/libfs.c index ce8c496a6940..4bb4d8a313e7 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -680,6 +680,7 @@ static int pseudo_fs_fill_super(struct super_block *s, = struct fs_context *fc) s->s_export_op =3D ctx->eops; s->s_xattr =3D ctx->xattr; s->s_time_gran =3D 1; + s->s_d_flags |=3D ctx->s_d_flags; root =3D new_inode(s); if (!root) return -ENOMEM; diff --git a/include/linux/pseudo_fs.h b/include/linux/pseudo_fs.h index 2503f7625d65..a651e60d9410 100644 --- a/include/linux/pseudo_fs.h +++ b/include/linux/pseudo_fs.h @@ -9,6 +9,7 @@ struct pseudo_fs_context { const struct xattr_handler * const *xattr; const struct dentry_operations *dops; unsigned long magic; + unsigned int s_d_flags; }; =20 struct pseudo_fs_context *init_pseudo(struct fs_context *fc, --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 7985B270551; Wed, 22 Oct 2025 16:06:15 +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=1761149176; cv=none; b=Npwxyi5ImD7R5+C2KZ9CziAom1mdRABz5KwmjtY4FvE7YBoNDlFYemf1qphbiGKw7yNFbUHTfqVJn71nKCvifvb1gn/hbgTk0A/RllfHGf/QRMO83Trjp/NpeGBg0NtHXrF8MeE03bXstG5qpJHV2dPDspy490Y28sABtaptErs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149176; c=relaxed/simple; bh=jSqJBpD/6utq5kB6r0uVAxUcKbpMKsXXqLyZPGG0ICk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qx0+6lGDd9ovnfjZu/uhEwNMixpy/F8L6NynM2C1Iw+fmEx5yTVDbFUJaHEPlORMbOAV8F4IeA0uPVaoNWrQ8jit/LLilW3j3KZtH3hcNTg6wbL73Tyanmb/OAb8SeoQ9UKiF8zJ7PRTDiAz3SfuFBcuzUiwAVmSlM+BMqeXvSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ry4UA73k; 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="ry4UA73k" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F2FBC4CEE7; Wed, 22 Oct 2025 16:06:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149175; bh=jSqJBpD/6utq5kB6r0uVAxUcKbpMKsXXqLyZPGG0ICk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ry4UA73kSbdXLE+Gf3T5AwqY/95tXQMz1bsUuxLLsSzE8AKeVZYI9+ZnBolHlxOG4 2pstUVcm9PhrDImoQrhTz/MjefbJnaINdtLXBJmKNewZSv4x1+8zxPYacy+fMFasiE dXH8F8rgSBEhrgmY4mQvoZIA80KHTmh6nDSvC6uOsWaL3TDLz6DsRY5ZN6KQKKAUEO dMmvLX7gL/U5U1LVN5o5GaT12pMA2hyhkaP9sossuRvwrwg01d5iA7vbK+1zSVKwbt pvjEZLv95Syu2CgiQljIttmcD2zJLeoFzX52NczofEwRv5odcwDAVchwiIhg/FS2SH ssXYBtIesnIGg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:40 +0200 Subject: [PATCH v2 02/63] nsfs: use inode_just_drop() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-2-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=930; i=brauner@kernel.org; h=from:subject:message-id; bh=jSqJBpD/6utq5kB6r0uVAxUcKbpMKsXXqLyZPGG0ICk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhy/PN2txU3Lkk/LgneGnNT5fbLiv/br81WkP1ew 5EWHqV6o6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAifv6MDE8UGn305JkE81Yo szW3ZfXka8luMamt1FtyTunw/GV/TjD8T45Ylr+lbplOTpfsvljXItUDXfKz3te9UJ4xbZL8jhI jdgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Currently nsfs uses the default inode_generic_drop() fallback which drops the inode when it's unlinked or when it's unhashed. Since nsfs never hashes inodes that always amounts to dropping the inode. But that's just annoying to have to reason through every time we look at this code. Switch to inode_just_drop() which always drops the inode explicitly. This also aligns the behavior with pidfs which does the same. Signed-off-by: Christian Brauner --- fs/nsfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nsfs.c b/fs/nsfs.c index 648dc59bef7f..4e77eba0c8fc 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -408,6 +408,7 @@ static const struct super_operations nsfs_ops =3D { .statfs =3D simple_statfs, .evict_inode =3D nsfs_evict, .show_path =3D nsfs_show_path, + .drop_inode =3D inode_just_drop, }; =20 static int nsfs_init_inode(struct inode *inode, void *data) --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 ACE05270EC3; Wed, 22 Oct 2025 16:06:21 +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=1761149182; cv=none; b=i73Fkcdme4WoJL3FYwyFwwruiT9OA/cih35GzUKy38tMVg8paXOiwtVVvR1iMNMSgoOOIz19ISvzYi6CpMYuSQ1W+bVsbuQJeaBB+nfvR8w/DcFrouxuGy5+EyUWsr7U/jpNCreiZffAZpaZf5p8SzMDeJstDCZx6z1ulStoqGM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149182; c=relaxed/simple; bh=VMCLQ5Neu+JsCPfFhnjTC4pvJzkr6RMBoSrPUgoYfJM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZBsr5rLcfr4zXTu4aZMvdx1NiAI1J4jiks6ZB6Lf7o0es7PdSwal2J2tsRYqbnRXLcKTTTQN2fbVBVhbmiCd8YD8bRXVsZgiEoJ2ga9IoKKXxJizeTljQ7oySafTOKXV2hy/PgTJvrA22bvw/jCvsB6qHeYUBfuDtVDTOH4K2i8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NR+WrNWo; 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="NR+WrNWo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63054C4CEF7; Wed, 22 Oct 2025 16:06:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149181; bh=VMCLQ5Neu+JsCPfFhnjTC4pvJzkr6RMBoSrPUgoYfJM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NR+WrNWooGSxhYhX+4Y4dXMJyX2ApwVxDL2xaZIilFKfV+ePSZOnMgYgzU5YeA3nL uCkhC7+xpm6Qudw5gcuTLDX9HZOP/K90y0O4TqfB0HWOOGjokjyhIRSXXw+hl0cGQL KaMIdd7hHbcHCw4XmzCJgQdpltPsoIclt02opbccCF0jkiG7z2DQ8LVGlkgQ4dJhnn 2oQ0PgjcSslF8M33VQ5VtsfqpQQh4UASeSdqb2oWvoCD+I5qjD/lGkyIBVKY7V/K3O SZ8DvCgZobrbB3djOt9GWbjOhv3wOt4TTj8MA6StlbJUXYRv0Vobi3Sy0MLxlynLZ8 SZIyjsxCXvogw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:41 +0200 Subject: [PATCH v2 03/63] nsfs: raise DCACHE_DONTCACHE explicitly Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-3-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=840; i=brauner@kernel.org; h=from:subject:message-id; bh=VMCLQ5Neu+JsCPfFhnjTC4pvJzkr6RMBoSrPUgoYfJM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgSdo/x+VKp3F7T7cFPSlOfdtYdeVsf5nwgrfHh5 mx+9ZrejlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlcP8bwVyrdiaOr3675i9Hx u72aRxma3URUJdJfbuZf9nWj2U7FrQz/k27UW3OVLXbKWjzrufaF5btltonsenNto4DYmdUspSn z+AA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 While nsfs dentries are never hashed and thus retain_dentry() will never consider them for placing them on the LRU it isn't great to always have to go and remember that. Raise DCACHE_DONTCACHE explicitly as a visual marker that dentries aren't kept but freed immediately instead. Signed-off-by: Christian Brauner --- fs/nsfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nsfs.c b/fs/nsfs.c index 4e77eba0c8fc..0e3fe8fda5bf 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -589,6 +589,7 @@ static int nsfs_init_fs_context(struct fs_context *fc) struct pseudo_fs_context *ctx =3D init_pseudo(fc, NSFS_MAGIC); if (!ctx) return -ENOMEM; + ctx->s_d_flags |=3D DCACHE_DONTCACHE; ctx->ops =3D &nsfs_ops; ctx->eops =3D &nsfs_export_operations; ctx->dops =3D &ns_dentry_operations; --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 E626F270545; Wed, 22 Oct 2025 16:06:26 +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=1761149187; cv=none; b=dKGPaym7vfyqGh32HwpJ8PfTLxaG6p891Zd3ALWf5aPgFsfHm0NtJYKCJvw701q4W5Xo+XYmCWvlV/656WeBnLXyIj4LJHtbn7/UuccXAGdezJ6yJ5/krFsi2GgkspfHgeT14S3ZPuPDI6AMIIM6Eh+VqvIkSXzXvJIFpjPSUpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149187; c=relaxed/simple; bh=LCe8V3QgmxQPWsHxmkO/HYNSTPj5l9bqGO1onywb9Xk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HtiDXdGp7vYmoXyMYjByt89l4e+hSs1OsN731TZWco93EMnwDJ+HUBkOkr5dcOCB20itKNLAK+SOUlj473Fskry5mFQva6CACLVnVjKhPfDTOzDvDJY2eGjzxa6GxyMMc3+XmXBKi3f5oWiiAOrzeLCfeBLoq3S5t2ipCxQ0Ljk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s8PIA0Vf; 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="s8PIA0Vf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4AB2C4CEE7; Wed, 22 Oct 2025 16:06:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149186; bh=LCe8V3QgmxQPWsHxmkO/HYNSTPj5l9bqGO1onywb9Xk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=s8PIA0VfE2ocot2tubS9anEfXvamyEbPyN402RWBQItpu7LgmxTAvhiyFhTu5UUlV j4eZKpkf5GFRPZbzuR7ckT0ayuqwhge31dZRmzTIoHJneikhFhKUDKpoKKjfvF5tcq at5Gqq5YhALw5/YswpMQ+bNStLftu7wsuS8HP/LaUaStyKaHaGBJ0HWvQ0vI8yme48 YFgqDRG+Wjqn3sdoPPghsyOMgs5eNPeWfdtK2ePq6JMLCsq2IrPvGbCwj3f/avURaT KX/HwY6P3xolMpxIeRMd8nokUNvHczoa3TRu//JFrzLmzf99Ody3+TVIhI8+ZQCkyv 1qe41AbBRRnrg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:42 +0200 Subject: [PATCH v2 04/63] pidfs: raise DCACHE_DONTCACHE explicitly Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-4-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=824; i=brauner@kernel.org; h=from:subject:message-id; bh=LCe8V3QgmxQPWsHxmkO/HYNSTPj5l9bqGO1onywb9Xk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhifVJGWW9Lvo3Ewoiz13xPS9uLTihRbTIz1cwNt vwb9GxSRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwERM/zEy3Fq0f6bJnP3Tnky8 VbZKwcZ35qpTnvLOUS2vEnebrQh73MHwT2FCUucTqWVr3zJrGft0Cu8o9t+9ytTurE+X4HetA3t l+AA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 While pidfs dentries are never hashed and thus retain_dentry() will never consider them for placing them on the LRU it isn't great to always have to go and remember that. Raise DCACHE_DONTCACHE explicitly as a visual marker that dentries aren't kept but freed immediately instead. Signed-off-by: Christian Brauner --- fs/pidfs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/pidfs.c b/fs/pidfs.c index 0ef5b47d796a..db236427fc2c 100644 --- a/fs/pidfs.c +++ b/fs/pidfs.c @@ -1022,6 +1022,7 @@ static int pidfs_init_fs_context(struct fs_context *f= c) =20 fc->s_iflags |=3D SB_I_NOEXEC; fc->s_iflags |=3D SB_I_NODEV; + ctx->s_d_flags |=3D DCACHE_DONTCACHE; ctx->ops =3D &pidfs_sops; ctx->eops =3D &pidfs_export_operations; ctx->dops =3D &pidfs_dentry_operations; --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 04211246764; Wed, 22 Oct 2025 16:06:32 +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=1761149192; cv=none; b=Llxzg9p/8k0ZWbGDSKHjdKJ1N4m0vzO3AHqN4wzW2bkLXF1VMh5r6sz/5Ef6N4KAYDRtbXSsDFmYIfm8vdA0IgNYoMUyz+b0qmw5YFhIoL3cMmi9XfwP6jF67WoKAVGdkvD1A7OXytXlYF/4u83N4jngPtjbKoKEQrS4QoKypiM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149192; c=relaxed/simple; bh=KoKI9phRTGMhjpn+9D8BgtjcoxSIgpJa0JnjxzKpEbY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=TwtWnzk5WhD0CnhBFt+vEtDgH9zmanyjPwMgjFE+uAITZeOXzfQz3Xegg0sWgfoxyIvGHZ7GPpHIXN0pYUro50HiYjL4V8wym+7LHUyqNZ6uqRKOzg1HIdSYBVoC6RL8ggbxNt4gziwXI4ZXlU5zBsHZ0sXza7x5tvWHypJ/1NQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kaPsLC0K; 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="kaPsLC0K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CBCDC4CEF7; Wed, 22 Oct 2025 16:06:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149191; bh=KoKI9phRTGMhjpn+9D8BgtjcoxSIgpJa0JnjxzKpEbY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kaPsLC0Kr59/ZM2zoqoz9UqFSqZJd2U5vFpwbLr/UHs1HbGJLizo/7CkWwNa/R+7r jL76e9CrN/WCtzRZSU7Lesna832v9/PteqX0VgdhGGoNgftR8UV4+pz/UKebzcWTK3 Dbej41WnhueynxU7K/4n/QVP6WqBFv+uG2+ug2v39KEXYXzYx0xhsOSM7eAx2m3qE8 OkcDXc5JRC0BrTHU6MtD6gO9tdj011GVJPFE5UXHPHho+Vyg+uPc33tZNtITXKAQWE 2fiYe+GaoCl+YMwpKEpFbTXUMgzOPbgNwzQBAVnKlf2dsyuCNMSOT43mMxVT04hkBM r3q3v/JInDKgQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:43 +0200 Subject: [PATCH v2 05/63] nsfs: raise SB_I_NODEV and SB_I_NOEXEC Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-5-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=647; i=brauner@kernel.org; h=from:subject:message-id; bh=KoKI9phRTGMhjpn+9D8BgtjcoxSIgpJa0JnjxzKpEbY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHiSLHZkhtzEN5K6h5MfPMk85ncrf+rCx6KP/omtN M99Lb1NqaOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiV+oYGVYe4077wdI3/YvT ZRnbjKh9oVXKm2W+d09g0DoufvuScTTD/+znec0hTs8+O2wsbdlxvFPslH/ppgWPD7vIOi9e/+2 uHh8A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 There's zero need for nsfs to allow device nodes or execution. Signed-off-by: Christian Brauner --- fs/nsfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/nsfs.c b/fs/nsfs.c index 0e3fe8fda5bf..363be226e357 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -589,6 +589,8 @@ static int nsfs_init_fs_context(struct fs_context *fc) struct pseudo_fs_context *ctx =3D init_pseudo(fc, NSFS_MAGIC); if (!ctx) return -ENOMEM; + fc->s_iflags |=3D SB_I_NOEXEC; + fc->s_iflags |=3D SB_I_NODEV; ctx->s_d_flags |=3D DCACHE_DONTCACHE; ctx->ops =3D &nsfs_ops; ctx->eops =3D &nsfs_export_operations; --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 2F2D929993A; Wed, 22 Oct 2025 16:06: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=1761149197; cv=none; b=LoejxZ/BBb3TiqZEjyUywdQ1wzaXGFvonAbjhTbHZdEadCNuDWsuebowlqWUV6xGaN9kC1MEGZV3wb8bhqGZAZr5vZqj3uaTqIS3mOtFsvepB3O7qOH/GDPMsjqHZG7IBB+2capdmShxZ8OiJxMp9Phyx4XNaT5TCXBZfNF9QME= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149197; c=relaxed/simple; bh=74AZcYyOqxtykIDy/RGdL2vrgfuHMaAEm8WcGrCjYG4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nowQFhRTyPfsE0oz/zCXpUxQ4R9w4EwJfprXUuuLqaRED8KW027Gdcg2DLucUTUNcmgCI/5QjQywK2pYX7mte6QJDmdIlOJ3aZUcylhHJZVnrsd9JX2bb6EAF+jv+r9t6MGFOnWXpI+S+zdOeY8ChDzPrNLvrnZ0qVwRXHwb/D8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GsorfsuM; 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="GsorfsuM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 56A08C4CEF7; Wed, 22 Oct 2025 16:06:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149197; bh=74AZcYyOqxtykIDy/RGdL2vrgfuHMaAEm8WcGrCjYG4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=GsorfsuMaDIbFLNgdihZm04ueS3KjYr/ga6yYj4Zfg24+ohkDKwX86q+33D1/Vuvb aoccV/kAOgePvPxCn70d5jg3agm1COKNt+uhWnLVuthdG9tNKa4jNv67AMq/Wcn3LK MlVQaKArHievEQkGdNGEjUithrWeAtY9C5mmQ/uBaWRJ9PHYlM5ECSGwZ0/1FcBiBW yK8IOTbrUkZQiG3zg9kz9+/lcvtCdiQI4eU0e82Hg/PNciWjIGLEXottZfdN15HOYf MsEEi1kXM7+hkQKxccs0dlkUcXwXQfGul3DOAJ5zFBbGq7j3U9MXuquh4jwUcgVvFZ 3MN3Hi+V5AGJA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:44 +0200 Subject: [PATCH v2 06/63] cgroup: add cgroup namespace to tree after owner is set Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-6-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=835; i=brauner@kernel.org; h=from:subject:message-id; bh=74AZcYyOqxtykIDy/RGdL2vrgfuHMaAEm8WcGrCjYG4=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjyPsfJZhGzwsvKjjj1BbqCWzuf7Clg3mV96bj9Z iV1KZYrHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPx8GT4X55lvP7WLFt5jz3i Lr/ett9ZXbPyu6zKOSnV24VC+2fzP2NkmG/xJ+31w8QYzTkBj9ku7PLxEVvkUa0X3TrnwvLyNVy tTAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Otherwise we trip VFS_WARN_ON_ONC() in __ns_tree_add_raw(). Fixes: 7c6059398533 ("cgroup: support ns lookup") Signed-off-by: Christian Brauner --- kernel/cgroup/namespace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c index fdbe57578e68..db9617556dd7 100644 --- a/kernel/cgroup/namespace.c +++ b/kernel/cgroup/namespace.c @@ -30,7 +30,6 @@ static struct cgroup_namespace *alloc_cgroup_ns(void) ret =3D ns_common_init(new_ns); if (ret) return ERR_PTR(ret); - ns_tree_add(new_ns); return no_free_ptr(new_ns); } =20 @@ -86,6 +85,7 @@ struct cgroup_namespace *copy_cgroup_ns(u64 flags, new_ns->ucounts =3D ucounts; new_ns->root_cset =3D cset; =20 + ns_tree_add(new_ns); return new_ns; } =20 --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 0424F2BCF54; Wed, 22 Oct 2025 16:06:42 +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=1761149203; cv=none; b=C8WjBCnriJJLdhJIMnqFJdvOCxadGCp2GFO0BL2DLM7EtMc7qSjsplb+PDhzww8sOjD4/DFx7DU29Nt9xfcvkjg0kgFaDaK4Ul1HGeAW7GHNKcfeWFTwws+1f78y6sS37Qse1X6WKw+259xyuRLH9OVIXpjn0SYAoyJGnbMix1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149203; c=relaxed/simple; bh=7aAHCcaecm2VZuosAD5WF6qVRIAZipjG6VYIR7g9o5A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KzcoDnUYTxtsoek1lsAODMd+F+vDo9OFReJsUjg0gSFDfVsj51pQ98RQQWz/54hGtoI9GIDKdN7wgyYisfXUqfi05k3jAK/1Xb55r2wWXFA8ZjW+f+hgagCV85ogYB6amkha3EJZv4F4zaCqGlUhwX5O9ZwoWeaLlxw3IQRjZU0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qTlKbQnN; 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="qTlKbQnN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 734CFC4CEE7; Wed, 22 Oct 2025 16:06:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149202; bh=7aAHCcaecm2VZuosAD5WF6qVRIAZipjG6VYIR7g9o5A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qTlKbQnNBX56eFps9NI0xPLDJT3oBO3igFJsVI9sktB+ntfqY1HmUoegPAr9j/Iuf uhoItu+5xSiNxtCcaE30Ry+LcEazHX244tvAQxADqJ58KH0pn+xTbv06iJqIx4o78r pUMiR6xojD8IMOQnvyuRr5Y6cMLIDcT2cQNfffmlwdqnmKEqA8K/fRw5mUCnoHhwsg aAilA+8luUhL+QT4xspKmuOBDwAefQKU9o4jX/hgJBvbblv2RYRGb1ITySdCMNl9sB I43kmLHqfSLM1fm4eE36/nLoPRSn3jWPe2YzV8iShKtf2ORqoglBHBBMJ619UKpQI9 zs8LFmrwDl8Zg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:45 +0200 Subject: [PATCH v2 07/63] nstree: simplify return Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-7-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=670; i=brauner@kernel.org; h=from:subject:message-id; bh=7aAHCcaecm2VZuosAD5WF6qVRIAZipjG6VYIR7g9o5A=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHiiM3vbZKk7We4P+YJeTgh1tDzpJPdE5NSjSwvOM XEI6W7T7ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIpXWMDLcYNTZFZsy2Uvj5 uWH2/TdG2nFm+ly376mtmmH7e6mV+FaG/2XhoWv+yL/x/RJ/l89zkqHB1SublfgnaXUceri47Uu fJisA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 node_to_ns() checks for NULL and the assert isn't really helpful and will have to be dropped later anyway. Signed-off-by: Christian Brauner --- kernel/nstree.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/kernel/nstree.c b/kernel/nstree.c index b24a320a11a6..369fd1675c6a 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -194,11 +194,6 @@ struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns= _type) break; } while (read_seqretry(&ns_tree->ns_tree_lock, seq)); =20 - if (!node) - return NULL; - - VFS_WARN_ON_ONCE(node_to_ns(node)->ns_type !=3D ns_type); - return node_to_ns(node); } =20 --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 5EC072765D7; Wed, 22 Oct 2025 16:06:49 +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=1761149209; cv=none; b=nHPY4BqpOuERZ7qxi9+KrrMJr2SAvZqUZqj2Ofwj6/zGzLZA/MXLCb1Xk4tLIvPNMPYP/CZysqovtgo5MdxNHGRZ6s42CcIuKneS1GMKOHAuKgXDMzWivOauCuVJszBHKSDjJ7P2pOzViujHPbzXE8HIyXbzCFBRyBhUklizPdE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149209; c=relaxed/simple; bh=GmTU8Q/fclIPwxUSGwafLrmOAHz2L+FN5rNlGUSGB9Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IAQlWywCx7Rf5wLbzqlC3WvNna0Qovzea/UCncfGj7lATauxPW48zVNUbUbIkSF0eF14EENHfa+HzkZDsz0LdTTQoJ0o8BXklimElP/HBQ1hzcpWivNliTZ6NHWOvLtkA2eKIfkMmIs1lYi2/SuJJHxJR9fcmWIuCVMAc/lJsjo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=u1bYCTdo; 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="u1bYCTdo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EBE31C4CEF7; Wed, 22 Oct 2025 16:06:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149207; bh=GmTU8Q/fclIPwxUSGwafLrmOAHz2L+FN5rNlGUSGB9Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=u1bYCTdoE+b7gFnvl2PGmM9NPIpUMfHNjZ8qBLI5Lvdd1v7UESkBh/I4S4TwifwLk NxbmFFBR6GRF0ep1c85mmO7P9/6T7Qwix3fOqWaLFpD2Ov6ccVnqC5Sa2uAeFLfHQF dViTYyrI8vyr18PSsbV1kfWGytPopK8y/EWAJ3BI6SkDK3w5sKm1/1JqcJLI/mxcbz b4ewLopZsejuLiFGMNJ7uJ2vE8TUKhMtaZMrN4+J4g3SmG8yEEkw2xtFHWuxDrw53t koMuip6wj3GJqqO77HQDKw3KfGvzQ4zl7JVaASG3xM6EZyS+eaDvUzjrFxphkZjrvS kH5cSmO89zutA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:46 +0200 Subject: [PATCH v2 08/63] ns: initialize ns_list_node for initial namespaces Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-8-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3505; i=brauner@kernel.org; h=from:subject:message-id; bh=GmTU8Q/fclIPwxUSGwafLrmOAHz2L+FN5rNlGUSGB9Y=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjyat6s6xpPjma+j70bd2LCm63vq17//fhiSUvNg 59Xpl42etBRysIgxsUgK6bI4tBuEi63nKdis1GmBswcViaQIQxcnAIwkelyDP/d59e/+dEX9U/i +OspqyezGKyIiV+xaa2yfXyK6JOgujQWhv9Fk3Mk73url72d1HbeR3Lxwogj+w81GbOFtnpv3t9 +Np0RAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Make sure that the list is always initialized for initial namespaces. Fixes: 885fc8ac0a4d ("nstree: make iterator generic") Signed-off-by: Christian Brauner --- fs/namespace.c | 1 + init/version-timestamp.c | 1 + ipc/msgutil.c | 1 + kernel/cgroup/cgroup.c | 1 + kernel/pid.c | 1 + kernel/time/namespace.c | 1 + kernel/user.c | 1 + 7 files changed, 7 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index d82910f33dc4..8ef8ba3dd316 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5993,6 +5993,7 @@ struct mnt_namespace init_mnt_ns =3D { .passive =3D REFCOUNT_INIT(1), .mounts =3D RB_ROOT, .poll =3D __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_list_node), }; =20 static void __init init_mount_tree(void) diff --git a/init/version-timestamp.c b/init/version-timestamp.c index d071835121c2..61b2405d97f9 100644 --- a/init/version-timestamp.c +++ b/init/version-timestamp.c @@ -20,6 +20,7 @@ struct uts_namespace init_uts_ns =3D { }, .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_uts_ns), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_list_node), #ifdef CONFIG_UTS_NS .ns.ops =3D &utsns_operations, #endif diff --git a/ipc/msgutil.c b/ipc/msgutil.c index 7a03f6d03de3..c9469fbce27c 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -30,6 +30,7 @@ struct ipc_namespace init_ipc_ns =3D { .ns.__ns_ref =3D REFCOUNT_INIT(1), .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_ipc_ns), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_list_node), #ifdef CONFIG_IPC_NS .ns.ops =3D &ipcns_operations, #endif diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 6ae5f48cf64e..a82918da8bae 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -256,6 +256,7 @@ struct cgroup_namespace init_cgroup_ns =3D { .ns.inum =3D ns_init_inum(&init_cgroup_ns), .root_cset =3D &init_css_set, .ns.ns_type =3D ns_common_type(&init_cgroup_ns), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_list_node), }; =20 static struct file_system_type cgroup2_fs_type; diff --git a/kernel/pid.c b/kernel/pid.c index 4fffec767a63..cb7574ca00f7 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -78,6 +78,7 @@ struct pid_namespace init_pid_ns =3D { .child_reaper =3D &init_task, .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_pid_ns), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_list_node), #ifdef CONFIG_PID_NS .ns.ops =3D &pidns_operations, #endif diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c index 5b6997f4dc3d..ee05cad288da 100644 --- a/kernel/time/namespace.c +++ b/kernel/time/namespace.c @@ -484,6 +484,7 @@ struct time_namespace init_time_ns =3D { .ns.inum =3D ns_init_inum(&init_time_ns), .ns.ops =3D &timens_operations, .frozen_offsets =3D true, + .ns.ns_list_node =3D LIST_HEAD_INIT(init_time_ns.ns.ns_list_node), }; =20 void __init time_ns_init(void) diff --git a/kernel/user.c b/kernel/user.c index 0163665914c9..b9cf3b056a71 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -70,6 +70,7 @@ struct user_namespace init_user_ns =3D { .owner =3D GLOBAL_ROOT_UID, .group =3D GLOBAL_ROOT_GID, .ns.inum =3D ns_init_inum(&init_user_ns), + .ns.ns_list_node =3D LIST_HEAD_INIT(init_user_ns.ns.ns_list_node), #ifdef CONFIG_USER_NS .ns.ops =3D &userns_operations, #endif --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 B95282C0282; Wed, 22 Oct 2025 16:06:53 +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=1761149213; cv=none; b=L09T5bwoEkr4vLJK+PoHqnYwIVsbdP41sQlYX2MkBPsAerWbEkNG2SzMVg4cXBoYotAoDsGqJhkGQuyPMLTOR45BxCu+KgT1reff+S/5k4bTupxyy7+PbDWrhnIv6+KAZ4hZMh5b2eHsp+dyc83YRAT+OOPJW8jEjKz0EMmvQog= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149213; c=relaxed/simple; bh=QM8oyzyJ0QczVJ0uxGx22MIzfw44XMMyED0mCYHZDF8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N76EtwJgMUXm0ob/JV2vp718F7+fhCJp8ObooQHKNL8KEKfkPq5UeVP3Ozv4flfKVhGSHetyl7nz6+QDhGEzD+UWl7we6/fEqDfQJInuFXJXjKclIjoRgYHqVwXDWOoL5w3xWh/lF2Pj/l/KU7KjShkuEebeNn9l0BSIxpcvTvc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gEpB/PVF; 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="gEpB/PVF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B61AC4CEE7; Wed, 22 Oct 2025 16:06:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149213; bh=QM8oyzyJ0QczVJ0uxGx22MIzfw44XMMyED0mCYHZDF8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gEpB/PVFOSaOpvp6ZR6yhvx1s5SZLhqFReaEmmbOrhMBrf8TM7A/NHAwomU1AdbHK VzxZtjN4LxE7PlBFQ1hNGvXYbm+DnEcNERJd5Be26Zk9lYGYBXqsmjA56eHZh4gAy7 1OinKw/8JZpf1v750FCJ98PZn5hsIGMHQ/l1cjjQWsK2mcYA9GlwJskWBT/iGwVlMK cxuIRiw67WelzJpOaEfzXhDc41/sJIjbDbSm20IyXWbyDMDrNIflhbwbllu+JcurWH 9mcRmZfKc0+AZoc8znBwgLDKaBj1SMQneuCBFXSPRSNYrrVhNIQiSeoIHzXthL7XBQ tup10iDnrgvYw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:47 +0200 Subject: [PATCH v2 09/63] ns: add __ns_ref_read() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-9-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1108; i=brauner@kernel.org; h=from:subject:message-id; bh=QM8oyzyJ0QczVJ0uxGx22MIzfw44XMMyED0mCYHZDF8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjC6Pnba1Ph24mX+DdlzE1Ta7ctUHlw48+fKyJOu /jeJPpKdZSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzEpJ3hr8AVC/ei+BpBu+Ni v2/Za4X2rdm/duk3TbmvZzmV645Y72P4KzLz/NW80qBZCqc/nDne7BLcnfrzk+c9Dc8FubyV8Z8 1WAE= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Implement ns_ref_read() the same way as ns_ref_{get,put}(). No point in making that any more special or different from the other helpers. Signed-off-by: Christian Brauner --- include/linux/ns_common.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index f5b68b8abb54..32114d5698dc 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -143,7 +143,12 @@ static __always_inline __must_check bool __ns_ref_get(= struct ns_common *ns) return refcount_inc_not_zero(&ns->__ns_ref); } =20 -#define ns_ref_read(__ns) refcount_read(&to_ns_common((__ns))->__ns_ref) +static __always_inline __must_check int __ns_ref_read(const struct ns_comm= on *ns) +{ + return refcount_read(&ns->__ns_ref); +} + +#define ns_ref_read(__ns) __ns_ref_read(to_ns_common((__ns))) #define ns_ref_inc(__ns) refcount_inc(&to_ns_common((__ns))->__ns_ref) #define ns_ref_get(__ns) __ns_ref_get(to_ns_common((__ns))) #define ns_ref_put(__ns) __ns_ref_put(to_ns_common((__ns))) --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 AA48227A10D; Wed, 22 Oct 2025 16:06:59 +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=1761149219; cv=none; b=XDGJQk+UKeBiOoomuo8zuDqIRZ802EMPqBDLbfC5zqm5SP64HQnuc8cuj6EYGKuqYpBx6Z0tpuWfhvVZfxjKHai0vOxdATukKa+GuWh5mklPza5q6VL1M0kpxIDE+DVnUJ7RACiX1CMV/98ud71pOh/8ElvtTAax4PWyhF0TRyM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149219; c=relaxed/simple; bh=+BA6Ji07XyQJ9aDuuwwFHepKxfmtS4I8owdAv7+CnpU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KB+Qk7Dp/0gLWD2G/dohFgiuG+rBHpgq2fovT+qvNNXD+77ugREcXBXBUKFnIbstndeAM1DjZQM9WosL6G+2c2tp0mE9D7GuXaPWBYJP6C4qLrssuy2JOAztqVF3EEacFfLNuZzlXzKGL4tt2LZaugVGwZwjd6yFILQ8CuZKduY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tzbmJdnQ; 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="tzbmJdnQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C347FC4CEF7; Wed, 22 Oct 2025 16:06:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149218; bh=+BA6Ji07XyQJ9aDuuwwFHepKxfmtS4I8owdAv7+CnpU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tzbmJdnQNs1XKkaGcs8LZ0X4n6OR4B+W8VGLPJ/K8FvxheNeO7QWcUiXofyoaJ9XP 9iBEkcISk7GIxHuuy4RQA3Ur6MEvuW7mUalLySdDGx03Je9yK4tZLFxBWcxg9X1mvL Z2CJaLvqvkashldzmVH9R/vgVKjRNYsQN4TVOVE5atWrddcRxvnGjcmHo+iEH7JI58 IBglMzSjgqOs5FTt1IKMMqpkAhyc21AC7LrHOU9+gzCuSDVukGxJHwO5LVi1J2Ydkt Gm0K4Kb/6BsP2ZEZLzKpWpSSul1It6aLI7cfk2h/F5fY4ZmoDxfS76OnjsGmwDWZ8O 1J8oQ06k3Q0Uw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:48 +0200 Subject: [PATCH v2 10/63] ns: add active reference count Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-10-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=34379; i=brauner@kernel.org; h=from:subject:message-id; bh=+BA6Ji07XyQJ9aDuuwwFHepKxfmtS4I8owdAv7+CnpU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjyzuv3qtxVOhv2Xz3eOcUvwMj86OT5gveV5hiZf t2hWsJk2lHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAnCRdQz/jIXSfs5t8PU//lLX U+tpfthk7c/ZL/6yLLj8cRvrpm87bzD8T+iNdwlakatx9d5z4+lTjH1P3XsopmUVLSP/Setn7Or TfAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 The namespace tree is, among other things, currently used to support file handles for namespaces. When a namespace is created it is placed on the namespace trees and when it is destroyed it is removed from the namespace trees. While a namespace is on the namespace trees with a valid reference count it is possible to reopen it through a namespace file handle. This is all fine but has some issues that should be addressed. On current kernels a namespace is visible to userspace in the following cases: (1) The namespace is in use by a task. (2) The namespace is persisted through a VFS object (namespace file descriptor or bind-mount). Note that (2) only cares about direct persistence of the namespace itself not indirectly via e.g., file->f_cred file references or similar. (3) The namespace is a hierarchical namespace type and is the parent of a single or multiple child namespaces. Case (3) is interesting because it is possible that a parent namespace might not fulfill any of (1) or (2), i.e., is invisible to userspace but it may still be resurrected through the NS_GET_PARENT ioctl(). Currently namespace file handles allow much broader access to namespaces than what is currently possible via (1)-(4). The reason is that namespaces may remain pinned for completely internal reasons yet are inaccessible to userspace. For example, a user namespace my remain pinned by get_cred() calls to stash the opener's credentials into file->f_cred. As it stands file handles allow to resurrect such a users namespace even though this should not be possible via (1)-(3). This is a fundamental uapi change that we shouldn't do if we don't have to. Consider the following insane case: Various architectures support the CONFIG_MMU_LAZY_TLB_REFCOUNT option which uses lazy TLB destruction. When this option is set a userspace task's struct mm_struct may be used for kernel threads such as the idle task and will only be destroyed once the cpu's runqueue switches back to another task. But because of ptrace() permission checks struct mm_struct stashes the user namespace of the task that struct mm_struct originally belonged to. The kernel thread will take a reference on the struct mm_struct and thus pin it. So on an idle system user namespaces can be persisted for arbitrary amounts of time which also means that they can be resurrected using namespace file handles. That makes no sense whatsoever. The problem is of course excarabted on large systems with a huge number of cpus. To handle this nicely we introduce an active reference count which tracks (1)-(3). This is easy to do as all of these things are already managed centrally. Only (1)-(3) will count towards the active reference count and only namespaces which are active may be opened via namespace file handles. The problem is that namespaces may be resurrected. Which means that they can become temporarily inactive and will be reactived some time later. Currently the only example of this is the SIOGCSKNS socket ioctl. The SIOCGSKNS ioctl allows to open a network namespace file descriptor based on a socket file descriptor. If a socket is tied to a network namespace that subsequently becomes inactive but that socket is persisted by another process in another network namespace (e.g., via SCM_RIGHTS of pidfd_getfd()) then the SIOCGSKNS ioctl will resurrect this network namespace. So calls to open_related_ns() and open_namespace() will end up resurrecting the corresponding namespace tree. Note that the active reference count does not regulate the lifetime of the namespace itself. This is still done by the normal reference count. The active reference count can only be elevated if the regular reference count is elevated. The active reference count also doesn't regulate the presence of a namespace on the namespace trees. It only regulates its visiblity to namespace file handles (and in later patches to listns()). A namespace remains on the namespace trees from creation until its actual destruction. This will allow the kernel to always reach any namespace trivially and it will also enable subsystems like bpf to walk the namespace lists on the system for tracing or general introspection purposes. Note that different namespaces have different visibility lifetimes on current kernels. While most namespace are immediately released when the last task using them exits, the user- and pid namespace are persisted and thus both remain accessible via /proc//ns/. The user namespace lifetime is aliged with struct cred and is only released through exit_creds(). However, it becomes inaccessible to userspace once the last task using it is reaped, i.e., when release_task() is called and all proc entries are flushed. Similarly, the pid namespace is also visible until the last task using it has been reaped and the associated pid numbers are freed. The active reference counts of the user- and pid namespace are decremented once the task is reaped. Signed-off-by: Christian Brauner --- fs/namespace.c | 2 + fs/nsfs.c | 46 +++++++++- include/linux/ns_common.h | 142 ++++++++++++++++++++++++++++- include/linux/nsfs.h | 3 + init/version-timestamp.c | 1 + ipc/msgutil.c | 1 + ipc/namespace.c | 1 + kernel/cgroup/cgroup.c | 1 + kernel/cgroup/namespace.c | 1 + kernel/cred.c | 17 ++++ kernel/exit.c | 1 + kernel/nscommon.c | 221 ++++++++++++++++++++++++++++++++++++++++++= +++- kernel/nsproxy.c | 7 ++ kernel/pid.c | 11 +++ kernel/pid_namespace.c | 1 + kernel/time/namespace.c | 2 + kernel/user.c | 1 + kernel/user_namespace.c | 1 + kernel/utsname.c | 1 + net/core/net_namespace.c | 1 + 20 files changed, 458 insertions(+), 4 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 8ef8ba3dd316..87116def5ee3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4173,6 +4173,7 @@ struct mnt_namespace *copy_mnt_ns(u64 flags, struct m= nt_namespace *ns, p =3D next_mnt(skip_mnt_tree(p), old); } ns_tree_add_raw(new_ns); + ns_ref_active_get_owner(new_ns); return new_ns; } =20 @@ -5989,6 +5990,7 @@ struct mnt_namespace init_mnt_ns =3D { .ns.ops =3D &mntns_operations, .user_ns =3D &init_user_ns, .ns.__ns_ref =3D REFCOUNT_INIT(1), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .ns.ns_type =3D ns_common_type(&init_mnt_ns), .passive =3D REFCOUNT_INIT(1), .mounts =3D RB_ROOT, diff --git a/fs/nsfs.c b/fs/nsfs.c index 363be226e357..ef9880232845 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -58,6 +58,8 @@ const struct dentry_operations ns_dentry_operations =3D { static void nsfs_evict(struct inode *inode) { struct ns_common *ns =3D inode->i_private; + + __ns_ref_active_put(ns); clear_inode(inode); ns->ops->put(ns); } @@ -419,6 +421,16 @@ static int nsfs_init_inode(struct inode *inode, void *= data) inode->i_mode |=3D S_IRUGO; inode->i_fop =3D &ns_file_operations; inode->i_ino =3D ns->inum; + + /* + * Bring the namespace subtree back to life if we have to. This + * can happen when e.g., all processes using a network namespace + * and all namespace files or namespace file bind-mounts have + * died but there are still sockets pinning it. The SIOCGSKNS + * ioctl on such a socket will resurrect the relevant namespace + * subtree. + */ + __ns_ref_active_resurrect(ns); return 0; } =20 @@ -493,7 +505,15 @@ static struct dentry *nsfs_fh_to_dentry(struct super_b= lock *sb, struct fid *fh, VFS_WARN_ON_ONCE(ns->ns_type !=3D fid->ns_type); VFS_WARN_ON_ONCE(ns->inum !=3D fid->ns_inum); =20 - if (!__ns_ref_get(ns)) + /* + * This is racy because we're not actually taking an + * active reference. IOW, it could happen that the + * namespace becomes inactive after this check. + * We don't care because nsfs_init_inode() will just + * resurrect the relevant namespace tree for us. If it + * has been active here we just proclaim it as namespac. + */ + if (!ns_get_unless_inactive(ns)) return NULL; } =20 @@ -614,3 +634,27 @@ void __init nsfs_init(void) nsfs_root_path.mnt =3D nsfs_mnt; nsfs_root_path.dentry =3D nsfs_mnt->mnt_root; } + +void nsproxy_ns_active_get(struct nsproxy *ns) +{ + ns_ref_active_get(ns->mnt_ns); + ns_ref_active_get(ns->uts_ns); + ns_ref_active_get(ns->ipc_ns); + ns_ref_active_get(ns->pid_ns_for_children); + ns_ref_active_get(ns->cgroup_ns); + ns_ref_active_get(ns->net_ns); + ns_ref_active_get(ns->time_ns); + ns_ref_active_get(ns->time_ns_for_children); +} + +void nsproxy_ns_active_put(struct nsproxy *ns) +{ + ns_ref_active_put(ns->mnt_ns); + ns_ref_active_put(ns->uts_ns); + ns_ref_active_put(ns->ipc_ns); + ns_ref_active_put(ns->pid_ns_for_children); + ns_ref_active_put(ns->cgroup_ns); + ns_ref_active_put(ns->net_ns); + ns_ref_active_put(ns->time_ns); + ns_ref_active_put(ns->time_ns_for_children); +} diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index 32114d5698dc..77ea38d8bac9 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -4,7 +4,9 @@ =20 #include #include +#include #include +#include =20 struct proc_ns_operations; =20 @@ -37,6 +39,73 @@ extern const struct proc_ns_operations cgroupns_operatio= ns; extern const struct proc_ns_operations timens_operations; extern const struct proc_ns_operations timens_for_children_operations; =20 +/* + * Namespace lifetimes are managed via a two-tier reference counting model: + * + * (1) __ns_ref (refcount_t): Main reference count tracking memory lifetim= e. + * Controls when the namespace structure itself is freed. It also + * pins the namespace on the namespace trees whereas (2) only + * regulates their visibility to userspace. + * + * (2) __ns_ref_active (atomic_t): Reference count tracking active users. + * Controls visibility of the namespace in the namespace trees. + * Any live task that uses the namespace (via nsproxy or cred) holds + * an active reference. Any open file descriptor or bind-mount of + * the namespace holds an active reference. Once all tasks have + * called exit_task_namespaces() and all file descriptors and + * bind-mounts have been released the active reference count drops + * to zero and the namespace becomes inactive. IOW, the namespace + * cannot be listed or opened via file handles anymore. + * + * Note that it is valid to transition from active to inactive and + * back from inactive to active e.g., when walking a hierarchical + * namespace tree upwards and reopening parent namespaces via + * NS_GET_PARENT that only exist because they are a parent of an + * actively used namespace. + * + * Relationship and lifecycle states: + * + * - Active (__ns_ref_active > 0): + * Namespace is actively used by one or more tasks. The namespace can + * be reopened via /proc//ns/ or discovered in the + * namespace tree. + * + * - Inactive (__ns_ref_active =3D=3D 0, __ns_ref > 0): + * No tasks are actively using the namespace and it isn't pinned by + * any bind-mounts or open file descriptors anymore. But the namespace + * is still kept alive by internal references. For example, the user + * namespace could be pinned by an open file through file->f_cred + * references when one of the now defunct tasks had opened a file and + * handed the file descriptor off to another process via a UNIX + * socket. Such references keep the namespace structure alive through + * __ns_ref but will not take an active reference. + * + * - Destroyed (__ns_ref =3D=3D 0): + * No references remain. The namespace is removed from the tree and free= d. + * + * State transitions: + * + * Active -> Inactive: + * When the last task using the namespace exits (via + * exit_task_namespaces()), it drops its active references to all + * namespaces apart from the pid namespace which remains accessible + * until the task has been reaped and its pid number is released. + * + * Inactive -> Active: + * When walking a hierarchical namespace tree upwards and reopening + * parent namespaces via NS_GET_PARENT that only exist because they + * are a parent of an actively used namespace it is possible to + * necrobump an inactive namespace back to the active state. + * + * Inactive -> Destroyed: + * When __ns_ref drops to zero (last file descriptor closed, last bind + * mount removed, parent namespace released), the namespace is removed + * from the tree and the memory is freed (after RCU grace period). + * + * Initial namespaces: + * Boot-time namespaces (init_net, init_pid_ns, etc.) start with + * __ns_ref_active =3D 1 and remain active forever. + */ struct ns_common { u32 ns_type; struct dentry *stashed; @@ -48,6 +117,7 @@ struct ns_common { u64 ns_id; struct rb_node ns_tree_node; struct list_head ns_list_node; + atomic_t __ns_ref_active; /* do not use directly */ }; struct rcu_head ns_rcu; }; @@ -56,6 +126,13 @@ struct ns_common { int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_= ns_operations *ops, int inum); void __ns_common_free(struct ns_common *ns); =20 +static __always_inline bool is_initial_namespace(struct ns_common *ns) +{ + VFS_WARN_ON_ONCE(ns->inum =3D=3D 0); + return unlikely(in_range(ns->inum, MNT_NS_INIT_INO, + IPC_NS_INIT_INO - MNT_NS_INIT_INO + 1)); +} + #define to_ns_common(__ns) \ _Generic((__ns), \ struct cgroup_namespace *: &(__ns)->ns, \ @@ -133,14 +210,26 @@ void __ns_common_free(struct ns_common *ns); =20 #define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns))) =20 +static __always_inline __must_check int __ns_ref_active_read(const struct = ns_common *ns) +{ + return atomic_read(&ns->__ns_ref_active); +} + static __always_inline __must_check bool __ns_ref_put(struct ns_common *ns) { - return refcount_dec_and_test(&ns->__ns_ref); + if (refcount_dec_and_test(&ns->__ns_ref)) { + VFS_WARN_ON_ONCE(__ns_ref_active_read(ns)); + return true; + } + return false; } =20 static __always_inline __must_check bool __ns_ref_get(struct ns_common *ns) { - return refcount_inc_not_zero(&ns->__ns_ref); + if (refcount_inc_not_zero(&ns->__ns_ref)) + return true; + VFS_WARN_ON_ONCE(__ns_ref_active_read(ns)); + return false; } =20 static __always_inline __must_check int __ns_ref_read(const struct ns_comm= on *ns) @@ -155,4 +244,53 @@ static __always_inline __must_check int __ns_ref_read(= const struct ns_common *ns #define ns_ref_put_and_lock(__ns, __lock) \ refcount_dec_and_lock(&to_ns_common((__ns))->__ns_ref, (__lock)) =20 +#define ns_ref_active_read(__ns) \ + ((__ns) ? __ns_ref_active_read(to_ns_common(__ns)) : 0) + +void __ns_ref_active_get_owner(struct ns_common *ns); + +static __always_inline void __ns_ref_active_get(struct ns_common *ns) +{ + WARN_ON_ONCE(atomic_add_negative(1, &ns->__ns_ref_active)); + VFS_WARN_ON_ONCE(is_initial_namespace(ns) && __ns_ref_active_read(ns) <= =3D 0); +} +#define ns_ref_active_get(__ns) \ + do { if (__ns) __ns_ref_active_get(to_ns_common(__ns)); } while (0) + +static __always_inline bool __ns_ref_active_get_not_zero(struct ns_common = *ns) +{ + if (atomic_inc_not_zero(&ns->__ns_ref_active)) { + VFS_WARN_ON_ONCE(!__ns_ref_read(ns)); + return true; + } + return false; +} + +#define ns_ref_active_get_owner(__ns) \ + do { if (__ns) __ns_ref_active_get_owner(to_ns_common(__ns)); } while (0) + +void __ns_ref_active_put_owner(struct ns_common *ns); + +static __always_inline void __ns_ref_active_put(struct ns_common *ns) +{ + if (atomic_dec_and_test(&ns->__ns_ref_active)) { + VFS_WARN_ON_ONCE(is_initial_namespace(ns)); + VFS_WARN_ON_ONCE(!__ns_ref_read(ns)); + __ns_ref_active_put_owner(ns); + } +} +#define ns_ref_active_put(__ns) \ + do { if (__ns) __ns_ref_active_put(to_ns_common(__ns)); } while (0) + +static __always_inline bool ns_get_unless_inactive(struct ns_common *ns) +{ + VFS_WARN_ON_ONCE(__ns_ref_active_read(ns) && !__ns_ref_read(ns)); + return __ns_ref_active_read(ns) && __ns_ref_get(ns); +} + +void __ns_ref_active_resurrect(struct ns_common *ns); + +#define ns_ref_active_resurrect(__ns) \ + do { if (__ns) __ns_ref_active_resurrect(to_ns_common(__ns)); } while (0) + #endif diff --git a/include/linux/nsfs.h b/include/linux/nsfs.h index e5a5fa83d36b..731b67fc2fec 100644 --- a/include/linux/nsfs.h +++ b/include/linux/nsfs.h @@ -37,4 +37,7 @@ void nsfs_init(void); =20 #define current_in_namespace(__ns) (__current_namespace_from_type(__ns) = =3D=3D __ns) =20 +void nsproxy_ns_active_get(struct nsproxy *ns); +void nsproxy_ns_active_put(struct nsproxy *ns); + #endif /* _LINUX_NSFS_H */ diff --git a/init/version-timestamp.c b/init/version-timestamp.c index 61b2405d97f9..c38498f94646 100644 --- a/init/version-timestamp.c +++ b/init/version-timestamp.c @@ -10,6 +10,7 @@ struct uts_namespace init_uts_ns =3D { .ns.ns_type =3D ns_common_type(&init_uts_ns), .ns.__ns_ref =3D REFCOUNT_INIT(2), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .name =3D { .sysname =3D UTS_SYSNAME, .nodename =3D UTS_NODENAME, diff --git a/ipc/msgutil.c b/ipc/msgutil.c index c9469fbce27c..d7c66b430470 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -28,6 +28,7 @@ DEFINE_SPINLOCK(mq_lock); */ struct ipc_namespace init_ipc_ns =3D { .ns.__ns_ref =3D REFCOUNT_INIT(1), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_ipc_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_list_node), diff --git a/ipc/namespace.c b/ipc/namespace.c index 59b12fcb40bd..23390d4f9b1f 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -87,6 +87,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_na= mespace *user_ns, sem_init_ns(ns); shm_init_ns(ns); ns_tree_add(ns); + ns_ref_active_get_owner(ns); =20 return ns; =20 diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index a82918da8bae..a18ec090ad7e 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -251,6 +251,7 @@ bool cgroup_enable_per_threadgroup_rwsem __read_mostly; /* cgroup namespace for init task */ struct cgroup_namespace init_cgroup_ns =3D { .ns.__ns_ref =3D REFCOUNT_INIT(2), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .user_ns =3D &init_user_ns, .ns.ops =3D &cgroupns_operations, .ns.inum =3D ns_init_inum(&init_cgroup_ns), diff --git a/kernel/cgroup/namespace.c b/kernel/cgroup/namespace.c index db9617556dd7..1aeb4303a3d8 100644 --- a/kernel/cgroup/namespace.c +++ b/kernel/cgroup/namespace.c @@ -86,6 +86,7 @@ struct cgroup_namespace *copy_cgroup_ns(u64 flags, new_ns->root_cset =3D cset; =20 ns_tree_add(new_ns); + ns_ref_active_get_owner(new_ns); return new_ns; } =20 diff --git a/kernel/cred.c b/kernel/cred.c index dbf6b687dc5c..9990875ea6e0 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -306,6 +306,11 @@ int copy_creds(struct task_struct *p, u64 clone_flags) kdebug("share_creds(%p{%ld})", p->cred, atomic_long_read(&p->cred->usage)); inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1); + /* + * Each task gets its own active reference, even if + * CLONE_THREAD shares the cred structure. + */ + ns_ref_active_get(new->user_ns); return 0; } =20 @@ -343,6 +348,8 @@ int copy_creds(struct task_struct *p, u64 clone_flags) =20 p->cred =3D p->real_cred =3D get_cred(new); inc_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1); + ns_ref_active_get(new->user_ns); + return 0; =20 error_put: @@ -435,6 +442,16 @@ int commit_creds(struct cred *new) */ if (new->user !=3D old->user || new->user_ns !=3D old->user_ns) inc_rlimit_ucounts(new->ucounts, UCOUNT_RLIMIT_NPROC, 1); + + /* + * Swap active refs if changing user_ns. This task is switching from + * actively using old->user_ns to actively using new->user_ns. + */ + if (new->user_ns !=3D old->user_ns) { + ns_ref_active_get(new->user_ns); + ns_ref_active_put(old->user_ns); + } + rcu_assign_pointer(task->real_cred, new); rcu_assign_pointer(task->cred, new); if (new->user !=3D old->user || new->user_ns !=3D old->user_ns) diff --git a/kernel/exit.c b/kernel/exit.c index 9f74e8f1c431..599375553c1f 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -291,6 +291,7 @@ void release_task(struct task_struct *p) write_unlock_irq(&tasklist_lock); /* @thread_pid can't go away until free_pids() below */ proc_flush_pid(thread_pid); + ns_ref_active_put(p->real_cred->user_ns); add_device_randomness(&p->se.sum_exec_runtime, sizeof(p->se.sum_exec_runtime)); free_pids(post.pids); diff --git a/kernel/nscommon.c b/kernel/nscommon.c index c1fb2bad6d72..d750e554d50b 100644 --- a/kernel/nscommon.c +++ b/kernel/nscommon.c @@ -2,6 +2,7 @@ =20 #include #include +#include #include =20 #ifdef CONFIG_DEBUG_VFS @@ -52,6 +53,8 @@ static void ns_debug(struct ns_common *ns, const struct p= roc_ns_operations *ops) =20 int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_= ns_operations *ops, int inum) { + int ret; + refcount_set(&ns->__ns_ref, 1); ns->stashed =3D NULL; ns->ops =3D ops; @@ -68,10 +71,226 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type= , const struct proc_ns_ope ns->inum =3D inum; return 0; } - return proc_alloc_inum(&ns->inum); + ret =3D proc_alloc_inum(&ns->inum); + if (ret) + return ret; + /* + * Tree ref starts at 0. It's incremented when namespace enters + * active use (installed in nsproxy) and decremented when all + * active uses are gone. Initial namespaces are always active. + */ + if (is_initial_namespace(ns)) + atomic_set(&ns->__ns_ref_active, 1); + else + atomic_set(&ns->__ns_ref_active, 0); + return 0; } =20 void __ns_common_free(struct ns_common *ns) { proc_free_inum(ns->inum); } + +static struct ns_common *ns_owner(struct ns_common *ns) +{ + struct user_namespace *owner; + + if (unlikely(!ns->ops)) + return NULL; + VFS_WARN_ON_ONCE(!ns->ops->owner); + owner =3D ns->ops->owner(ns); + VFS_WARN_ON_ONCE(!owner && ns !=3D to_ns_common(&init_user_ns)); + if (!owner) + return NULL; + /* Skip init_user_ns as it's always active */ + if (owner =3D=3D &init_user_ns) + return NULL; + return to_ns_common(owner); +} + +void __ns_ref_active_get_owner(struct ns_common *ns) +{ + ns =3D ns_owner(ns); + if (ns) + WARN_ON_ONCE(atomic_add_negative(1, &ns->__ns_ref_active)); +} + +/* + * The active reference count works by having each namespace that gets + * created take a single active reference on its owning user namespace. + * That single reference is only released once the child namespace's + * active count itself goes down. This makes it possible to efficiently + * resurrect a namespace tree: + * + * On namespace creation each new namespace will take a single reference + * count on its owning user namespace. + * + * A regular namespace tree might look as follow: + * Legend: + * + : adding active reference + * - : dropping active reference + * x : always active (initial namespace) + * + * + * net_ns pid_ns + * \ / + * + + + * user_ns1 (2) + * | + * ipc_ns | uts_ns + * \ | / + * + + + + * user_ns2 (3) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * If both net_ns and pid_ns put their last active reference on + * themselves it will cascade to user_ns1 dropping its own active + * reference and dropping one active reference on user_ns2: + * + * net_ns pid_ns + * \ / + * - - + * user_ns1 (0) + * | + * ipc_ns | uts_ns + * \ | / + * + - + + * user_ns2 (2) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * The iteration stops once we reach a namespace that still has active + * references. + */ +void __ns_ref_active_put_owner(struct ns_common *ns) +{ + for (;;) { + ns =3D ns_owner(ns); + if (!ns) + return; + if (!atomic_dec_and_test(&ns->__ns_ref_active)) + return; + } +} + +/* + * The active reference count works by having each namespace that gets + * created take a single active reference on its owning user namespace. + * That single reference is only released once the child namespace's + * active count itself goes down. This makes it possible to efficiently + * resurrect a namespace tree: + * + * On namespace creation each new namespace will take a single reference + * count on its owning user namespace. + * + * A regular namespace tree might look as follow: + * Legend: + * + : adding active reference + * - : dropping active reference + * x : always active (initial namespace) + * + * + * net_ns pid_ns + * \ / + * + + + * user_ns1 (2) + * | + * ipc_ns | uts_ns + * \ | / + * + + + + * user_ns2 (3) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * If both net_ns and pid_ns put their last active reference on + * themselves it will cascade to user_ns1 dropping its own active + * reference and dropping one active reference on user_ns2: + * + * net_ns pid_ns + * \ / + * - - + * user_ns1 (0) + * | + * ipc_ns | uts_ns + * \ | / + * + - + + * user_ns2 (2) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * Assume the whole tree is dead but all namespaces are still active: + * + * net_ns pid_ns + * \ / + * - - + * user_ns1 (0) + * | + * ipc_ns | uts_ns + * \ | / + * - - - + * user_ns2 (0) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * Now assume the net_ns gets resurrected (.e.g., via the SIOCGSKNS ioctl(= )): + * + * net_ns pid_ns + * \ / + * + - + * user_ns1 (0) + * | + * ipc_ns | uts_ns + * \ | / + * - + - + * user_ns2 (0) + * | + * cgroup_ns | mnt_ns + * \ | / + * x x x + * init_user_ns (1) + * + * If net_ns had a zero reference count and we bumped it we also need to + * take another reference on its owning user namespace. Similarly, if + * pid_ns had a zero reference count it also needs to take another + * reference on its owning user namespace. So both net_ns and pid_ns + * will each have their own reference on the owning user namespace. + * + * If the owning user namespace user_ns1 had a zero reference count then + * it also needs to take another reference on its owning user namespace + * and so on. + */ +void __ns_ref_active_resurrect(struct ns_common *ns) +{ + /* If we didn't resurrect the namespace we're done. */ + if (atomic_fetch_add(1, &ns->__ns_ref_active)) + return; + + /* + * We did resurrect it. Walk the ownership hierarchy upwards + * until we found an owning user namespace that is active. + */ + for (;;) { + ns =3D ns_owner(ns); + if (!ns) + return; + + if (atomic_fetch_add(1, &ns->__ns_ref_active)) + return; + } +} diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 19aa64ab08c8..3324d827f6bc 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -26,6 +26,7 @@ #include #include #include +#include =20 static struct kmem_cache *nsproxy_cachep; =20 @@ -179,12 +180,15 @@ int copy_namespaces(u64 flags, struct task_struct *ts= k) if ((flags & CLONE_VM) =3D=3D 0) timens_on_fork(new_ns, tsk); =20 + nsproxy_ns_active_get(new_ns); tsk->nsproxy =3D new_ns; return 0; } =20 void free_nsproxy(struct nsproxy *ns) { + nsproxy_ns_active_put(ns); + put_mnt_ns(ns->mnt_ns); put_uts_ns(ns->uts_ns); put_ipc_ns(ns->ipc_ns); @@ -232,6 +236,9 @@ void switch_task_namespaces(struct task_struct *p, stru= ct nsproxy *new) =20 might_sleep(); =20 + if (new) + nsproxy_ns_active_get(new); + task_lock(p); ns =3D p->nsproxy; p->nsproxy =3D new; diff --git a/kernel/pid.c b/kernel/pid.c index cb7574ca00f7..4f7b5054e23d 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -72,6 +72,7 @@ static int pid_max_max =3D PID_MAX_LIMIT; */ struct pid_namespace init_pid_ns =3D { .ns.__ns_ref =3D REFCOUNT_INIT(2), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .idr =3D IDR_INIT(init_pid_ns.idr), .pid_allocated =3D PIDNS_ADDING, .level =3D 0, @@ -118,9 +119,13 @@ static void delayed_put_pid(struct rcu_head *rhp) void free_pid(struct pid *pid) { int i; + struct pid_namespace *active_ns; =20 lockdep_assert_not_held(&tasklist_lock); =20 + active_ns =3D pid->numbers[pid->level].ns; + ns_ref_active_put(active_ns); + spin_lock(&pidmap_lock); for (i =3D 0; i <=3D pid->level; i++) { struct upid *upid =3D pid->numbers + i; @@ -285,6 +290,12 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t = *set_tid, spin_unlock(&pidmap_lock); idr_preload_end(); =20 + /* + * Increment active ref for the task's active PID namespace. + * This marks the namespace as actively in use by a running task. + */ + ns_ref_active_get(ns); + return pid; =20 out_unlock: diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 650be58d8d18..2e678338c6d1 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -124,6 +124,7 @@ static struct pid_namespace *create_pid_namespace(struc= t user_namespace *user_ns #endif =20 ns_tree_add(ns); + ns_ref_active_get_owner(ns); return ns; =20 out_free_inum: diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c index ee05cad288da..2e7c110bd13f 100644 --- a/kernel/time/namespace.c +++ b/kernel/time/namespace.c @@ -106,6 +106,7 @@ static struct time_namespace *clone_time_ns(struct user= _namespace *user_ns, ns->offsets =3D old_ns->offsets; ns->frozen_offsets =3D false; ns_tree_add(ns); + ns_ref_active_get_owner(ns); return ns; =20 fail_free_page: @@ -480,6 +481,7 @@ const struct proc_ns_operations timens_for_children_ope= rations =3D { struct time_namespace init_time_ns =3D { .ns.ns_type =3D ns_common_type(&init_time_ns), .ns.__ns_ref =3D REFCOUNT_INIT(3), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_time_ns), .ns.ops =3D &timens_operations, diff --git a/kernel/user.c b/kernel/user.c index b9cf3b056a71..bf60532856db 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -67,6 +67,7 @@ struct user_namespace init_user_ns =3D { }, .ns.ns_type =3D ns_common_type(&init_user_ns), .ns.__ns_ref =3D REFCOUNT_INIT(3), + .ns.__ns_ref_active =3D ATOMIC_INIT(1), .owner =3D GLOBAL_ROOT_UID, .group =3D GLOBAL_ROOT_GID, .ns.inum =3D ns_init_inum(&init_user_ns), diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index 03cb63883d04..9da3ee9e2eb1 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -160,6 +160,7 @@ int create_user_ns(struct cred *new) =20 set_cred_user_ns(new, ns); ns_tree_add(ns); + ns_ref_active_get_owner(ns); return 0; fail_keyring: #ifdef CONFIG_PERSISTENT_KEYRINGS diff --git a/kernel/utsname.c b/kernel/utsname.c index ebbfc578a9d3..18f55a05ad5b 100644 --- a/kernel/utsname.c +++ b/kernel/utsname.c @@ -60,6 +60,7 @@ static struct uts_namespace *clone_uts_ns(struct user_nam= espace *user_ns, ns->user_ns =3D get_user_ns(user_ns); up_read(&uts_sem); ns_tree_add(ns); + ns_ref_active_get_owner(ns); return ns; =20 fail_free: diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index b0e0f22d7b21..f30fb78f020c 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -450,6 +450,7 @@ static __net_init int setup_net(struct net *net) list_add_tail_rcu(&net->list, &net_namespace_list); up_write(&net_rwsem); ns_tree_add_raw(net); + ns_ref_active_get_owner(net); out: return error; =20 --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 2920227A129; Wed, 22 Oct 2025 16:07: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=1761149224; cv=none; b=XRcjaEmEeDNSsiQzrJunRhzct6f8ZNn0F8b3c8Dgn/dMeL+MdU2i3MG1u4+PTGdvnbfQ/XATn0NlxDfOhwKFgGk9ziewGyEPLPpNiFH2cItR5GeqSsBhx5VS8dgG6NSWOw3VGDHzzjwgEZwhXRZVSQLEw54CrmKYwBldEGpRqrQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149224; c=relaxed/simple; bh=BQTckd1lwN42TzFjtcvMTDlqbwW0nSU43xXjRiLpTAc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=eqJ2dL8s6Jv8iSGc8m9AuH2WRzQH9ntKL1CESWkVuDKV4XJix40ivg+CKqewINNQuhUaRHEJKEd9j6L0LY+A/vocWEmyf2f8T+NdQYiBx9IJYHnhoJDG3EwZlaQiZLqmERPp60CornMn3Tb2+4IgQzQeuMjDvtXXAr4ImEY5njs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CuGyKgnS; 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="CuGyKgnS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 41E4FC4CEE7; Wed, 22 Oct 2025 16:06:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149224; bh=BQTckd1lwN42TzFjtcvMTDlqbwW0nSU43xXjRiLpTAc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CuGyKgnSDuCkBcGOsZyzu/GT4DQb2+JiyLBHtJNlGRTVxUpFGrOcoltIeQNb7eQgM m1Cja7A86ViaW5mlORm27W3MMNI4YDAZHBqIg2qh6WDbvDIxo5fLX9f1eytyoYNRpU 50JZ13MDJT+n3qy5uXRwEfuaFdpRXMzJhtzZbtJo4cuUQ0+axlRr0a/TrSXLWnE9LY x20e73TfBGJN7shGonKyVv0/hYPSpTJtBHlGxud6FJG6GqBmBzsmbkwyG/kBYpP22x /90ptKQP3N9dx/CjT1cEMl3NSrheBfk+MArQgdjAriIwi+yRmbaT1NuejppZW2UYMC LOF33Lavu473Q== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:49 +0200 Subject: [PATCH v2 11/63] ns: use anonymous struct to group list member Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-11-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=775; i=brauner@kernel.org; h=from:subject:message-id; bh=BQTckd1lwN42TzFjtcvMTDlqbwW0nSU43xXjRiLpTAc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhyW23hLO6ehQd2T9K7JOGZWCa0pP2S+/rK7CXx2 zjnnJJT6ihlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiI6QpGhveCH9TeKlzp78v9 lvvKJZTRSSapltfjrlr/Zs+THboh+xn+SouF7fi2xrL7apVR2wzJ2B6hlEnmYQ2hH/QvZCkptK9 gBgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Make it easier to spot that they belong together conceptually. Signed-off-by: Christian Brauner --- include/linux/ns_common.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index 77ea38d8bac9..f340a279acc2 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -115,8 +115,10 @@ struct ns_common { union { struct { u64 ns_id; - struct rb_node ns_tree_node; - struct list_head ns_list_node; + struct /* per type rbtree and list */ { + struct rb_node ns_tree_node; + struct list_head ns_list_node; + }; atomic_t __ns_ref_active; /* do not use directly */ }; struct rcu_head ns_rcu; --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 CF2B926FD9B; Wed, 22 Oct 2025 16:07:09 +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=1761149229; cv=none; b=SNEekEIEg+2Duw6Khk8yQ7o40yiWTjdytsGhvSNb1ZGsn6GpBlomtnMPbRPuolveCOmXH6SLNItb5L7gcxQtZMyMa+xu/UHCT4ZBSmzAzdZQfcMZ8MbhySUGSdQszbwCKbdqWcTlR0NibKp7g7mWSt4V7CKOi+umKS90Y+cHi+g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149229; c=relaxed/simple; bh=I9Gr6zapSqyfvp5VjlbXhfKK8aPWlTON9tgSCFZUh0w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RIyhpPfDNFITODEvbeG3z7Amg9JoGdqWOh1tsO8eTfNv15BzQoM24wOgOTDU3hDy+D1feUH4VTsey1utDk/1Jx8b4reE3clxfIIt1psjh9B4w2HtOHcBixXEv94Oz6+30rEOSvYSGrCTVIdqieX7Qf6jnMfxwGmYHVNuBpm8+FM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=vAvNeKsc; 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="vAvNeKsc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7CA5CC4CEE7; Wed, 22 Oct 2025 16:07:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149229; bh=I9Gr6zapSqyfvp5VjlbXhfKK8aPWlTON9tgSCFZUh0w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=vAvNeKscG15zFM3N/MnNRBtSKqa6Wq26wDv0VhEIVmlz/hpdrrnTnyq9YYj0PFMwn Uem8UzNH8KcxxeogQo7BHbjyLj9DHZv5YOUvWdMrOTJyxd/A6P3yLrmZm3p6qkb3/q cD7sjNNQTVf9X3A+bgscKWUZZVy5dPtLFIxkBzAyRXmBwrEI5qAq8ZDB5X/9ua8y6b 2achFZxUw+50H2Pq5gUy6K7jksgmBC3rr8fTk6EFLfX1QGaCmbLYyEY+HO1W/kawDO 6RPL99KMMq0NYYySjLx2fOWl11Th4tq1aQpVljivKtzjd2Hw7LBZgfrrihAXW6iDEd D7eAP/4/xpjKg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:50 +0200 Subject: [PATCH v2 12/63] nstree: introduce a unified tree Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-12-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=8126; i=brauner@kernel.org; h=from:subject:message-id; bh=I9Gr6zapSqyfvp5VjlbXhfKK8aPWlTON9tgSCFZUh0w=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjy69kGScXY78zPQq9Hd6ws1+5vuCR/xH7znn2FF uKmGgqPO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyV5qRYXWh6JdV/YfUNlzO +JwvLX5r8pbzG+sEjvgU/uZ7v+hPzlSGv9I2p1k45PZn8D3k+LVyTsLDs71Gp86FfV4eJSNl2ud izQ8A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 This will allow userspace to lookup and stat a namespace simply by its identifier without having to know what type of namespace it is. Signed-off-by: Christian Brauner --- include/linux/ns_common.h | 4 ++ kernel/nscommon.c | 1 + kernel/nstree.c | 94 ++++++++++++++++++++++++++++++++++++-------= ---- 3 files changed, 77 insertions(+), 22 deletions(-) diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index f340a279acc2..b7d2123a9d19 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -115,6 +115,10 @@ struct ns_common { union { struct { u64 ns_id; + struct /* global namespace rbtree and list */ { + struct rb_node ns_unified_tree_node; + struct list_head ns_unified_list_node; + }; struct /* per type rbtree and list */ { struct rb_node ns_tree_node; struct list_head ns_list_node; diff --git a/kernel/nscommon.c b/kernel/nscommon.c index d750e554d50b..bdd32e14a587 100644 --- a/kernel/nscommon.c +++ b/kernel/nscommon.c @@ -61,6 +61,7 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, c= onst struct proc_ns_ope ns->ns_id =3D 0; ns->ns_type =3D ns_type; RB_CLEAR_NODE(&ns->ns_tree_node); + RB_CLEAR_NODE(&ns->ns_unified_tree_node); INIT_LIST_HEAD(&ns->ns_list_node); =20 #ifdef CONFIG_DEBUG_VFS diff --git a/kernel/nstree.c b/kernel/nstree.c index 369fd1675c6a..d21df06b6747 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -4,31 +4,30 @@ #include #include =20 +__cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock); +static struct rb_root ns_unified_tree =3D RB_ROOT; /* protected by ns_tree= _lock */ + /** * struct ns_tree - Namespace tree * @ns_tree: Rbtree of namespaces of a particular type * @ns_list: Sequentially walkable list of all namespaces of this type - * @ns_tree_lock: Seqlock to protect the tree and list * @type: type of namespaces in this tree */ struct ns_tree { - struct rb_root ns_tree; - struct list_head ns_list; - seqlock_t ns_tree_lock; - int type; + struct rb_root ns_tree; + struct list_head ns_list; + int type; }; =20 struct ns_tree mnt_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(mnt_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(mnt_ns_tree.ns_tree_lock), .type =3D CLONE_NEWNS, }; =20 struct ns_tree net_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(net_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(net_ns_tree.ns_tree_lock), .type =3D CLONE_NEWNET, }; EXPORT_SYMBOL_GPL(net_ns_tree); @@ -36,42 +35,36 @@ EXPORT_SYMBOL_GPL(net_ns_tree); struct ns_tree uts_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(uts_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(uts_ns_tree.ns_tree_lock), .type =3D CLONE_NEWUTS, }; =20 struct ns_tree user_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(user_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(user_ns_tree.ns_tree_lock), .type =3D CLONE_NEWUSER, }; =20 struct ns_tree ipc_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(ipc_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(ipc_ns_tree.ns_tree_lock), .type =3D CLONE_NEWIPC, }; =20 struct ns_tree pid_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(pid_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(pid_ns_tree.ns_tree_lock), .type =3D CLONE_NEWPID, }; =20 struct ns_tree cgroup_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(cgroup_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(cgroup_ns_tree.ns_tree_lock), .type =3D CLONE_NEWCGROUP, }; =20 struct ns_tree time_ns_tree =3D { .ns_tree =3D RB_ROOT, .ns_list =3D LIST_HEAD_INIT(time_ns_tree.ns_list), - .ns_tree_lock =3D __SEQLOCK_UNLOCKED(time_ns_tree.ns_tree_lock), .type =3D CLONE_NEWTIME, }; =20 @@ -84,6 +77,13 @@ static inline struct ns_common *node_to_ns(const struct = rb_node *node) return rb_entry(node, struct ns_common, ns_tree_node); } =20 +static inline struct ns_common *node_to_ns_unified(const struct rb_node *n= ode) +{ + if (!node) + return NULL; + return rb_entry(node, struct ns_common, ns_unified_tree_node); +} + static inline int ns_cmp(struct rb_node *a, const struct rb_node *b) { struct ns_common *ns_a =3D node_to_ns(a); @@ -98,13 +98,27 @@ static inline int ns_cmp(struct rb_node *a, const struc= t rb_node *b) return 0; } =20 +static inline int ns_cmp_unified(struct rb_node *a, const struct rb_node *= b) +{ + struct ns_common *ns_a =3D node_to_ns_unified(a); + struct ns_common *ns_b =3D node_to_ns_unified(b); + u64 ns_id_a =3D ns_a->ns_id; + u64 ns_id_b =3D ns_b->ns_id; + + if (ns_id_a < ns_id_b) + return -1; + if (ns_id_a > ns_id_b) + return 1; + return 0; +} + void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree) { struct rb_node *node, *prev; =20 VFS_WARN_ON_ONCE(!ns->ns_id); =20 - write_seqlock(&ns_tree->ns_tree_lock); + write_seqlock(&ns_tree_lock); =20 VFS_WARN_ON_ONCE(ns->ns_type !=3D ns_tree->type); =20 @@ -119,7 +133,8 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns_= tree *ns_tree) else list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node); =20 - write_sequnlock(&ns_tree->ns_tree_lock); + rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unifi= ed); + write_sequnlock(&ns_tree_lock); =20 VFS_WARN_ON_ONCE(node); } @@ -130,11 +145,12 @@ void __ns_tree_remove(struct ns_common *ns, struct ns= _tree *ns_tree) VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node)); VFS_WARN_ON_ONCE(ns->ns_type !=3D ns_tree->type); =20 - write_seqlock(&ns_tree->ns_tree_lock); + write_seqlock(&ns_tree_lock); rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree); + rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); list_bidir_del_rcu(&ns->ns_list_node); RB_CLEAR_NODE(&ns->ns_tree_node); - write_sequnlock(&ns_tree->ns_tree_lock); + write_sequnlock(&ns_tree_lock); } EXPORT_SYMBOL_GPL(__ns_tree_remove); =20 @@ -150,6 +166,17 @@ static int ns_find(const void *key, const struct rb_no= de *node) return 0; } =20 +static int ns_find_unified(const void *key, const struct rb_node *node) +{ + const u64 ns_id =3D *(u64 *)key; + const struct ns_common *ns =3D node_to_ns_unified(node); + + if (ns_id < ns->ns_id) + return -1; + if (ns_id > ns->ns_id) + return 1; + return 0; +} =20 static struct ns_tree *ns_tree_from_type(int ns_type) { @@ -175,28 +202,51 @@ static struct ns_tree *ns_tree_from_type(int ns_type) return NULL; } =20 -struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type) +static struct ns_common *__ns_unified_tree_lookup_rcu(u64 ns_id) { - struct ns_tree *ns_tree; struct rb_node *node; unsigned int seq; =20 - RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_lookup_rcu() = usage"); + do { + seq =3D read_seqbegin(&ns_tree_lock); + node =3D rb_find_rcu(&ns_id, &ns_unified_tree, ns_find_unified); + if (node) + break; + } while (read_seqretry(&ns_tree_lock, seq)); + + return node_to_ns_unified(node); +} + +static struct ns_common *__ns_tree_lookup_rcu(u64 ns_id, int ns_type) +{ + struct ns_tree *ns_tree; + struct rb_node *node; + unsigned int seq; =20 ns_tree =3D ns_tree_from_type(ns_type); if (!ns_tree) return NULL; =20 do { - seq =3D read_seqbegin(&ns_tree->ns_tree_lock); + seq =3D read_seqbegin(&ns_tree_lock); node =3D rb_find_rcu(&ns_id, &ns_tree->ns_tree, ns_find); if (node) break; - } while (read_seqretry(&ns_tree->ns_tree_lock, seq)); + } while (read_seqretry(&ns_tree_lock, seq)); =20 return node_to_ns(node); } =20 +struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type) +{ + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_lookup_rcu() = usage"); + + if (ns_type) + return __ns_tree_lookup_rcu(ns_id, ns_type); + + return __ns_unified_tree_lookup_rcu(ns_id); +} + /** * ns_tree_adjoined_rcu - find the next/previous namespace in the same * tree --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 2AB7B26FD9B; Wed, 22 Oct 2025 16:07:14 +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=1761149235; cv=none; b=Y9J5QSa7pOiGRA6o9w46ZPU2DNxmgtug1mynCWWyQDoTqGt20ykuqnD62oXyW41Oq955H34oH17d8Og34cji5A0E4I7x/3ZdnS+JaYd464hVdZkaVs+rd8oWC0tWOAeKK+MKOrEzgCqm3kDGXwM2kvQYhnkME0DmZjhZjzsYbHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149235; c=relaxed/simple; bh=j0WQly3wTCTevkshQpRfR9gFQtuZN2v/pgPj++s8+Zg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OC9GDYNhLCgzKIJQXehszr5G3M4iZTdhBcEJWFi0g3c9fXHLMTrRTp50zqLEONu1WDZPw8Z7UkVxjshJre2QXKMYhr8BCloqXflVVe+pyOElKuPC2B6QXhAOOtpX59XAbp9J0zruLg0ZlKr9WiX4uEuUHBQvGie+Fl0QpWMbFnk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=O1Q2FIkh; 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="O1Q2FIkh" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D34F4C4CEF7; Wed, 22 Oct 2025 16:07:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149234; bh=j0WQly3wTCTevkshQpRfR9gFQtuZN2v/pgPj++s8+Zg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=O1Q2FIkhNW3glBSr4QrWFub+LpYikf5GOvbITTQYjXL27CPSiAIyZq9uskxHdgZIB uOPdT4S4HXh3cgKJKxdL+ZgpGHDd2YcgVaNzI8QVpaCUOD4BdR9ZK5YR0Q2b7MSWTM gUXYCWtoO2MTCThsxpbw9ilehUv419J9SuH4+AXXEZ1nuq+dp3neXKVIph97Ngcs5S qXyMXUgl/0krSqkRpErgF1QESxCzFzl1CLvoy4/Rb/an5Q1YtXRfE2XRNa0ID7GVtk jlYxTWosqJ6cbBJ+yHL0tRcMlFbFzRcxEqy/98dMyZQIHdeo3Vp/WVx/xJTtEq5C6o CwGDd/SHOdRTg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:51 +0200 Subject: [PATCH v2 13/63] nstree: allow lookup solely based on inode Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-13-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1240; i=brauner@kernel.org; h=from:subject:message-id; bh=j0WQly3wTCTevkshQpRfR9gFQtuZN2v/pgPj++s8+Zg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhy0Uh8TvXrc8kuuksXPbES/X2Zocngq3Km0c3zs 98K7zb70FHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRW9MY/jvkamiof46R2vdX l5VVYJbh9clnf16OviNQPHPS1tKqEA9GhreZx7RSvd9tcLB9eHd39t60q6tvL3r230LksbBN9s4 /trwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 The namespace file handle struct nsfs_file_handle is uapi and userspace is expressly allowed to generate file handles without going through name_to_handle_at(). Allow userspace to generate a file handle where both the inode number and the namespace type are zero and just pass in the unique namespace id. The kernel uses the unified namespace tree to find the namespace and open the file handle. When the kernel creates a file handle via name_to_handle_at() it will always fill in the type and the inode number allowing userspace to retrieve core information. Signed-off-by: Christian Brauner --- fs/nsfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nsfs.c b/fs/nsfs.c index ef9880232845..bbef9a49eb37 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -502,8 +502,8 @@ static struct dentry *nsfs_fh_to_dentry(struct super_bl= ock *sb, struct fid *fh, return NULL; =20 VFS_WARN_ON_ONCE(ns->ns_id !=3D fid->ns_id); - VFS_WARN_ON_ONCE(ns->ns_type !=3D fid->ns_type); - VFS_WARN_ON_ONCE(ns->inum !=3D fid->ns_inum); + if (fid->ns_inum && (fid->ns_inum !=3D ns->inum)) + return NULL; =20 /* * This is racy because we're not actually taking an --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 9726827FD51; Wed, 22 Oct 2025 16:07:20 +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=1761149240; cv=none; b=nvi0KyQQaWDN8ey6ywW2c7TtdUfO2GYLMCthuPYnaLviujNIkdpM+8cz+IJeephixKoBR9PzNikIw5nHGXzr4WqyYVkQzr495qQuVd9nT13FmRm7N3dEN/FV/G2+fJtRC3VJK4jUbqqUzAMSTv4sXrHFgZhbm8yzKxj6MRWRAfU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149240; c=relaxed/simple; bh=0Z06FS7PHlmbbOXNaiYAotrcXY1wE2OxBYSA5XT3a6Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oeDMwCv4vy5pUKGNYXt0324Jhc8cWUJEypci+fXcyge5lZQExyadPRoTpmbRwLJDPafUuBNFYXZwYM/1fYu0B8N6ZqaMJ7HkQkRTOxV63uaNSyEc5LOS5tun7RRTh3lQGu+EWFwRzayVDtYBwVtoFMGW8CKoAW3JME8zai1Cw4g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Sq7Sd5kG; 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="Sq7Sd5kG" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4A884C4CEE7; Wed, 22 Oct 2025 16:07:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149240; bh=0Z06FS7PHlmbbOXNaiYAotrcXY1wE2OxBYSA5XT3a6Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Sq7Sd5kGvpZkYLe2SXy8OvT8VeOjVjRNRCTFtlQcdOIVAoGl59N7urVaBkUwbGj4u mceSsHeB9p3kXR8+gcI13VGd4ueOO0XYe1sKH8+zYFb6SsNIkzFDEp35QKY0qIBLpJ pWXdNSvsPKYoRvsVoP9EQ3HRJCgItItfxLS4fg+oUEQ0BEh8szS6fJ2RHI7SzqR4Vo PU+36ubSVd5UAHOEQS+9gWp0ME7ZVTqztZjYGY1Tcao4CZe/FPQ7GSfmVAqyWGIia9 x9mzJy2v2JKTmmbz0coXxZMnfU3yFW3tMDix7xa1v3jQYxMxV8W+k25CIl7ib4wC7i JuWScSnAjKeLA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:52 +0200 Subject: [PATCH v2 14/63] nstree: assign fixed ids to the initial namespaces Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-14-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6182; i=brauner@kernel.org; h=from:subject:message-id; bh=0Z06FS7PHlmbbOXNaiYAotrcXY1wE2OxBYSA5XT3a6Q=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHiSdUl67XdNIy09ieK+C+bT0z+lXJYsS/Hp3u/7a 88v6SMsHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPZ957hD0egz1TdGoYF82+a GNo3MvbPsPv8bemJrb7F+18/L1opcJ/hf61rgnTon2zl24sXvjvTEtnR8EIwL8w3N8DTzO/P04k RbAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 The initial set of namespace comes with fixed inode numbers making it easy for userspace to identify them solely based on that information. This has long preceeded anything here. Similarly, let's assign fixed namespace ids for the initial namespaces. Kill the cookie and use a sequentially increasing number. This has the nice side-effect that the owning user namespace will always have a namespace id that is smaller than any of it's descendant namespaces. Signed-off-by: Christian Brauner --- fs/namespace.c | 2 +- include/linux/nstree.h | 26 ++++++++++++++++++++++---- include/uapi/linux/nsfs.h | 14 ++++++++++++++ kernel/nstree.c | 13 ++++++++----- net/core/net_namespace.c | 2 +- 5 files changed, 46 insertions(+), 11 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index 87116def5ee3..5d8a80e1e944 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4094,7 +4094,7 @@ static struct mnt_namespace *alloc_mnt_ns(struct user= _namespace *user_ns, bool a return ERR_PTR(ret); } if (!anon) - ns_tree_gen_id(&new_ns->ns); + ns_tree_gen_id(new_ns); refcount_set(&new_ns->passive, 1); new_ns->mounts =3D RB_ROOT; init_waitqueue_head(&new_ns->poll); diff --git a/include/linux/nstree.h b/include/linux/nstree.h index 8b8636690473..96ee71622517 100644 --- a/include/linux/nstree.h +++ b/include/linux/nstree.h @@ -8,6 +8,7 @@ #include #include #include +#include =20 extern struct ns_tree cgroup_ns_tree; extern struct ns_tree ipc_ns_tree; @@ -29,7 +30,22 @@ extern struct ns_tree uts_ns_tree; struct user_namespace *: &(user_ns_tree), \ struct uts_namespace *: &(uts_ns_tree)) =20 -u64 ns_tree_gen_id(struct ns_common *ns); +#define ns_init_id(__ns) \ + _Generic((__ns), \ + struct cgroup_namespace *: CGROUP_NS_INIT_ID, \ + struct ipc_namespace *: IPC_NS_INIT_ID, \ + struct mnt_namespace *: MNT_NS_INIT_ID, \ + struct net *: NET_NS_INIT_ID, \ + struct pid_namespace *: PID_NS_INIT_ID, \ + struct time_namespace *: TIME_NS_INIT_ID, \ + struct user_namespace *: USER_NS_INIT_ID, \ + struct uts_namespace *: UTS_NS_INIT_ID) + +#define ns_tree_gen_id(__ns) \ + __ns_tree_gen_id(to_ns_common(__ns), \ + (((__ns) =3D=3D ns_init_ns(__ns)) ? ns_init_id(__ns) : 0)) + +u64 __ns_tree_gen_id(struct ns_common *ns, u64 id); void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree); void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree); struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type); @@ -37,9 +53,9 @@ struct ns_common *__ns_tree_adjoined_rcu(struct ns_common= *ns, struct ns_tree *ns_tree, bool previous); =20 -static inline void __ns_tree_add(struct ns_common *ns, struct ns_tree *ns_= tree) +static inline void __ns_tree_add(struct ns_common *ns, struct ns_tree *ns_= tree, u64 id) { - ns_tree_gen_id(ns); + __ns_tree_gen_id(ns, id); __ns_tree_add_raw(ns, ns_tree); } =20 @@ -59,7 +75,9 @@ static inline void __ns_tree_add(struct ns_common *ns, st= ruct ns_tree *ns_tree) * This function assigns a new id to the namespace and adds it to the * appropriate namespace tree and list. */ -#define ns_tree_add(__ns) __ns_tree_add(to_ns_common(__ns), to_ns_tree(__n= s)) +#define ns_tree_add(__ns) \ + __ns_tree_add(to_ns_common(__ns), to_ns_tree(__ns), \ + (((__ns) =3D=3D ns_init_ns(__ns)) ? ns_init_id(__ns) : 0)) =20 /** * ns_tree_remove - Remove a namespace from a namespace tree diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h index e098759ec917..f8bc2aad74d6 100644 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@ -67,4 +67,18 @@ struct nsfs_file_handle { #define NSFS_FILE_HANDLE_SIZE_VER0 16 /* sizeof first published struct */ #define NSFS_FILE_HANDLE_SIZE_LATEST sizeof(struct nsfs_file_handle) /* si= zeof latest published struct */ =20 +enum init_ns_id { + IPC_NS_INIT_ID =3D 1ULL, + UTS_NS_INIT_ID =3D 2ULL, + USER_NS_INIT_ID =3D 3ULL, + PID_NS_INIT_ID =3D 4ULL, + CGROUP_NS_INIT_ID =3D 5ULL, + TIME_NS_INIT_ID =3D 6ULL, + NET_NS_INIT_ID =3D 7ULL, + MNT_NS_INIT_ID =3D 8ULL, +#ifdef __KERNEL__ + NS_LAST_INIT_ID =3D MNT_NS_INIT_ID, +#endif +}; + #endif /* __LINUX_NSFS_H */ diff --git a/kernel/nstree.c b/kernel/nstree.c index d21df06b6747..de5ceda44637 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -68,8 +68,6 @@ struct ns_tree time_ns_tree =3D { .type =3D CLONE_NEWTIME, }; =20 -DEFINE_COOKIE(namespace_cookie); - static inline struct ns_common *node_to_ns(const struct rb_node *node) { if (!node) @@ -278,15 +276,20 @@ struct ns_common *__ns_tree_adjoined_rcu(struct ns_co= mmon *ns, /** * ns_tree_gen_id - generate a new namespace id * @ns: namespace to generate id for + * @id: if non-zero, this is the initial namespace and this is a fixed id * * Generates a new namespace id and assigns it to the namespace. All * namespaces types share the same id space and thus can be compared * directly. IOW, when two ids of two namespace are equal, they are * identical. */ -u64 ns_tree_gen_id(struct ns_common *ns) +u64 __ns_tree_gen_id(struct ns_common *ns, u64 id) { - guard(preempt)(); - ns->ns_id =3D gen_cookie_next(&namespace_cookie); + static atomic64_t namespace_cookie =3D ATOMIC64_INIT(NS_LAST_INIT_ID + 1); + + if (id) + ns->ns_id =3D id; + else + ns->ns_id =3D atomic64_inc_return(&namespace_cookie); return ns->ns_id; } diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index f30fb78f020c..a76b9b9709d6 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -439,7 +439,7 @@ static __net_init int setup_net(struct net *net) LIST_HEAD(net_exit_list); int error =3D 0; =20 - net->net_cookie =3D ns_tree_gen_id(&net->ns); + net->net_cookie =3D ns_tree_gen_id(net); =20 list_for_each_entry(ops, &pernet_list, list) { error =3D ops_init(ops, net); --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 F40702820A9; Wed, 22 Oct 2025 16:07:25 +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=1761149246; cv=none; b=TmwZ6gJUEl0z1vKHqj7joq3Sc96HJUusrKZ/lmItdDGwBObXwcqZDQ+sUwxCOysFCbKwrcZJi268W55m1er7Q7fMeAftu04gFgH4aUlrYAKOhhW8hnCjmd3+TpaemjhXFtTw7wJoZ7wOL3/fMPHVLYd2Kr6uRAlByMREGRBsp/0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149246; c=relaxed/simple; bh=D29D+H2EPiZJISFL40IfX5Y3tdXtohnOiqq233NStmo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rlV8eyIZc+7Gl06iWW7dzu5pdMZKgMxolF3qqY7aPWXU7hVP8bdMKUs2OW2QdhHHtLJ9zL0qAltYl09N6tGuRi7vZmsC1XcUUclMt1mpnoF7Hm6VqLtCVFA9dDx1B+bm9OMSPnTjL9q07z4pYOc92qzZDj3bhmF8xOu4uVnb2Rc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=puhw+qgT; 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="puhw+qgT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 989C7C4CEFD; Wed, 22 Oct 2025 16:07:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149245; bh=D29D+H2EPiZJISFL40IfX5Y3tdXtohnOiqq233NStmo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=puhw+qgTxhUgbr04MzQIOmfESoiRsibRT4ZgaE2kbxcjMa/bs0e2h8xur9nEDdUQc gPMkeX8P9k1jlReaCiZYDOzX1WDouDn/H/NQ6JRaN4o9G35X4gR4c/mp0GTzqG/g/0 nrgxOxMRfAIUM46r8/2Ne9Gl6hlkqA+5H1IMI37bnb1jyQRdFLhkqWdivPsUGbY5dG 43yDXpS6Tgwv6oSZul4gqmDI2teT48DNZLNl2lI6/0HjRYBEaTulyY/iGotP/wWXRT F8KeR2MB4zDRV1tCWYjDohXaTijg6hMeG/mfm/UUgoGqZeKoBmQK5hvm9ZKB9l12jm pUvm2+IelnxXw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:53 +0200 Subject: [PATCH v2 15/63] ns: maintain list of owned namespaces Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-15-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=7611; i=brauner@kernel.org; h=from:subject:message-id; bh=D29D+H2EPiZJISFL40IfX5Y3tdXtohnOiqq233NStmo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgafeXirgn6m54IF5jMX/ZKZL5Hc/pt86TXjUdW5 22z2h8o11HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjARbllGhvmZdxUPTe7NfKy0 K8t24ZxXWa8ZOPb7LVXWvtAiYH+6dCbD/4g9v9/d6Fh0XXTTMcc377mjL/1c5/DQ/a1LYqXm0pc KdvwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 The namespace tree doesn't express the ownership concept of namespace appropriately. Maintain a list of directly owned namespaces per user namespace. This will allow userspace and the kernel to use the listns() system call to walk the namespace tree by owning user namespace. Read-only list operations are completely lockless. Signed-off-by: Christian Brauner --- fs/namespace.c | 2 ++ include/linux/ns_common.h | 4 ++++ init/version-timestamp.c | 2 ++ ipc/msgutil.c | 2 ++ kernel/cgroup/cgroup.c | 2 ++ kernel/nscommon.c | 2 ++ kernel/nstree.c | 19 +++++++++++++++++++ kernel/pid.c | 2 ++ kernel/time/namespace.c | 2 ++ kernel/user.c | 2 ++ 10 files changed, 39 insertions(+) diff --git a/fs/namespace.c b/fs/namespace.c index 5d8a80e1e944..d460ca79f0e7 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5996,6 +5996,8 @@ struct mnt_namespace init_mnt_ns =3D { .mounts =3D RB_ROOT, .poll =3D __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll), .ns.ns_list_node =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_owner), }; =20 static void __init init_mount_tree(void) diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index b7d2123a9d19..88dce67e06e4 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -123,6 +123,10 @@ struct ns_common { struct rb_node ns_tree_node; struct list_head ns_list_node; }; + struct /* namespace ownership list */ { + struct list_head ns_owner; /* list of namespaces owned by this namespa= ce */ + struct list_head ns_owner_entry; /* node in the owner namespace's ns_o= wned list */ + }; atomic_t __ns_ref_active; /* do not use directly */ }; struct rcu_head ns_rcu; diff --git a/init/version-timestamp.c b/init/version-timestamp.c index c38498f94646..e5c278dabecf 100644 --- a/init/version-timestamp.c +++ b/init/version-timestamp.c @@ -22,6 +22,8 @@ struct uts_namespace init_uts_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_uts_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_owner), #ifdef CONFIG_UTS_NS .ns.ops =3D &utsns_operations, #endif diff --git a/ipc/msgutil.c b/ipc/msgutil.c index d7c66b430470..ce1de73725c0 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -32,6 +32,8 @@ struct ipc_namespace init_ipc_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_ipc_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_owner), #ifdef CONFIG_IPC_NS .ns.ops =3D &ipcns_operations, #endif diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index a18ec090ad7e..41a1fc562ed0 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -258,6 +258,8 @@ struct cgroup_namespace init_cgroup_ns =3D { .root_cset =3D &init_css_set, .ns.ns_type =3D ns_common_type(&init_cgroup_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_owner), }; =20 static struct file_system_type cgroup2_fs_type; diff --git a/kernel/nscommon.c b/kernel/nscommon.c index bdd32e14a587..ba46de0637c3 100644 --- a/kernel/nscommon.c +++ b/kernel/nscommon.c @@ -63,6 +63,8 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, c= onst struct proc_ns_ope RB_CLEAR_NODE(&ns->ns_tree_node); RB_CLEAR_NODE(&ns->ns_unified_tree_node); INIT_LIST_HEAD(&ns->ns_list_node); + INIT_LIST_HEAD(&ns->ns_owner); + INIT_LIST_HEAD(&ns->ns_owner_entry); =20 #ifdef CONFIG_DEBUG_VFS ns_debug(ns, ops); diff --git a/kernel/nstree.c b/kernel/nstree.c index de5ceda44637..829682bb04a1 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -3,6 +3,7 @@ #include #include #include +#include =20 __cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock); static struct rb_root ns_unified_tree =3D RB_ROOT; /* protected by ns_tree= _lock */ @@ -113,8 +114,10 @@ static inline int ns_cmp_unified(struct rb_node *a, co= nst struct rb_node *b) void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree) { struct rb_node *node, *prev; + const struct proc_ns_operations *ops =3D ns->ops; =20 VFS_WARN_ON_ONCE(!ns->ns_id); + VFS_WARN_ON_ONCE(ns->ns_type !=3D ns_tree->type); =20 write_seqlock(&ns_tree_lock); =20 @@ -132,6 +135,21 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns= _tree *ns_tree) list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node); =20 rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unifi= ed); + + if (ops) { + struct user_namespace *user_ns; + + VFS_WARN_ON_ONCE(!ops->owner); + user_ns =3D ops->owner(ns); + if (user_ns) { + struct ns_common *owner =3D &user_ns->ns; + VFS_WARN_ON_ONCE(owner->ns_type !=3D CLONE_NEWUSER); + list_add_tail_rcu(&ns->ns_owner_entry, &owner->ns_owner); + } else { + /* Only the initial user namespace doesn't have an owner. */ + VFS_WARN_ON_ONCE(ns !=3D to_ns_common(&init_user_ns)); + } + } write_sequnlock(&ns_tree_lock); =20 VFS_WARN_ON_ONCE(node); @@ -148,6 +166,7 @@ void __ns_tree_remove(struct ns_common *ns, struct ns_t= ree *ns_tree) rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); list_bidir_del_rcu(&ns->ns_list_node); RB_CLEAR_NODE(&ns->ns_tree_node); + list_bidir_del_rcu(&ns->ns_owner_entry); write_sequnlock(&ns_tree_lock); } EXPORT_SYMBOL_GPL(__ns_tree_remove); diff --git a/kernel/pid.c b/kernel/pid.c index 4f7b5054e23d..f82dab348540 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -80,6 +80,8 @@ struct pid_namespace init_pid_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_pid_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_owner), #ifdef CONFIG_PID_NS .ns.ops =3D &pidns_operations, #endif diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c index 2e7c110bd13f..15cb74267c75 100644 --- a/kernel/time/namespace.c +++ b/kernel/time/namespace.c @@ -485,6 +485,8 @@ struct time_namespace init_time_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_time_ns), .ns.ops =3D &timens_operations, + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_time_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_time_ns.ns.ns_owner), .frozen_offsets =3D true, .ns.ns_list_node =3D LIST_HEAD_INIT(init_time_ns.ns.ns_list_node), }; diff --git a/kernel/user.c b/kernel/user.c index bf60532856db..e392768ccd44 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -72,6 +72,8 @@ struct user_namespace init_user_ns =3D { .group =3D GLOBAL_ROOT_GID, .ns.inum =3D ns_init_inum(&init_user_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_user_ns.ns.ns_list_node), + .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_user_ns.ns.ns_owner_entry), + .ns.ns_owner =3D LIST_HEAD_INIT(init_user_ns.ns.ns_owner), #ifdef CONFIG_USER_NS .ns.ops =3D &userns_operations, #endif --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 657BF28489B; Wed, 22 Oct 2025 16:07:31 +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=1761149251; cv=none; b=KSNCWBhstNzsDlkr2dkISd0BoksIRHlrpHUQKxU30QEOr7FhGZTaV4UJU8NL0Huvix92X8nqAGKZ4IHyBPU/DyR7W+xdibAZhXE4os2IK2e3GJ2vdpiKYmfoVjJTIH1b1YxHT/x1SFDo8lpg111cuBRvaf3OHOjXK/AagNaCkn0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149251; c=relaxed/simple; bh=9nfoxwdtd3YmUqAJRC79K3mZAnLww/eYU3+vhS2CuZY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UyseTz9grBAZism2gZg8qEK5G5HUB41AliZF6JP/1QhmeECSITsI5IgVhSxcMHBQXtbLlyj3IZ11e4qBlW88244fUi2PmeVHcIKH9LUUSM38KAk1k4HHWowflEp0ukHJBmuTFWtYL1e4JrzaLF37JJBB5TgI8ZqSzuZd3NnAKWg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iLx3cZ4V; 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="iLx3cZ4V" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E34AEC4CEF7; Wed, 22 Oct 2025 16:07:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149250; bh=9nfoxwdtd3YmUqAJRC79K3mZAnLww/eYU3+vhS2CuZY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=iLx3cZ4VUcGp4ezo4zdJuuXuUC/lHIWH6kBSrr8FxjbJJ643Iu5gl1AOvBhzeAA+r zJgqyv9WHfu2KtESrw+v9uJAF9csPdaSzRa5x1/1RQi52OG0rxLVPeul+2HhdTArYE DsfwlD6bbsFcsjviszDhgTdw16h8VV1P2c10uivpvvotJy6ZDu4/DpKEhm3KfJ9DEo uG3Im1BNi9/yYBRVnAgxN2dss4MJodJuAixCLVxfBmFeuC+BygM+iw5JL92T1ImTnA CSCo2AomBtM/UOaN9+Q4uCMZx1fe/PETPP0wKOjb1e1fzRe+tGpRXozoW71Xe9zzcq JGN0bEdEsrU9A== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:54 +0200 Subject: [PATCH v2 16/63] nstree: add listns() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-16-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=30795; i=brauner@kernel.org; h=from:subject:message-id; bh=9nfoxwdtd3YmUqAJRC79K3mZAnLww/eYU3+vhS2CuZY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi6U/hmz+6pF72fv1o12VnYOaVk82aLY8eDDi0N6 E7ovvPRt6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiX24zMjyWO+pj/pt52WGR ZMaP0zLcml+Y8dyb17unL4Nz59GQP5MYGU4+uWu1f9FCf4sJ8fuPhuSKlB6xTFXtf8Bv6+DAGWt /kxcA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a new listns() system call that allows userspace to iterate through namespaces in the system. This provides a programmatic interface to discover and inspect namespaces, enhancing existing namespace apis. Currently, there is no direct way for userspace to enumerate namespaces in the system. Applications must resort to scanning /proc//ns/ across all processes, which is: 1. Inefficient - requires iterating over all processes 2. Incomplete - misses inactive namespaces that aren't attached to any running process but are kept alive by file descriptors, bind mounts, or parent namespace references 3. Permission-heavy - requires access to /proc for many processes 4. No ordering or ownership. 5. No filtering per namespace type: Must always iterate and check all namespaces. The list goes on. The listns() system call solves these problems by providing direct kernel-level enumeration of namespaces. It is similar to listmount() but obviously tailored to namespaces. /* * @req: Pointer to struct ns_id_req specifying search parameters * @ns_ids: User buffer to receive namespace IDs * @nr_ns_ids: Size of ns_ids buffer (maximum number of IDs to return) * @flags: Reserved for future use (must be 0) */ ssize_t listns(const struct ns_id_req *req, u64 *ns_ids, size_t nr_ns_ids, unsigned int flags); Returns: - On success: Number of namespace IDs written to ns_ids - On error: Negative error code /* * @size: Structure size * @ns_id: Starting point for iteration; use 0 for first call, then * use the last returned ID for subsequent calls to paginate * @ns_type: Bitmask of namespace types to include (from enum ns_type): * 0: Return all namespace types * MNT_NS: Mount namespaces * NET_NS: Network namespaces * USER_NS: User namespaces * etc. Can be OR'd together * @user_ns_id: Filter results to namespaces owned by this user namespace: * 0: Return all namespaces (subject to permission checks) * LISTNS_CURRENT_USER: Namespaces owned by caller's user name= space * Other value: Namespaces owned by the specified user namespa= ce ID */ struct ns_id_req { __u32 size; /* sizeof(struct ns_id_req) */ __u32 spare; /* Reserved, must be 0 */ __u64 ns_id; /* Last seen namespace ID (for pagination) */ __u32 ns_type; /* Filter by namespace type(s) */ __u32 spare2; /* Reserved, must be 0 */ __u64 user_ns_id; /* Filter by owning user namespace */ }; Example 1: List all namespaces void list_all_namespaces(void) { struct ns_id_req req =3D { .size =3D sizeof(req), .ns_id =3D 0, /* Start from beginning */ .ns_type =3D 0, /* All types */ .user_ns_id =3D 0, /* All user namespaces */ }; uint64_t ids[100]; ssize_t ret; printf("All namespaces in the system:\n"); do { ret =3D listns(&req, ids, 100, 0); if (ret < 0) { perror("listns"); break; } for (ssize_t i =3D 0; i < ret; i++) printf(" Namespace ID: %llu\n", (unsigned long long)ids[i]); /* Continue from last seen ID */ if (ret > 0) req.ns_id =3D ids[ret - 1]; } while (ret =3D=3D 100); /* Buffer was full, more may exist */ } Example 2: List network namespaces only void list_network_namespaces(void) { struct ns_id_req req =3D { .size =3D sizeof(req), .ns_id =3D 0, .ns_type =3D NET_NS, /* Only network namespaces */ .user_ns_id =3D 0, }; uint64_t ids[100]; ssize_t ret; ret =3D listns(&req, ids, 100, 0); if (ret < 0) { perror("listns"); return; } printf("Network namespaces: %zd found\n", ret); for (ssize_t i =3D 0; i < ret; i++) printf(" netns ID: %llu\n", (unsigned long long)ids[i]); } Example 3: List namespaces owned by current user namespace void list_owned_namespaces(void) { struct ns_id_req req =3D { .size =3D sizeof(req), .ns_id =3D 0, .ns_type =3D 0, /* All types */ .user_ns_id =3D LISTNS_CURRENT_USER, /* Current userns */ }; uint64_t ids[100]; ssize_t ret; ret =3D listns(&req, ids, 100, 0); if (ret < 0) { perror("listns"); return; } printf("Namespaces owned by my user namespace: %zd\n", ret); for (ssize_t i =3D 0; i < ret; i++) printf(" ns ID: %llu\n", (unsigned long long)ids[i]); } Example 4: List multiple namespace types void list_network_and_mount_namespaces(void) { struct ns_id_req req =3D { .size =3D sizeof(req), .ns_id =3D 0, .ns_type =3D NET_NS | MNT_NS, /* Network and mount */ .user_ns_id =3D 0, }; uint64_t ids[100]; ssize_t ret; ret =3D listns(&req, ids, 100, 0); printf("Network and mount namespaces: %zd found\n", ret); } Example 5: Pagination through large namespace sets void list_all_with_pagination(void) { struct ns_id_req req =3D { .size =3D sizeof(req), .ns_id =3D 0, .ns_type =3D 0, .user_ns_id =3D 0, }; uint64_t ids[50]; size_t total =3D 0; ssize_t ret; printf("Enumerating all namespaces with pagination:\n"); while (1) { ret =3D listns(&req, ids, 50, 0); if (ret < 0) { perror("listns"); break; } if (ret =3D=3D 0) break; /* No more namespaces */ total +=3D ret; printf(" Batch: %zd namespaces\n", ret); /* Last ID in this batch becomes start of next batch */ req.ns_id =3D ids[ret - 1]; if (ret < 50) break; /* Partial batch =3D end of results */ } printf("Total: %zu namespaces\n", total); } Permission Model listns() respects namespace isolation and capabilities: (1) Global listing (user_ns_id =3D 0): - Requires CAP_SYS_ADMIN in the namespace's owning user namespace - OR the namespace must be in the caller's namespace context (e.g., a namespace the caller is currently using) - User namespaces additionally allow listing if the caller has CAP_SYS_ADMIN in that user namespace itself (2) Owner-filtered listing (user_ns_id !=3D 0): - Requires CAP_SYS_ADMIN in the specified owner user namespace - OR the namespace must be in the caller's namespace context - This allows unprivileged processes to enumerate namespaces they own (3) Visibility: - Only "active" namespaces are listed - A namespace is active if it has a non-zero __ns_ref_active count - This includes namespaces used by running processes, held by open file descriptors, or kept active by bind mounts - Inactive namespaces (kept alive only by internal kernel references) are not visible via listns() Signed-off-by: Christian Brauner --- fs/namespace.c | 1 + fs/nsfs.c | 39 ++++ include/linux/ns_common.h | 5 +- include/linux/syscalls.h | 4 + include/linux/user_namespace.h | 4 +- include/uapi/linux/nsfs.h | 44 +++++ init/version-timestamp.c | 1 + ipc/msgutil.c | 1 + kernel/cgroup/cgroup.c | 1 + kernel/nscommon.c | 3 + kernel/nstree.c | 404 +++++++++++++++++++++++++++++++++++++= +++- kernel/pid.c | 1 + kernel/time/namespace.c | 1 + kernel/user.c | 1 + 14 files changed, 503 insertions(+), 7 deletions(-) diff --git a/fs/namespace.c b/fs/namespace.c index d460ca79f0e7..980296b0ec86 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -5996,6 +5996,7 @@ struct mnt_namespace init_mnt_ns =3D { .mounts =3D RB_ROOT, .poll =3D __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll), .ns.ns_list_node =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_unified_lis= t_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_mnt_ns.ns.ns_owner), }; diff --git a/fs/nsfs.c b/fs/nsfs.c index bbef9a49eb37..dab5d2af9de4 100644 --- a/fs/nsfs.c +++ b/fs/nsfs.c @@ -471,6 +471,45 @@ static int nsfs_encode_fh(struct inode *inode, u32 *fh= , int *max_len, return FILEID_NSFS; } =20 +bool is_current_namespace(struct ns_common *ns) +{ + switch (ns->ns_type) { +#ifdef CONFIG_CGROUPS + case CLONE_NEWCGROUP: + return current_in_namespace(to_cg_ns(ns)); +#endif +#ifdef CONFIG_IPC_NS + case CLONE_NEWIPC: + return current_in_namespace(to_ipc_ns(ns)); +#endif + case CLONE_NEWNS: + return current_in_namespace(to_mnt_ns(ns)); +#ifdef CONFIG_NET_NS + case CLONE_NEWNET: + return current_in_namespace(to_net_ns(ns)); +#endif +#ifdef CONFIG_PID_NS + case CLONE_NEWPID: + return current_in_namespace(to_pid_ns(ns)); +#endif +#ifdef CONFIG_TIME_NS + case CLONE_NEWTIME: + return current_in_namespace(to_time_ns(ns)); +#endif +#ifdef CONFIG_USER_NS + case CLONE_NEWUSER: + return current_in_namespace(to_user_ns(ns)); +#endif +#ifdef CONFIG_UTS_NS + case CLONE_NEWUTS: + return current_in_namespace(to_uts_ns(ns)); +#endif + default: + VFS_WARN_ON_ONCE(true); + return false; + } +} + static struct dentry *nsfs_fh_to_dentry(struct super_block *sb, struct fid= *fh, int fh_len, int fh_type) { diff --git a/include/linux/ns_common.h b/include/linux/ns_common.h index 88dce67e06e4..95b3e2aa177d 100644 --- a/include/linux/ns_common.h +++ b/include/linux/ns_common.h @@ -123,8 +123,10 @@ struct ns_common { struct rb_node ns_tree_node; struct list_head ns_list_node; }; - struct /* namespace ownership list */ { + struct /* namespace ownership rbtree and list */ { + struct rb_root ns_owner_tree; /* rbtree of namespaces owned by this na= mespace */ struct list_head ns_owner; /* list of namespaces owned by this namespa= ce */ + struct rb_node ns_owner_tree_node; /* node in the owner namespace's rb= tree */ struct list_head ns_owner_entry; /* node in the owner namespace's ns_o= wned list */ }; atomic_t __ns_ref_active; /* do not use directly */ @@ -133,6 +135,7 @@ struct ns_common { }; }; =20 +bool is_current_namespace(struct ns_common *ns); int __ns_common_init(struct ns_common *ns, u32 ns_type, const struct proc_= ns_operations *ops, int inum); void __ns_common_free(struct ns_common *ns); =20 diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 66c06fcdfe19..cf84d98964b2 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -77,6 +77,7 @@ struct cachestat_range; struct cachestat; struct statmount; struct mnt_id_req; +struct ns_id_req; struct xattr_args; struct file_attr; =20 @@ -437,6 +438,9 @@ asmlinkage long sys_statmount(const struct mnt_id_req _= _user *req, asmlinkage long sys_listmount(const struct mnt_id_req __user *req, u64 __user *mnt_ids, size_t nr_mnt_ids, unsigned int flags); +asmlinkage long sys_listns(const struct ns_id_req __user *req, + u64 __user *ns_ids, size_t nr_ns_ids, + unsigned int flags); asmlinkage long sys_truncate(const char __user *path, long length); asmlinkage long sys_ftruncate(unsigned int fd, off_t length); #if BITS_PER_LONG =3D=3D 32 diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 9a9aebbf96b9..9c3be157397e 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -166,13 +166,13 @@ static inline void set_userns_rlimit_max(struct user_= namespace *ns, ns->rlimit_max[type] =3D max <=3D LONG_MAX ? max : LONG_MAX; } =20 -#ifdef CONFIG_USER_NS - static inline struct user_namespace *to_user_ns(struct ns_common *ns) { return container_of(ns, struct user_namespace, ns); } =20 +#ifdef CONFIG_USER_NS + static inline struct user_namespace *get_user_ns(struct user_namespace *ns) { if (ns) diff --git a/include/uapi/linux/nsfs.h b/include/uapi/linux/nsfs.h index f8bc2aad74d6..a25e38d1c874 100644 --- a/include/uapi/linux/nsfs.h +++ b/include/uapi/linux/nsfs.h @@ -81,4 +81,48 @@ enum init_ns_id { #endif }; =20 +enum ns_type { + TIME_NS =3D (1ULL << 7), /* CLONE_NEWTIME */ + MNT_NS =3D (1ULL << 17), /* CLONE_NEWNS */ + CGROUP_NS =3D (1ULL << 25), /* CLONE_NEWCGROUP */ + UTS_NS =3D (1ULL << 26), /* CLONE_NEWUTS */ + IPC_NS =3D (1ULL << 27), /* CLONE_NEWIPC */ + USER_NS =3D (1ULL << 28), /* CLONE_NEWUSER */ + PID_NS =3D (1ULL << 29), /* CLONE_NEWPID */ + NET_NS =3D (1ULL << 30), /* CLONE_NEWNET */ +}; + +/** + * struct ns_id_req - namespace ID request structure + * @size: size of this structure + * @spare: reserved for future use + * @filter: filter mask + * @ns_id: last namespace id + * @user_ns_id: owning user namespace ID + * + * Structure for passing namespace ID and miscellaneous parameters to + * statns(2) and listns(2). + * + * For statns(2) @param represents the request mask. + * For listns(2) @param represents the last listed mount id (or zero). + */ +struct ns_id_req { + __u32 size; + __u32 spare; + __u64 ns_id; + struct /* listns */ { + __u32 ns_type; + __u32 spare2; + __u64 user_ns_id; + }; +}; + +/* + * Special @user_ns_id value that can be passed to listns() + */ +#define LISTNS_CURRENT_USER 0xffffffffffffffff /* Caller's userns */ + +/* List of all ns_id_req versions. */ +#define NS_ID_REQ_SIZE_VER0 32 /* sizeof first published struct */ + #endif /* __LINUX_NSFS_H */ diff --git a/init/version-timestamp.c b/init/version-timestamp.c index e5c278dabecf..cd6f435d5fde 100644 --- a/init/version-timestamp.c +++ b/init/version-timestamp.c @@ -22,6 +22,7 @@ struct uts_namespace init_uts_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_uts_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_unified_lis= t_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_uts_ns.ns.ns_owner), #ifdef CONFIG_UTS_NS diff --git a/ipc/msgutil.c b/ipc/msgutil.c index ce1de73725c0..3708f325228d 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -32,6 +32,7 @@ struct ipc_namespace init_ipc_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_ipc_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_unified_lis= t_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_ipc_ns.ns.ns_owner), #ifdef CONFIG_IPC_NS diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 41a1fc562ed0..9ab0e7d7b54d 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -258,6 +258,7 @@ struct cgroup_namespace init_cgroup_ns =3D { .root_cset =3D &init_css_set, .ns.ns_type =3D ns_common_type(&init_cgroup_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_unified_= list_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_cgroup_ns.ns.ns_owner), }; diff --git a/kernel/nscommon.c b/kernel/nscommon.c index ba46de0637c3..def79b549c52 100644 --- a/kernel/nscommon.c +++ b/kernel/nscommon.c @@ -62,7 +62,10 @@ int __ns_common_init(struct ns_common *ns, u32 ns_type, = const struct proc_ns_ope ns->ns_type =3D ns_type; RB_CLEAR_NODE(&ns->ns_tree_node); RB_CLEAR_NODE(&ns->ns_unified_tree_node); + RB_CLEAR_NODE(&ns->ns_owner_tree_node); INIT_LIST_HEAD(&ns->ns_list_node); + INIT_LIST_HEAD(&ns->ns_unified_list_node); + ns->ns_owner_tree =3D RB_ROOT; INIT_LIST_HEAD(&ns->ns_owner); INIT_LIST_HEAD(&ns->ns_owner_entry); =20 diff --git a/kernel/nstree.c b/kernel/nstree.c index 829682bb04a1..ea6e292a485e 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -2,11 +2,14 @@ =20 #include #include +#include +#include #include #include =20 __cacheline_aligned_in_smp DEFINE_SEQLOCK(ns_tree_lock); static struct rb_root ns_unified_tree =3D RB_ROOT; /* protected by ns_tree= _lock */ +static LIST_HEAD(ns_unified_list); /* protected by ns_tree_lock */ =20 /** * struct ns_tree - Namespace tree @@ -83,6 +86,13 @@ static inline struct ns_common *node_to_ns_unified(const= struct rb_node *node) return rb_entry(node, struct ns_common, ns_unified_tree_node); } =20 +static inline struct ns_common *node_to_ns_owner(const struct rb_node *nod= e) +{ + if (!node) + return NULL; + return rb_entry(node, struct ns_common, ns_owner_tree_node); +} + static inline int ns_cmp(struct rb_node *a, const struct rb_node *b) { struct ns_common *ns_a =3D node_to_ns(a); @@ -111,6 +121,20 @@ static inline int ns_cmp_unified(struct rb_node *a, co= nst struct rb_node *b) return 0; } =20 +static inline int ns_cmp_owner(struct rb_node *a, const struct rb_node *b) +{ + struct ns_common *ns_a =3D node_to_ns_owner(a); + struct ns_common *ns_b =3D node_to_ns_owner(b); + u64 ns_id_a =3D ns_a->ns_id; + u64 ns_id_b =3D ns_b->ns_id; + + if (ns_id_a < ns_id_b) + return -1; + if (ns_id_a > ns_id_b) + return 1; + return 0; +} + void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree) { struct rb_node *node, *prev; @@ -134,7 +158,13 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns= _tree *ns_tree) else list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node); =20 + /* Add to unified tree and list */ rb_find_add_rcu(&ns->ns_unified_tree_node, &ns_unified_tree, ns_cmp_unifi= ed); + prev =3D rb_prev(&ns->ns_unified_tree_node); + if (!prev) + list_add_rcu(&ns->ns_unified_list_node, &ns_unified_list); + else + list_add_rcu(&ns->ns_unified_list_node, &node_to_ns_unified(prev)->ns_un= ified_list_node); =20 if (ops) { struct user_namespace *user_ns; @@ -144,7 +174,16 @@ void __ns_tree_add_raw(struct ns_common *ns, struct ns= _tree *ns_tree) if (user_ns) { struct ns_common *owner =3D &user_ns->ns; VFS_WARN_ON_ONCE(owner->ns_type !=3D CLONE_NEWUSER); - list_add_tail_rcu(&ns->ns_owner_entry, &owner->ns_owner); + + /* Insert into owner's rbtree */ + rb_find_add_rcu(&ns->ns_owner_tree_node, &owner->ns_owner_tree, ns_cmp_= owner); + + /* Insert into owner's list in sorted order */ + prev =3D rb_prev(&ns->ns_owner_tree_node); + if (!prev) + list_add_rcu(&ns->ns_owner_entry, &owner->ns_owner); + else + list_add_rcu(&ns->ns_owner_entry, &node_to_ns_owner(prev)->ns_owner_en= try); } else { /* Only the initial user namespace doesn't have an owner. */ VFS_WARN_ON_ONCE(ns !=3D to_ns_common(&init_user_ns)); @@ -157,16 +196,36 @@ void __ns_tree_add_raw(struct ns_common *ns, struct n= s_tree *ns_tree) =20 void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree) { + const struct proc_ns_operations *ops =3D ns->ops; + struct user_namespace *user_ns; + VFS_WARN_ON_ONCE(RB_EMPTY_NODE(&ns->ns_tree_node)); VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node)); VFS_WARN_ON_ONCE(ns->ns_type !=3D ns_tree->type); =20 write_seqlock(&ns_tree_lock); rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree); - rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); - list_bidir_del_rcu(&ns->ns_list_node); RB_CLEAR_NODE(&ns->ns_tree_node); - list_bidir_del_rcu(&ns->ns_owner_entry); + + list_bidir_del_rcu(&ns->ns_list_node); + + rb_erase(&ns->ns_unified_tree_node, &ns_unified_tree); + RB_CLEAR_NODE(&ns->ns_unified_tree_node); + + list_bidir_del_rcu(&ns->ns_unified_list_node); + + /* Remove from owner's rbtree if this namespace has an owner */ + if (ops) { + user_ns =3D ops->owner(ns); + if (user_ns) { + struct ns_common *owner =3D &user_ns->ns; + rb_erase(&ns->ns_owner_tree_node, &owner->ns_owner_tree); + RB_CLEAR_NODE(&ns->ns_owner_tree_node); + } + + list_bidir_del_rcu(&ns->ns_owner_entry); + } + write_sequnlock(&ns_tree_lock); } EXPORT_SYMBOL_GPL(__ns_tree_remove); @@ -312,3 +371,340 @@ u64 __ns_tree_gen_id(struct ns_common *ns, u64 id) ns->ns_id =3D atomic64_inc_return(&namespace_cookie); return ns->ns_id; } + +struct klistns { + u64 *kns_ids; + u32 nr_ns_ids; + u64 last_ns_id; + u64 user_ns_id; + u32 ns_type; + struct user_namespace *user_ns; + struct ns_common *first_ns; +}; + +static void __free_klistns_free(const struct klistns *kls) +{ + if (kls->user_ns_id !=3D LISTNS_CURRENT_USER) + put_user_ns(kls->user_ns); + if (kls->first_ns) + kls->first_ns->ops->put(kls->first_ns); + kvfree(kls->kns_ids); +} + +#define NS_ALL (PID_NS | USER_NS | MNT_NS | UTS_NS | IPC_NS | NET_NS | CGR= OUP_NS | TIME_NS) + +static int copy_ns_id_req(const struct ns_id_req __user *req, + struct ns_id_req *kreq) +{ + int ret; + size_t usize; + + BUILD_BUG_ON(sizeof(struct ns_id_req) !=3D NS_ID_REQ_SIZE_VER0); + + ret =3D get_user(usize, &req->size); + if (ret) + return -EFAULT; + if (unlikely(usize > PAGE_SIZE)) + return -E2BIG; + if (unlikely(usize < NS_ID_REQ_SIZE_VER0)) + return -EINVAL; + memset(kreq, 0, sizeof(*kreq)); + ret =3D copy_struct_from_user(kreq, sizeof(*kreq), req, usize); + if (ret) + return ret; + if (kreq->spare !=3D 0) + return -EINVAL; + if (kreq->ns_type & ~NS_ALL) + return -EOPNOTSUPP; + return 0; +} + +static inline int prepare_klistns(struct klistns *kls, struct ns_id_req *k= req, + size_t nr_ns_ids) +{ + kls->last_ns_id =3D kreq->ns_id; + kls->user_ns_id =3D kreq->user_ns_id; + kls->nr_ns_ids =3D nr_ns_ids; + kls->ns_type =3D kreq->ns_type; + + kls->kns_ids =3D kvmalloc_array(nr_ns_ids, sizeof(*kls->kns_ids), + GFP_KERNEL_ACCOUNT); + if (!kls->kns_ids) + return -ENOMEM; + + return 0; +} + +/* + * Lookup a namespace owned by owner with id >=3D ns_id. + * Returns the namespace with the smallest id that is >=3D ns_id. + */ +static struct ns_common *lookup_ns_owner_at(u64 ns_id, struct ns_common *o= wner) +{ + struct ns_common *ret =3D NULL; + struct rb_node *node; + + VFS_WARN_ON_ONCE(owner->ns_type !=3D CLONE_NEWUSER); + + read_seqlock_excl(&ns_tree_lock); + node =3D owner->ns_owner_tree.rb_node; + + while (node) { + struct ns_common *ns =3D node_to_ns_owner(node); + + if (ns_id <=3D ns->ns_id) { + ret =3D ns; + if (ns_id =3D=3D ns->ns_id) + break; + node =3D node->rb_left; + } else { + node =3D node->rb_right; + } + } + + if (ret && !ns_get_unless_inactive(ret)) + ret =3D NULL; + read_sequnlock_excl(&ns_tree_lock); + return ret; +} + +static struct ns_common *lookup_ns_id(u64 mnt_ns_id, int ns_type) +{ + struct ns_common *ns; + + guard(rcu)(); + ns =3D ns_tree_lookup_rcu(mnt_ns_id, ns_type); + if (!ns) + return NULL; + + if (!ns_get_unless_inactive(ns)) + return NULL; + + return ns; +} + +static ssize_t do_listns_userns(struct klistns *kls) +{ + u64 *ns_ids =3D kls->kns_ids; + size_t nr_ns_ids =3D kls->nr_ns_ids; + struct ns_common *ns =3D NULL, *first_ns =3D NULL; + const struct list_head *head; + bool userns_capable; + ssize_t ret; + + VFS_WARN_ON_ONCE(!kls->user_ns_id); + + if (kls->user_ns_id =3D=3D LISTNS_CURRENT_USER) + ns =3D to_ns_common(current_user_ns()); + else if (kls->user_ns_id) + ns =3D lookup_ns_id(kls->user_ns_id, CLONE_NEWUSER); + if (!ns) + return -EINVAL; + kls->user_ns =3D to_user_ns(ns); + + /* + * Use the rbtree to find the first namespace we care about and + * then use it's list entry to iterate from there. + */ + if (kls->last_ns_id) { + kls->first_ns =3D lookup_ns_owner_at(kls->last_ns_id + 1, ns); + if (!kls->first_ns) + return -ENOENT; + first_ns =3D kls->first_ns; + } + + ret =3D 0; + head =3D &to_ns_common(kls->user_ns)->ns_owner; + userns_capable =3D ns_capable_noaudit(kls->user_ns, CAP_SYS_ADMIN); + guard(rcu)(); + if (!first_ns) + first_ns =3D list_entry_rcu(head->next, typeof(*ns), ns_owner_entry); + for (ns =3D first_ns; &ns->ns_owner_entry !=3D head && nr_ns_ids; + ns =3D list_entry_rcu(ns->ns_owner_entry.next, typeof(*ns), ns_owner= _entry)) { + if (kls->ns_type && !(kls->ns_type & ns->ns_type)) + continue; + if (!__ns_ref_active_read(ns)) + continue; + if (!userns_capable && !is_current_namespace(ns) && + ((ns->ns_type !=3D CLONE_NEWUSER) || + !ns_capable_noaudit(to_user_ns(ns), CAP_SYS_ADMIN))) + continue; + *ns_ids =3D ns->ns_id; + ns_ids++; + nr_ns_ids--; + ret++; + } + + return ret; +} + +/* + * Lookup a namespace with id >=3D ns_id in either the unified tree or a t= ype-specific tree. + * Returns the namespace with the smallest id that is >=3D ns_id. + */ +static struct ns_common *lookup_ns_id_at(u64 ns_id, int ns_type) +{ + struct ns_common *ret =3D NULL; + struct ns_tree *ns_tree =3D NULL; + struct rb_node *node; + + if (ns_type) { + ns_tree =3D ns_tree_from_type(ns_type); + if (!ns_tree) + return NULL; + } + + read_seqlock_excl(&ns_tree_lock); + if (ns_tree) + node =3D ns_tree->ns_tree.rb_node; + else + node =3D ns_unified_tree.rb_node; + + while (node) { + struct ns_common *ns; + + if (ns_type) + ns =3D node_to_ns(node); + else + ns =3D node_to_ns_unified(node); + + if (ns_id <=3D ns->ns_id) { + if (ns_type) + ret =3D node_to_ns(node); + else + ret =3D node_to_ns_unified(node); + if (ns_id =3D=3D ns->ns_id) + break; + node =3D node->rb_left; + } else { + node =3D node->rb_right; + } + } + + if (ret && !ns_get_unless_inactive(ret)) + ret =3D NULL; + read_sequnlock_excl(&ns_tree_lock); + return ret; +} + +static inline struct ns_common *first_ns_common(const struct list_head *he= ad, + struct ns_tree *ns_tree) +{ + if (ns_tree) + return list_entry_rcu(head->next, struct ns_common, ns_list_node); + return list_entry_rcu(head->next, struct ns_common, ns_unified_list_node); +} + +static inline struct ns_common *next_ns_common(struct ns_common *ns, + struct ns_tree *ns_tree) +{ + if (ns_tree) + return list_entry_rcu(ns->ns_list_node.next, struct ns_common, ns_list_n= ode); + return list_entry_rcu(ns->ns_unified_list_node.next, struct ns_common, ns= _unified_list_node); +} + +static inline bool ns_common_is_head(struct ns_common *ns, + const struct list_head *head, + struct ns_tree *ns_tree) +{ + if (ns_tree) + return &ns->ns_list_node =3D=3D head; + return &ns->ns_unified_list_node =3D=3D head; +} + +static ssize_t do_listns(struct klistns *kls) +{ + u64 *ns_ids =3D kls->kns_ids; + size_t nr_ns_ids =3D kls->nr_ns_ids; + struct ns_common *ns, *first_ns =3D NULL; + struct ns_tree *ns_tree =3D NULL; + const struct list_head *head; + struct user_namespace *user_ns; + ssize_t ret; + + if (hweight32(kls->ns_type) =3D=3D 1) { + ns_tree =3D ns_tree_from_type(kls->ns_type); + if (!ns_tree) + return -EINVAL; + } + + if (kls->last_ns_id) { + kls->first_ns =3D lookup_ns_id_at(kls->last_ns_id + 1, 0); + if (!kls->first_ns) + return -ENOENT; + first_ns =3D kls->first_ns; + } + + ret =3D 0; + if (ns_tree) + head =3D &ns_tree->ns_list; + else + head =3D &ns_unified_list; + + guard(rcu)(); + if (!first_ns) + first_ns =3D first_ns_common(head, ns_tree); + + for (ns =3D first_ns; !ns_common_is_head(ns, head, ns_tree) && nr_ns_ids; + ns =3D next_ns_common(ns, ns_tree)) { + if (kls->ns_type && !(kls->ns_type & ns->ns_type)) + continue; + if (!__ns_ref_active_read(ns)) + continue; + /* Check permissions */ + if (!ns->ops) + user_ns =3D NULL; + else + user_ns =3D ns->ops->owner(ns); + if (!user_ns) + user_ns =3D &init_user_ns; + if (!ns_capable_noaudit(user_ns, CAP_SYS_ADMIN) && + !is_current_namespace(ns) && + ((ns->ns_type !=3D CLONE_NEWUSER) || + !ns_capable_noaudit(to_user_ns(ns), CAP_SYS_ADMIN))) + continue; + *ns_ids++ =3D ns->ns_id; + nr_ns_ids--; + ret++; + } + + return ret; +} + +SYSCALL_DEFINE4(listns, const struct ns_id_req __user *, req, + u64 __user *, ns_ids, size_t, nr_ns_ids, unsigned int, flags) +{ + struct klistns klns __free(klistns_free) =3D {}; + const size_t maxcount =3D 1000000; + struct ns_id_req kreq; + ssize_t ret; + + if (flags) + return -EINVAL; + + if (unlikely(nr_ns_ids > maxcount)) + return -EOVERFLOW; + + if (!access_ok(ns_ids, nr_ns_ids * sizeof(*ns_ids))) + return -EFAULT; + + ret =3D copy_ns_id_req(req, &kreq); + if (ret) + return ret; + + ret =3D prepare_klistns(&klns, &kreq, nr_ns_ids); + if (ret) + return ret; + + if (kreq.user_ns_id) + ret =3D do_listns_userns(&klns); + else + ret =3D do_listns(&klns); + if (ret <=3D 0) + return ret; + + if (copy_to_user(ns_ids, klns.kns_ids, ret * sizeof(*ns_ids))) + return -EFAULT; + + return ret; +} diff --git a/kernel/pid.c b/kernel/pid.c index f82dab348540..a1bfb2924476 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -80,6 +80,7 @@ struct pid_namespace init_pid_ns =3D { .user_ns =3D &init_user_ns, .ns.inum =3D ns_init_inum(&init_pid_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_unified_lis= t_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_pid_ns.ns.ns_owner), #ifdef CONFIG_PID_NS diff --git a/kernel/time/namespace.c b/kernel/time/namespace.c index 15cb74267c75..acbeec049263 100644 --- a/kernel/time/namespace.c +++ b/kernel/time/namespace.c @@ -489,6 +489,7 @@ struct time_namespace init_time_ns =3D { .ns.ns_owner =3D LIST_HEAD_INIT(init_time_ns.ns.ns_owner), .frozen_offsets =3D true, .ns.ns_list_node =3D LIST_HEAD_INIT(init_time_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_time_ns.ns.ns_unified_li= st_node), }; =20 void __init time_ns_init(void) diff --git a/kernel/user.c b/kernel/user.c index e392768ccd44..68fe16617d38 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -72,6 +72,7 @@ struct user_namespace init_user_ns =3D { .group =3D GLOBAL_ROOT_GID, .ns.inum =3D ns_init_inum(&init_user_ns), .ns.ns_list_node =3D LIST_HEAD_INIT(init_user_ns.ns.ns_list_node), + .ns.ns_unified_list_node =3D LIST_HEAD_INIT(init_user_ns.ns.ns_unified_li= st_node), .ns.ns_owner_entry =3D LIST_HEAD_INIT(init_user_ns.ns.ns_owner_entry), .ns.ns_owner =3D LIST_HEAD_INIT(init_user_ns.ns.ns_owner), #ifdef CONFIG_USER_NS --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 B663A285CB4; Wed, 22 Oct 2025 16:07:36 +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=1761149256; cv=none; b=qkHC8GJLYuaUQ228wNUDZY9xstf/D6EgcVT/iNoW4K3ALfb2HszI01/Cq5AoW2pbG4VeJhaHvdyUhmujOP3SPJiBoNappxSG2yKuYXhNZeU6UHEzlPKcOWMUSaxBDOkgCONem86u/RUdN5MFaJA5DRK+XF54IKVrS/eXUNkhudU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149256; c=relaxed/simple; bh=tRwqy5SwFVniPr5V+qBsta76Evy4Uws4vCbVqOZukQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KBORMwSKc1Pb8vguDg8FdYx3UF20jJDtGC4wN/SLEG3SDj0Q8EXVAIA43gAYwRi/luJKlYqRa8U1VaI1Xs+UzwJS40/9uwore11mMgJ82jR8rTbtB3vmlfcTzbhseQWubI1DMD3UhHuAmk4D4cX+PWl56eF/ihQ8Tk5wesg9I0w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b+aNE0Dl; 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="b+aNE0Dl" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 634FDC4CEFD; Wed, 22 Oct 2025 16:07:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149256; bh=tRwqy5SwFVniPr5V+qBsta76Evy4Uws4vCbVqOZukQo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=b+aNE0DlatGvJ8lmCQu0Om50TyVurq2vO5/rYdq6ZezPwFXQk2QqgjlDIEVVUpnnN p22X2nrUlrVFWmAQqhgbr081KHeu6JwQuuhkphJR3E4HkE9cI/+l8xNqJwtTF2kFk3 /BRqOqmq84wlPqRoc0uvEn5CaxB9Qfph11ucfCr2OVaZzTsA3AALD7NC1uToKQTZv1 BwEh89kir8EyMyec+DuZX+7ffNJzVZOo1wrQUEihoHeMdIsPSSowQBRqZXAKIG0dFf SmIrzYnl7lTzURkUBggmUppQC4K7js/c7nb81/JJRJwHGdgRPrKlV23YdR+Dcph9Ki e9Eftjd1FVFOA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:55 +0200 Subject: [PATCH v2 17/63] arch: hookup listns() system call Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-17-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=8895; i=brauner@kernel.org; h=from:subject:message-id; bh=tRwqy5SwFVniPr5V+qBsta76Evy4Uws4vCbVqOZukQo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi67L3LLa68C7u22zk+nyN08J99sL2A3jv3BO1df NfkZ/6R7ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiIrwbD/5rNCszfzB9IZDOp h177HX78m+jCo3Y17D9ON+1mM0tsVGL4K1YXuWTOqmPlDlGlvQoN23f+XVH2SSu3bcs5/ZVLA8M buQE= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add the listns() system call to all architectures. Signed-off-by: Christian Brauner --- arch/alpha/kernel/syscalls/syscall.tbl | 1 + arch/arm/tools/syscall.tbl | 1 + arch/arm64/tools/syscall_32.tbl | 1 + arch/m68k/kernel/syscalls/syscall.tbl | 1 + arch/microblaze/kernel/syscalls/syscall.tbl | 1 + arch/mips/kernel/syscalls/syscall_n32.tbl | 1 + arch/mips/kernel/syscalls/syscall_n64.tbl | 1 + arch/mips/kernel/syscalls/syscall_o32.tbl | 1 + arch/parisc/kernel/syscalls/syscall.tbl | 1 + arch/powerpc/kernel/syscalls/syscall.tbl | 1 + arch/s390/kernel/syscalls/syscall.tbl | 1 + arch/sh/kernel/syscalls/syscall.tbl | 1 + arch/sparc/kernel/syscalls/syscall.tbl | 1 + arch/x86/entry/syscalls/syscall_32.tbl | 1 + arch/x86/entry/syscalls/syscall_64.tbl | 1 + arch/xtensa/kernel/syscalls/syscall.tbl | 1 + include/uapi/asm-generic/unistd.h | 4 +++- scripts/syscall.tbl | 1 + 18 files changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/alpha/kernel/syscalls/syscall.tbl b/arch/alpha/kernel/sys= calls/syscall.tbl index 16dca28ebf17..3fed97478058 100644 --- a/arch/alpha/kernel/syscalls/syscall.tbl +++ b/arch/alpha/kernel/syscalls/syscall.tbl @@ -509,3 +509,4 @@ 577 common open_tree_attr sys_open_tree_attr 578 common file_getattr sys_file_getattr 579 common file_setattr sys_file_setattr +580 common listns sys_listns diff --git a/arch/arm/tools/syscall.tbl b/arch/arm/tools/syscall.tbl index b07e699aaa3c..fd09afae72a2 100644 --- a/arch/arm/tools/syscall.tbl +++ b/arch/arm/tools/syscall.tbl @@ -484,3 +484,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/arm64/tools/syscall_32.tbl b/arch/arm64/tools/syscall_32.= tbl index 8d9088bc577d..8cdfe5d4dac9 100644 --- a/arch/arm64/tools/syscall_32.tbl +++ b/arch/arm64/tools/syscall_32.tbl @@ -481,3 +481,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/m68k/kernel/syscalls/syscall.tbl b/arch/m68k/kernel/sysca= lls/syscall.tbl index f41d38dfbf13..871a5d67bf41 100644 --- a/arch/m68k/kernel/syscalls/syscall.tbl +++ b/arch/m68k/kernel/syscalls/syscall.tbl @@ -469,3 +469,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/microblaze/kernel/syscalls/syscall.tbl b/arch/microblaze/= kernel/syscalls/syscall.tbl index 580af574fe73..022fc85d94b3 100644 --- a/arch/microblaze/kernel/syscalls/syscall.tbl +++ b/arch/microblaze/kernel/syscalls/syscall.tbl @@ -475,3 +475,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/s= yscalls/syscall_n32.tbl index d824ffe9a014..8cedc83c3266 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -408,3 +408,4 @@ 467 n32 open_tree_attr sys_open_tree_attr 468 n32 file_getattr sys_file_getattr 469 n32 file_setattr sys_file_setattr +470 n32 listns sys_listns diff --git a/arch/mips/kernel/syscalls/syscall_n64.tbl b/arch/mips/kernel/s= yscalls/syscall_n64.tbl index 7a7049c2c307..9b92bddf06b5 100644 --- a/arch/mips/kernel/syscalls/syscall_n64.tbl +++ b/arch/mips/kernel/syscalls/syscall_n64.tbl @@ -384,3 +384,4 @@ 467 n64 open_tree_attr sys_open_tree_attr 468 n64 file_getattr sys_file_getattr 469 n64 file_setattr sys_file_setattr +470 n64 listns sys_listns diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/s= yscalls/syscall_o32.tbl index d330274f0601..f810b8a55716 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -457,3 +457,4 @@ 467 o32 open_tree_attr sys_open_tree_attr 468 o32 file_getattr sys_file_getattr 469 o32 file_setattr sys_file_setattr +470 o32 listns sys_listns diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/s= yscalls/syscall.tbl index 88a788a7b18d..39bdacaa530b 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -468,3 +468,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel= /syscalls/syscall.tbl index b453e80dfc00..ec4458cdb97b 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -560,3 +560,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/s390/kernel/syscalls/syscall.tbl b/arch/s390/kernel/sysca= lls/syscall.tbl index 8a6744d658db..5863787ab036 100644 --- a/arch/s390/kernel/syscalls/syscall.tbl +++ b/arch/s390/kernel/syscalls/syscall.tbl @@ -472,3 +472,4 @@ 467 common open_tree_attr sys_open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr sys_file_setattr +470 common listns sys_listns sys_listns diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/= syscall.tbl index 5e9c9eff5539..969c11325ade 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -473,3 +473,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/sys= calls/syscall.tbl index ebb7d06d1044..39aa26b6a50b 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -515,3 +515,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscal= ls/syscall_32.tbl index 4877e16da69a..e979a3eac7a3 100644 --- a/arch/x86/entry/syscalls/syscall_32.tbl +++ b/arch/x86/entry/syscalls/syscall_32.tbl @@ -475,3 +475,4 @@ 467 i386 open_tree_attr sys_open_tree_attr 468 i386 file_getattr sys_file_getattr 469 i386 file_setattr sys_file_setattr +470 i386 listns sys_listns diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscal= ls/syscall_64.tbl index ced2a1deecd7..8a4ac4841be6 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -394,6 +394,7 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns =20 # # Due to a historical design error, certain syscalls are numbered differen= tly diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/s= yscalls/syscall.tbl index 374e4cb788d8..438a3b170402 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -440,3 +440,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/u= nistd.h index 04e0077fb4c9..942370b3f5d2 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -857,9 +857,11 @@ __SYSCALL(__NR_open_tree_attr, sys_open_tree_attr) __SYSCALL(__NR_file_getattr, sys_file_getattr) #define __NR_file_setattr 469 __SYSCALL(__NR_file_setattr, sys_file_setattr) +#define __NR_listns 470 +__SYSCALL(__NR_listns, sys_listns) =20 #undef __NR_syscalls -#define __NR_syscalls 470 +#define __NR_syscalls 471 =20 /* * 32 bit systems traditionally used different diff --git a/scripts/syscall.tbl b/scripts/syscall.tbl index d1ae5e92c615..e74868be513c 100644 --- a/scripts/syscall.tbl +++ b/scripts/syscall.tbl @@ -410,3 +410,4 @@ 467 common open_tree_attr sys_open_tree_attr 468 common file_getattr sys_file_getattr 469 common file_setattr sys_file_setattr +470 common listns sys_listns --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 2CB5734F251; Wed, 22 Oct 2025 16:07: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=1761149262; cv=none; b=tTdA6eyxO6YSEar5Ar7/82G0RxjsYFL78eJmhoyAJQD53jEGU3ed52GsyvjScACZfIsUCvilCvQLrabR5meAcmOMELwiqAiYV0eWrPoOw21BzS6scxTREQRX7/mN0G4AGT3RmBuTQIyh0TEd+f9ZEIq4Wh2zdEKhwMI89yn/Vmc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149262; c=relaxed/simple; bh=1Vbdfejrzu8I2m1UigJuDF0ynX7SsD3EwMJY3zP1DiU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SZEPJZLv0hjqAusXYX8YD7SmtYYKm3fMYyhrsZrjSwgir51ziAlxDCQ9hHF6MBwkt8PiL2MHt9LuKEwAJVt/7h79f+jEzlnevhdejOhH+sb55/HPjSQAs9oLU2z9ZpxKRd9R40B9rvhUCZLLrCKXQvKFmhAIkLF8x0Y+yEruAEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ASBbj6ME; 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="ASBbj6ME" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE8CCC4CEE7; Wed, 22 Oct 2025 16:07:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149261; bh=1Vbdfejrzu8I2m1UigJuDF0ynX7SsD3EwMJY3zP1DiU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ASBbj6MEprXMqyvfD5do/DikYaPNn5tNyzkWEbSE8UhBJzzC1sE6yugIZ+3lEjtMO MR+m6Eh05EGTHKygxm3aNg+8xE2hWy7DYowB2M0tqHUYSV3ao8YyB23p2ZdS25aPI8 jTtETgucd9w+qUdShE2woMEFv3pPS3SQKEuyzbDMr6HwReh4zayNCh7k3MtYbx3Lr3 Wsu0wxh70v1ktKKfdQSpJwSUUx0FRkXpRlkoxX7vF5Fxk1McorOrj50KY3izUn0x6p CRJ09rd2a54vC0d+gXLdZB1kpZamSbSQph4QTfbmtwHldB09nHKSLHyggxUEJF5dom EfRRLbDuSB0MQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:56 +0200 Subject: [PATCH v2 18/63] nsfs: update tools header Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-18-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2616; i=brauner@kernel.org; h=from:subject:message-id; bh=1Vbdfejrzu8I2m1UigJuDF0ynX7SsD3EwMJY3zP1DiU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhqHNZ3mCP+X/OZTSyxx6W4dKaJbjuzIn72+y98w a+3PQ7R6ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIjXCG/0WR/HWRq4tFPEOc q1d1q/ypvLbxt/nUlr7AosapJ3tllRj+2VhJ129abtu4/sOj39x6q+JrdbWeLQrn6HH+xyVy68g aLgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Ensure all the new uapi bits are visible for the selftests. Signed-off-by: Christian Brauner --- tools/include/uapi/linux/nsfs.h | 70 +++++++++++++++++++++++++++++++++++++= ++++ 1 file changed, 70 insertions(+) diff --git a/tools/include/uapi/linux/nsfs.h b/tools/include/uapi/linux/nsf= s.h index 33c9b578b3b2..a25e38d1c874 100644 --- a/tools/include/uapi/linux/nsfs.h +++ b/tools/include/uapi/linux/nsfs.h @@ -53,6 +53,76 @@ enum init_ns_ino { TIME_NS_INIT_INO =3D 0xEFFFFFFAU, NET_NS_INIT_INO =3D 0xEFFFFFF9U, MNT_NS_INIT_INO =3D 0xEFFFFFF8U, +#ifdef __KERNEL__ + MNT_NS_ANON_INO =3D 0xEFFFFFF7U, +#endif }; =20 +struct nsfs_file_handle { + __u64 ns_id; + __u32 ns_type; + __u32 ns_inum; +}; + +#define NSFS_FILE_HANDLE_SIZE_VER0 16 /* sizeof first published struct */ +#define NSFS_FILE_HANDLE_SIZE_LATEST sizeof(struct nsfs_file_handle) /* si= zeof latest published struct */ + +enum init_ns_id { + IPC_NS_INIT_ID =3D 1ULL, + UTS_NS_INIT_ID =3D 2ULL, + USER_NS_INIT_ID =3D 3ULL, + PID_NS_INIT_ID =3D 4ULL, + CGROUP_NS_INIT_ID =3D 5ULL, + TIME_NS_INIT_ID =3D 6ULL, + NET_NS_INIT_ID =3D 7ULL, + MNT_NS_INIT_ID =3D 8ULL, +#ifdef __KERNEL__ + NS_LAST_INIT_ID =3D MNT_NS_INIT_ID, +#endif +}; + +enum ns_type { + TIME_NS =3D (1ULL << 7), /* CLONE_NEWTIME */ + MNT_NS =3D (1ULL << 17), /* CLONE_NEWNS */ + CGROUP_NS =3D (1ULL << 25), /* CLONE_NEWCGROUP */ + UTS_NS =3D (1ULL << 26), /* CLONE_NEWUTS */ + IPC_NS =3D (1ULL << 27), /* CLONE_NEWIPC */ + USER_NS =3D (1ULL << 28), /* CLONE_NEWUSER */ + PID_NS =3D (1ULL << 29), /* CLONE_NEWPID */ + NET_NS =3D (1ULL << 30), /* CLONE_NEWNET */ +}; + +/** + * struct ns_id_req - namespace ID request structure + * @size: size of this structure + * @spare: reserved for future use + * @filter: filter mask + * @ns_id: last namespace id + * @user_ns_id: owning user namespace ID + * + * Structure for passing namespace ID and miscellaneous parameters to + * statns(2) and listns(2). + * + * For statns(2) @param represents the request mask. + * For listns(2) @param represents the last listed mount id (or zero). + */ +struct ns_id_req { + __u32 size; + __u32 spare; + __u64 ns_id; + struct /* listns */ { + __u32 ns_type; + __u32 spare2; + __u64 user_ns_id; + }; +}; + +/* + * Special @user_ns_id value that can be passed to listns() + */ +#define LISTNS_CURRENT_USER 0xffffffffffffffff /* Caller's userns */ + +/* List of all ns_id_req versions. */ +#define NS_ID_REQ_SIZE_VER0 32 /* sizeof first published struct */ + #endif /* __LINUX_NSFS_H */ --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 49F5E337100; Wed, 22 Oct 2025 16:07:47 +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=1761149267; cv=none; b=N7pPgpRG/MHeFDBN6vC54h6Lzn7iFo00Zb1AABGOWrgwtKLcyia9xLRFUEmadzNcxDMjU5TVpstPRExt6C9affhibpnQB7EUuRsBl8FQ1as6HIv5ZnPM7JYM7XuXPdTFfoAr32sUYX5KsORpn9yAsqiRXHufpwq7cu9/kZIJkyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149267; c=relaxed/simple; bh=5c8S8VpHc/7sZMeT1/SbhEW34RvFd3Tre08SPwP5pEQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=R/AWvdmcye7K6GDxRllFPwS4KLroeF5MEhbJyLHUnJZlboscGdNCDJFCXiWPA5dPZ+bFuH2wAcv7oYB+uNKSaiovIMPorBAfJErpyAdULpQUWyk5L+2BmPqAfxTsE7XIHav7SGVKfw9dHs9WFvSX/920WT/C4pv1+7N1LblrcjE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=K4c6vvD3; 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="K4c6vvD3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2D6B4C116B1; Wed, 22 Oct 2025 16:07:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149267; bh=5c8S8VpHc/7sZMeT1/SbhEW34RvFd3Tre08SPwP5pEQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=K4c6vvD3rnSEEu+Jw1oM0YWh9q2imSru6TNaOD++k0VR4cEqbfqFdhNdsKSD/z5uv sIo/aA9cSpR+hHC5zByS/f6h333JchazdC1dcsTCh/L/U+PCVvvFKpKSzME2UWFqbr b/MGv2RES2TBICoiaO/Z9UjSPpWUDNpO7lmeFe1PkQSpreeennSF298tBWh7YHfJZc o6qKBk4vN/6UocTJ+3aRjMf/Zp0FOyMOQezSyWKszW/N3B4csOsS3cu3NunOa/Z1lo 1ddHMHjSqDy+ykRe0yYGksdlzmRlgUWJHgaqd0qybKNUrupn5PaY6OtxA6G2HR+F4E Fxvkk8Fsx6gzg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:57 +0200 Subject: [PATCH v2 19/63] selftests/filesystems: remove CLONE_NEWPIDNS from setup_userns() helper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-19-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=852; i=brauner@kernel.org; h=from:subject:message-id; bh=5c8S8VpHc/7sZMeT1/SbhEW34RvFd3Tre08SPwP5pEQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj6ek9eNou5+ozcXuWy5a+eP93QuyU7N+60cQdL4 NQnJ147d5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzEQZuRYeNnjyTNkMLk5Qd1 Y1aubDc9PMHlUdvPW6q7bYo8VqqE1TAynGoP9WTUm7db5YfcdZVvG3e9ZVXnKyoO0+1+dWSdwPm DPAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 This is effectively unused and doesn't really server any purpose after having reviewed all of the tests that rely on it. Signed-off-by: Christian Brauner --- tools/testing/selftests/filesystems/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/filesystems/utils.c b/tools/testing/se= lftests/filesystems/utils.c index c43a69dffd83..a0c64f415a7f 100644 --- a/tools/testing/selftests/filesystems/utils.c +++ b/tools/testing/selftests/filesystems/utils.c @@ -487,7 +487,7 @@ int setup_userns(void) uid_t uid =3D getuid(); gid_t gid =3D getgid(); =20 - ret =3D unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); + ret =3D unshare(CLONE_NEWNS|CLONE_NEWUSER); if (ret) { ksft_exit_fail_msg("unsharing mountns and userns: %s\n", strerror(errno)); --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 3275626FDB6; Wed, 22 Oct 2025 16:07: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=1761149273; cv=none; b=nJtGZglmwNbqirUooozD5yvg0ZlDep4K6B6LN+VuAUh1uBJheK7M3JSaECdCjnxrbWs1todaIuBYAmscQvqZtRYUegwNsvm7Prn5ByJvglkAWc0LUdZkluvccwQTbHFZseISewjwbdh1huMS2L5eP+eBmX6mJQudL6d1zArp5Ok= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149273; c=relaxed/simple; bh=zTxekEdjlVJZprVoI/00FXYGRRSOiQasmJAHzIPasqQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QSyo1f23/NbI1xk6uEs+NXf38NzIj2CQB18F1SYVFOibuRyJh+cRsDGZ+/x0javznZnVpXY+N0vd4NqadocL+PneR0NWmCdikTNWMINqT2vC3a/i3h+6Sr4kvnaoie0TjEaAKsldh9eysjBB9AeL4gFfpiAte/yS0mEHFtPfDX4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qsVmbJR+; 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="qsVmbJR+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9D529C4CEF7; Wed, 22 Oct 2025 16:07:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149272; bh=zTxekEdjlVJZprVoI/00FXYGRRSOiQasmJAHzIPasqQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qsVmbJR+J3SeyoPm5N882n/X4gd93PVWxDult5F1LV1cCZFNWXKJKavxXL7Vkn7VB Dbuo0vmzM0rv6lfFjmAU3y3BQhCp6Gsa4wOPIfiQsamvF0GzgBtmcLMV3TGe/9nlsW Tubor+bRCNlqsJevFTHfbVhCP6fSnH+5/gZoYeqi0SFucr13v/geGoNOEiV8EA9+NP 1Riw65tYccyvDxFOOs9E55oV6mQrzVmd+1raD8lKFNp6ss4XM1onQkd+px4ApGGLQp 6z/u7wwv09TCn0WHbKAhv189eDnf9oB437KdhkVyuY9fi2IB7yb/qVwqO9Lrs/pzkI I1MmuI9se/7eg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:58 +0200 Subject: [PATCH v2 20/63] selftests/namespaces: first active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-20-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3703; i=brauner@kernel.org; h=from:subject:message-id; bh=zTxekEdjlVJZprVoI/00FXYGRRSOiQasmJAHzIPasqQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHja9HHV3/3Soa+Eb3Qpv/S9q31vuVZK1Z2Avm8Nj ZlbXq9e3VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRqF6G/4WOl1bbFghvktQV XRky58kxj/aov/28Gi4CKWn+05q/nmf4w8cS65wVkd6+4kdvfYyp5sEAPX0Z6e8pqx2FvdYKFU7 lAgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that initial namespaces can be reopened via file handle. Initial namespaces should always have a ref count of one from boot. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 5 +- .../selftests/namespaces/ns_active_ref_test.c | 74 ++++++++++++++++++= ++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index ccfb40837a73..100cc5bfef04 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -1,3 +1,4 @@ nsid_test file_handle_test init_ino_test +ns_active_ref_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index 5fe4b3dc07d3..5cea938cdde8 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -1,7 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS +=3D -Wall -O0 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) +LDLIBS +=3D -lcap =20 -TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test +TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test =20 include ../lib.mk =20 +$(OUTPUT)/ns_active_ref_test: ../filesystems/utils.c + diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c new file mode 100644 index 000000000000..21514a537b26 --- /dev/null +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest_harness.h" +#include "../filesystems/utils.h" + +#ifndef FD_NSFS_ROOT +#define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */ +#endif + +/* + * Test that initial namespaces can be reopened via file handle. + * Initial namespaces should have active ref count of 1 from boot. + */ +TEST(init_ns_always_active) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd1, fd2; + struct stat st1, st2; + + handle =3D malloc(sizeof(*handle) + MAX_HANDLE_SZ); + ASSERT_NE(handle, NULL); + + /* Open initial network namespace */ + fd1 =3D open("/proc/1/ns/net", O_RDONLY); + ASSERT_GE(fd1, 0); + + /* Get file handle for initial namespace */ + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd1, "", handle, &mount_id, AT_EMPTY_PATH); + if (ret < 0 && errno =3D=3D EOPNOTSUPP) { + SKIP(free(handle); close(fd1); + return, "nsfs doesn't support file handles"); + } + ASSERT_EQ(ret, 0); + + /* Close the namespace fd */ + close(fd1); + + /* Try to reopen via file handle - should succeed since init ns is always= active */ + fd2 =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd2 < 0 && (errno =3D=3D EINVAL || errno =3D=3D EOPNOTSUPP)) { + SKIP(free(handle); + return, "open_by_handle_at with FD_NSFS_ROOT not supported"); + } + ASSERT_GE(fd2, 0); + + /* Verify we opened the same namespace */ + fd1 =3D open("/proc/1/ns/net", O_RDONLY); + ASSERT_GE(fd1, 0); + ASSERT_EQ(fstat(fd1, &st1), 0); + ASSERT_EQ(fstat(fd2, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + + close(fd1); + close(fd2); + free(handle); +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 7B23426E6F6; Wed, 22 Oct 2025 16:07: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=1761149278; cv=none; b=lziqkH6qiAqekurSdaAOXYYxhnD92SRlmvpM+awZvFmJlIxzTvaLWA/2/0R+g9HWYF9sJOgdoAyOOxws2iawzirzObS/8HbLecRyUZ+L37ssSCXj37/LX/dlhivmnmZt2ylJZfdYb04m2Phwslx/oKcNPoiRHFwwTeBOFJeYaK4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149278; c=relaxed/simple; bh=Pa0j7tNfgc1/Tkfnlhd7s6hsezXzZgIe91NhoiJaauI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Upefj+kqBaPpaNf4jhLOjDcd0d62K9eNIBeiueDobP5LrsLNr613Iy2U2+ojS72JrdVGyzx2LG1VW9mpeLiAxTR5Z5IMBrD5fWhl9LOwUh7BhPt45vDMwLL551Py/PFaL/ejV50JNV1XuXTAW+o8UWboQqeoiK3MArm7v/4VRfc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QQjDMdbz; 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="QQjDMdbz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F379C4CEE7; Wed, 22 Oct 2025 16:07:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149278; bh=Pa0j7tNfgc1/Tkfnlhd7s6hsezXzZgIe91NhoiJaauI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QQjDMdbzEwKGXJiY+cHxrNTjn6KaXW673nKh0n8PGNiubJx5CGidkTXnktMaL3HWN TQjNNUDkl2FSz1uH5DicBVBYg81ueSlK0Lb2zI1e/00aSdU3obmHY/KX+SCUyqMXHN lN0+8y535zn9yVGc7BhkvPhEKklTC5Mon5mf8dKcPoUMupwI6RJtH4koIqetm/7OJN l3nLphdwsOBMn0WGOYP6l7E91EUhNkRrStj//XSGbjHS7QZVRz/wuQfr9TyhB78s83 gfiPALHZOaUBaK+RDj6q8tMpbb2v+ffOSfKO05fRYWoHJFxehLP3tF1XTIDf5cLnBo KTxWJqWN5tIwQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:05:59 +0200 Subject: [PATCH v2 21/63] selftests/namespaces: second active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-21-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2999; i=brauner@kernel.org; h=from:subject:message-id; bh=Pa0j7tNfgc1/Tkfnlhd7s6hsezXzZgIe91NhoiJaauI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjqf/ipcFKW1pEjW4J2NslVzjE0mqFcc2NO+Oml5 5e6xnWGd5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExEKZ3hn61MVEdpaGXtPPOp Kh6VnRdU7oTXP9KTTnn36Zz/Zm+2akaGY36yHxKUJm/WnewmPvF9SHKz1fVM3f2nLk6c/Kpsd2w rBwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test namespace lifecycle: create a namespace in a child process, get a file handle while it's active, then try to reopen after the process exits (namespace becomes inactive). Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 89 ++++++++++++++++++= ++++ 1 file changed, 89 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 21514a537b26..f628b4a4a927 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -71,4 +71,93 @@ TEST(init_ns_always_active) free(handle); } =20 +/* + * Test namespace lifecycle: create a namespace in a child process, + * get a file handle while it's active, then try to reopen after + * the process exits (namespace becomes inactive). + */ +TEST(ns_inactive_after_exit) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd; + int pipefd[2]; + pid_t pid; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + + /* Create pipe for passing file handle from child */ + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + + /* Create new network namespace */ + ret =3D unshare(CLONE_NEWNET); + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* Open our new namespace */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get file handle for the namespace */ + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH); + close(fd); + + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* Send handle to parent */ + write(pipefd[1], buf, sizeof(*handle) + handle->handle_bytes); + close(pipefd[1]); + + /* Exit - namespace should become inactive */ + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + /* Read file handle from child */ + ret =3D read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to create namespace or get handle"); + } + + ASSERT_GT(ret, 0); + handle =3D (struct file_handle *)buf; + + /* Try to reopen namespace - should fail with ENOENT since it's inactive = */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd >=3D 0) { + /* Namespace is still active - this could happen if cleanup is slow */ + TH_LOG("Warning: Namespace still active after process exit"); + close(fd); + } else { + /* Should fail with ENOENT (namespace inactive) or ESTALE */ + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 9129D355054; Wed, 22 Oct 2025 16:08:03 +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=1761149283; cv=none; b=QyhhnXuJbz/kWfU8TbtBspSL4Lh9290xvbfQ3M1/i31V7cqDWJ2WG3OQMksVlMFL8FKR9+2d00ZnlzwRluvxZydBb4hsUiZpIyzHGeuqdIgaNGropcbaq1JJvLczlAbqp7p1cLlUhuVT8ux1n7isUChtO9IeCU3poST6VRvTrvQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149283; c=relaxed/simple; bh=RDvCp753eytqBU6RSu1QM6e320xY8EyidsVLpCI0zLo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ck2tFpbFhPkgESr8HGLGrW4UgMz36slXkjaJ7SvbTzHxEGnjcRvgWiDEmKfqejRiJr9gzOUffeRTcXz7+9PJmnZKCY7FPTt04hZj3WplpC1Ei1HHabtK0MNRnTjFZfWNOTlhwT92QpzpF8vHquXR5RP5ceoyY6LVzfYnQ/VjWRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tnHPE4jF; 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="tnHPE4jF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 758ECC4CEF7; Wed, 22 Oct 2025 16:07:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149283; bh=RDvCp753eytqBU6RSu1QM6e320xY8EyidsVLpCI0zLo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tnHPE4jFZvB5N7V43VxXppjBy+8iiRcTHfhpTfa3gt7aiiTyPz3/m8072r4L+Fae5 KFNOKs4jWOvGw/dHWFN3xj6yxE/rIezvHqTTS9JDtbE1/oetgZVnyLbffs8DLfHeX0 s8VeU6EUBHea2hIDvmd/+AOxWv2q66xyZ7/yDjFqxQjemYDfYbTnWlWmh5aEHCMmzu 0G0cqLEQmUGeokCpenHazvCjstsggu7NuwlXfB/d283mEF/lQ01oQrnnyOhu4QstCL juYs3ViMEZuVINCXL4kCAkd/alBnHWolydB0SjqNkO/S+XiT59WnyL4Z9uSHQHo6G3 8j4/zTcp4ErsA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:00 +0200 Subject: [PATCH v2 22/63] selftests/namespaces: third active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-22-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3662; i=brauner@kernel.org; h=from:subject:message-id; bh=RDvCp753eytqBU6RSu1QM6e320xY8EyidsVLpCI0zLo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj6O6+2nMc5/pjx8/QXFznK1t1t4bZlyn8nv8xRv kt6vpxCRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwERWv2dkeJvVFtfTKSEp9l1A dp56b0or7zF+gZeLlGfV921sTK3PY2SYfXvXtF8HZ38T5Kj7cOzW+nOcx15/X5i67Kth1gKTjhA 1BgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that a namespace remains active while a process is using it, even after the creating process exits. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 128 +++++++++++++++++= ++++ 1 file changed, 128 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index f628b4a4a927..63233f22517a 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -160,4 +160,132 @@ TEST(ns_inactive_after_exit) } } =20 +/* + * Test that a namespace remains active while a process is using it, + * even after the creating process exits. + */ +TEST(ns_active_with_multiple_processes) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd; + int pipefd[2]; + int syncpipe[2]; + pid_t pid1, pid2; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + char sync_byte; + + /* Create pipes for communication */ + ASSERT_EQ(pipe(pipefd), 0); + ASSERT_EQ(pipe(syncpipe), 0); + + pid1 =3D fork(); + ASSERT_GE(pid1, 0); + + if (pid1 =3D=3D 0) { + /* First child - creates namespace */ + close(pipefd[0]); + close(syncpipe[1]); + + /* Create new network namespace */ + ret =3D unshare(CLONE_NEWNET); + if (ret < 0) { + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + + /* Open and get handle */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH); + close(fd); + + if (ret < 0) { + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + + /* Send handle to parent */ + write(pipefd[1], buf, sizeof(*handle) + handle->handle_bytes); + close(pipefd[1]); + + /* Wait for signal before exiting */ + read(syncpipe[0], &sync_byte, 1); + close(syncpipe[0]); + exit(0); + } + + /* Parent reads handle */ + close(pipefd[1]); + ret =3D read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + ASSERT_GT(ret, 0); + + handle =3D (struct file_handle *)buf; + + /* Create second child that will keep namespace active */ + pid2 =3D fork(); + ASSERT_GE(pid2, 0); + + if (pid2 =3D=3D 0) { + /* Second child - reopens the namespace */ + close(syncpipe[0]); + close(syncpipe[1]); + + /* Open the namespace via handle */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd < 0) { + exit(1); + } + + /* Join the namespace */ + ret =3D setns(fd, CLONE_NEWNET); + close(fd); + if (ret < 0) { + exit(1); + } + + /* Sleep to keep namespace active */ + sleep(1); + exit(0); + } + + /* Let second child enter the namespace */ + usleep(100000); /* 100ms */ + + /* Signal first child to exit */ + close(syncpipe[0]); + sync_byte =3D 'X'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + + /* Wait for first child */ + waitpid(pid1, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + /* Namespace should still be active because second child is using it */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd < 0) { + /* If this fails, second child might not have entered namespace yet */ + TH_LOG("Warning: Could not reopen namespace (errno=3D%d)", errno); + } else { + close(fd); + } + + /* Wait for second child */ + waitpid(pid2, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 D74793570D4; Wed, 22 Oct 2025 16:08:08 +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=1761149289; cv=none; b=Wjkq80+endRQZca6sD6/ElPwTO3scN6vnj24EPEYTKgeR2d05EPbspX17NqSsUeY/5gVP8/Q16kqZI48aB9pAHgFxfjTF6oecNdMhp/dqZMEkn7nRN8hD+FtB9fOa3i1ss4rr+I+bjoqD180GZBHrfo+6j0iRXFQhaPWlCCkhjw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149289; c=relaxed/simple; bh=Xovo3cXcUN+Ljmv09mWRu/zdhsZObjVTLb0tW+lNHe8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Vh+uRkq20H1VpBgwKZns3qgH5EE5B2y8d3WgIxjUcy8xnylte2zyfc9GVH1rPV45Fbx+IWj0FCDnw99vMxyhwi/LfVri9u8nTzbyHaZe4OhAwJJanUKU9F38j+VFfXZRJOJSP8fIyUMUbXwCJDm/MHzQw+x5MameE8yhPl9RPkc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BzPJQePA; 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="BzPJQePA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1CABC4CEE7; Wed, 22 Oct 2025 16:08:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149288; bh=Xovo3cXcUN+Ljmv09mWRu/zdhsZObjVTLb0tW+lNHe8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BzPJQePABSnPueXGAVDq9fYA3O9LbAS6qZott+iC9V3L8aJ4uF1B+EutmSHxTaL6j iGwN9fZD/7Wg35uJS4NGFpqbZGzGS2wP5YszC8V9NzBSZvLSkuXgvispr/mjwVfTvy QWWcW5QM+EVV6j7mzycfugYFgXmeHLLpaQ8DcXJtS08tnwALGCL5Jw6gzAyBbg8q+1 BtrghHHfJ889rN5/NDMe/2HBVLoRiPWerJKkioPv42HzdoBdJ5K/RLJ3FIi5oCcQw+ jyotFPGgqLQkWBdOdi8A42CcuIcPdqjyeMf2QTMF4ElroeKnuvQM0z9MYqQ4a88i1/ r6QfA8/Vc78vA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:01 +0200 Subject: [PATCH v2 23/63] selftests/namespaces: fourth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-23-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3057; i=brauner@kernel.org; h=from:subject:message-id; bh=Xovo3cXcUN+Ljmv09mWRu/zdhsZObjVTLb0tW+lNHe8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHia+/mr2gOj+dJ/Xe/5HS9eVNyrN/ef1beu46FrB Ccx3q0S7ihlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIknZGhj9JL/1DZLJe+ivt qdBf1mGzp3rNrvXMXWrKAteOS6dmSzEyfF+oN0le/a4oS4jcz2zTsBLLkJmn3kaUCu3L81OIeuz ACQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test user namespace active ref tracking via credential lifecycle. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 97 ++++++++++++++++++= ++++ 1 file changed, 97 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 63233f22517a..b9836693f5ec 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -288,4 +288,101 @@ TEST(ns_active_with_multiple_processes) ASSERT_TRUE(WIFEXITED(status)); } =20 +/* + * Test user namespace active ref tracking via credential lifecycle + */ +TEST(userns_active_ref_lifecycle) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd; + int pipefd[2]; + pid_t pid; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + + /* Create new user namespace */ + ret =3D unshare(CLONE_NEWUSER); + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* Set up uid/gid mappings */ + int uid_map_fd =3D open("/proc/self/uid_map", O_WRONLY); + int gid_map_fd =3D open("/proc/self/gid_map", O_WRONLY); + int setgroups_fd =3D open("/proc/self/setgroups", O_WRONLY); + + if (uid_map_fd >=3D 0 && gid_map_fd >=3D 0 && setgroups_fd >=3D 0) { + write(setgroups_fd, "deny", 4); + close(setgroups_fd); + + char mapping[64]; + snprintf(mapping, sizeof(mapping), "0 %d 1", getuid()); + write(uid_map_fd, mapping, strlen(mapping)); + close(uid_map_fd); + + snprintf(mapping, sizeof(mapping), "0 %d 1", getgid()); + write(gid_map_fd, mapping, strlen(mapping)); + close(gid_map_fd); + } + + /* Get file handle */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH); + close(fd); + + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* Send handle to parent */ + write(pipefd[1], buf, sizeof(*handle) + handle->handle_bytes); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + ret =3D read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to create user namespace"); + } + + ASSERT_GT(ret, 0); + handle =3D (struct file_handle *)buf; + + /* Namespace should be inactive after all tasks exit */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd >=3D 0) { + TH_LOG("Warning: User namespace still active after process exit"); + close(fd); + } else { + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6D01629992A; Wed, 22 Oct 2025 16:08:14 +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=1761149294; cv=none; b=UVJ/1GyMtc8lKBih2Ae9MDNGxB3emr1yr+GlWXzDbiYhALH8x5CPuEJVUXW/u+3DO8K215Ggp40cGt8Aru0yy86M/Ekzu4+U0VWAvIwMFy3c1czo7LjMcoTPz1KVGjtw3kyfXUTGIG4K2aWpd5oQpAcy8yeBh4caJWD5VoyVZsM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149294; c=relaxed/simple; bh=Hpp75xec5mwn0pm6bwe74NHV8CGVz16jvWJi/wNRADw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kSVmfkJ4i4hRjY9Sd7cAhOPycNZTktTlOCJ7p2S2h7+rZ71OXtjgioGf3ixMPuxtDSIQDVYA+eZzi3Ky2HOH0jZIbIOENKKFUxszcg/KEBF3jYDaDMGBntGIUNjMYmyUXiD3FyFfhB1gcR4PNVT0o+v5t2PFW0tCqApSpelaWWY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rO33dQDZ; 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="rO33dQDZ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 13F22C4CEF7; Wed, 22 Oct 2025 16:08:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149293; bh=Hpp75xec5mwn0pm6bwe74NHV8CGVz16jvWJi/wNRADw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rO33dQDZU+D7JZrRA3L8gPCPs07wyQ1JnOM19SbP/zvOomkZgOWGBFf8q0LbtBh2w ZqVwQjsM2jeOcY0xJ57Sn1MHsr/nFAVq/WAZjorR4hsRWXqIz4fUOLwY4GqsKN6URp ZGxVDt9DWHL3zMaI3PnQjAJRAYXMQWpcsKi4Oah4rgaWcfKsIxDkR5pNTgojx2rOQz ZfMeqAcXdh0fLoG6SVwuxOcz7pxW8EMxjuGtZqED7u7zdH6AkBGlkCLLEce7mjCHko /rBQ8BpCmI/P6SVUNv+X4cxkaWDXm5ZJ1TT3bffjsR8vv5QerLWjYPQaC/8IAWQ7c2 FLTyZgmXDi1Ig== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:02 +0200 Subject: [PATCH v2 24/63] selftests/namespaces: fifth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-24-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2525; i=brauner@kernel.org; h=from:subject:message-id; bh=Hpp75xec5mwn0pm6bwe74NHV8CGVz16jvWJi/wNRADw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjaEHE8eK7Khu/rE8IPHJu8/1lCT6rLtEmdpg/6N M+qvlks2VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjARTyGGv8I6vJy+l06dXBs7 Sbe4O2DO3IKwk+mM3m7z0r9EHjUVX83wV9x66yrtX1Xv2DcJXd1iwbH5zc/SRoV4ddbbuw9cMuX cxwsA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test PID namespace active ref tracking Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 88 ++++++++++++++++++= ++++ 1 file changed, 88 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index b9836693f5ec..66665bd39e9b 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -385,4 +385,92 @@ TEST(userns_active_ref_lifecycle) } } =20 +/* + * Test PID namespace active ref tracking + */ +TEST(pidns_active_ref_lifecycle) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd; + int pipefd[2]; + pid_t pid; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + + /* Create new PID namespace */ + ret =3D unshare(CLONE_NEWPID); + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* Fork to actually enter the PID namespace */ + pid_t child =3D fork(); + if (child < 0) { + close(pipefd[1]); + exit(1); + } + + if (child =3D=3D 0) { + /* Grandchild - in new PID namespace */ + fd =3D open("/proc/self/ns/pid", O_RDONLY); + if (fd < 0) { + exit(1); + } + + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH); + close(fd); + + if (ret < 0) { + exit(1); + } + + /* Send handle to grandparent */ + write(pipefd[1], buf, sizeof(*handle) + handle->handle_bytes); + close(pipefd[1]); + exit(0); + } + + /* Wait for grandchild */ + waitpid(child, NULL, 0); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + ret =3D read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (ret <=3D 0) { + SKIP(return, "Child failed to create PID namespace or get handle"); + } + + handle =3D (struct file_handle *)buf; + + /* Namespace should be inactive after all processes exit */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd >=3D 0) { + TH_LOG("Warning: PID namespace still active after process exit"); + close(fd); + } else { + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6234C36A5FC; Wed, 22 Oct 2025 16:08:19 +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=1761149299; cv=none; b=ceSyr6RhiGjErrgTTAy4tvPFwXI+aulkTUmDarbzGSX8G9SzbZm5808nY0Q6hOUHVeCEc6R75Mps18YKI33nTD5Qse9KgPRQAPYcENv6t4sBGo+KbKWqtUH3gHEF50YAWlFcmvF28M9xzCaCWcoDKXuQpwP7dEU4pG3ESphu9mg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149299; c=relaxed/simple; bh=uOH3CT+OUgM5Z/Sy7CrxJmBWupBsQ4/yDAh+nMm1LYg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Pe3MGjDEJT/ZHkVeLOvU3Cc3G0FYZtGpGmEgQgdMNJjiXoZGxgJ8D9K1R5gO+zt6rvf+U9bBWADCkSjBaVXL1qRsdu74C+S/XU93dqcEij36U9mYxxhZu7LQfDEJz1SpkfmvVuU07ZTMXlfxB4lyA6JHKNhKaaUf2UpVeEFtzA8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BMmlsMME; 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="BMmlsMME" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 59E8CC4CEE7; Wed, 22 Oct 2025 16:08:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149299; bh=uOH3CT+OUgM5Z/Sy7CrxJmBWupBsQ4/yDAh+nMm1LYg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=BMmlsMMEzFa9ooZsqKAPjZFgkYwZmd+L9lKwf9GCzOe5jEcwCGMdUu5RNEZ3B9KwU PnRvlf3MKnGBRfabGhiMSHR9zL8K6E72t2BxeRxhLODKKho3aNmnj1aLG79xb+bCsb rZKM1eMycJKX2ieWM+bxdGqpWMXJFj++4SuL2v82rQ4mwUrr36ZPtLy1GLt8slm2UG gHAja/GPjciPjhkDLergRgRwd+kLc7gkw2qqnmVJy+Yh5pY8wdIqi3svkI6zO5fI+v gw4lmQm9eHFeHshN9P2lVGGbvjsRLjlP8dTTbY71Ax8KKoxQ5VnEQ2VZAYRQnY0ufj h9y6EXgFsmcXg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:03 +0200 Subject: [PATCH v2 25/63] selftests/namespaces: sixth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-25-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6091; i=brauner@kernel.org; h=from:subject:message-id; bh=uOH3CT+OUgM5Z/Sy7CrxJmBWupBsQ4/yDAh+nMm1LYg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi65UXQp4N8qdYXlpws03z1O+KbzPZYg/8Btwyje k74GC5621HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjARraMM/8zOrJKR5O/n8ozb uV9AOVa8Lracbf8X981+nTVz1VJz/RkZbpqZ9Hy8uvGqxrp5rl8tGe7ftbPzjj7O1b6NY9nU40e ZWAE= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that an open file descriptor keeps a namespace active. Even after the creating process exits, the namespace should remain active as long as an fd is held open. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 168 +++++++++++++++++= ++++ 1 file changed, 168 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 66665bd39e9b..dbb1eb8a04b2 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -473,4 +473,172 @@ TEST(pidns_active_ref_lifecycle) } } =20 +/* + * Test that an open file descriptor keeps a namespace active. + * Even after the creating process exits, the namespace should remain + * active as long as an fd is held open. + */ +TEST(ns_fd_keeps_active) +{ + struct file_handle *handle; + int mount_id; + int ret; + int nsfd; + int pipe_child_ready[2]; + int pipe_parent_ready[2]; + pid_t pid; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + char sync_byte; + char proc_path[64]; + + ASSERT_EQ(pipe(pipe_child_ready), 0); + ASSERT_EQ(pipe(pipe_parent_ready), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipe_child_ready[0]); + close(pipe_parent_ready[1]); + + TH_LOG("Child: creating new network namespace"); + + /* Create new network namespace */ + ret =3D unshare(CLONE_NEWNET); + if (ret < 0) { + TH_LOG("Child: unshare(CLONE_NEWNET) failed: %s", strerror(errno)); + close(pipe_child_ready[1]); + close(pipe_parent_ready[0]); + exit(1); + } + + TH_LOG("Child: network namespace created successfully"); + + /* Get file handle for the namespace */ + nsfd =3D open("/proc/self/ns/net", O_RDONLY); + if (nsfd < 0) { + TH_LOG("Child: failed to open /proc/self/ns/net: %s", strerror(errno)); + close(pipe_child_ready[1]); + close(pipe_parent_ready[0]); + exit(1); + } + + TH_LOG("Child: opened namespace fd %d", nsfd); + + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(nsfd, "", handle, &mount_id, AT_EMPTY_PATH); + close(nsfd); + + if (ret < 0) { + TH_LOG("Child: name_to_handle_at failed: %s", strerror(errno)); + close(pipe_child_ready[1]); + close(pipe_parent_ready[0]); + exit(1); + } + + TH_LOG("Child: got file handle (bytes=3D%u)", handle->handle_bytes); + + /* Send file handle to parent */ + ret =3D write(pipe_child_ready[1], buf, sizeof(*handle) + handle->handle= _bytes); + TH_LOG("Child: sent %d bytes of file handle to parent", ret); + close(pipe_child_ready[1]); + + /* Wait for parent to open the fd */ + TH_LOG("Child: waiting for parent to open fd"); + ret =3D read(pipe_parent_ready[0], &sync_byte, 1); + close(pipe_parent_ready[0]); + + TH_LOG("Child: parent signaled (read %d bytes), exiting now", ret); + /* Exit - namespace should stay active because parent holds fd */ + exit(0); + } + + /* Parent process */ + close(pipe_child_ready[1]); + close(pipe_parent_ready[0]); + + TH_LOG("Parent: reading file handle from child"); + + /* Read file handle from child */ + ret =3D read(pipe_child_ready[0], buf, sizeof(buf)); + close(pipe_child_ready[0]); + ASSERT_GT(ret, 0); + handle =3D (struct file_handle *)buf; + + TH_LOG("Parent: received %d bytes, handle size=3D%u", ret, handle->handle= _bytes); + + /* Open the child's namespace while it's still alive */ + snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/net", pid); + TH_LOG("Parent: opening child's namespace at %s", proc_path); + nsfd =3D open(proc_path, O_RDONLY); + if (nsfd < 0) { + TH_LOG("Parent: failed to open %s: %s", proc_path, strerror(errno)); + close(pipe_parent_ready[1]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open child's namespace"); + } + + TH_LOG("Parent: opened child's namespace, got fd %d", nsfd); + + /* Signal child that we have the fd */ + sync_byte =3D 'G'; + write(pipe_parent_ready[1], &sync_byte, 1); + close(pipe_parent_ready[1]); + TH_LOG("Parent: signaled child that we have the fd"); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + close(nsfd); + SKIP(return, "Child failed to create namespace"); + } + + TH_LOG("Child exited, parent holds fd %d to namespace", nsfd); + + /* + * Namespace should still be ACTIVE because we hold an fd. + * We should be able to reopen it via file handle. + */ + TH_LOG("Attempting to reopen namespace via file handle (should succeed - = fd held)"); + int fd2 =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd2 < 0) { + close(nsfd); + TH_LOG("ERROR: Failed to reopen active namespace (fd held): %s (errno=3D= %d)", + strerror(errno), errno); + ASSERT_TRUE(false); + } + + TH_LOG("Successfully reopened namespace via file handle, got fd %d", fd2); + + /* Verify it's the same namespace */ + struct stat st1, st2; + ASSERT_EQ(fstat(nsfd, &st1), 0); + ASSERT_EQ(fstat(fd2, &st2), 0); + TH_LOG("Namespace inodes: nsfd=3D%lu, fd2=3D%lu", st1.st_ino, st2.st_ino); + ASSERT_EQ(st1.st_ino, st2.st_ino); + close(fd2); + + /* Now close the fd - namespace should become inactive */ + TH_LOG("Closing fd %d - namespace should become inactive", nsfd); + close(nsfd); + + /* Now reopening should fail - namespace is inactive */ + TH_LOG("Attempting to reopen namespace via file handle (should fail - ina= ctive)"); + fd2 =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd2 >=3D 0) { + close(fd2); + TH_LOG("ERROR: Namespace still active after closing all fds (fd=3D%d)", = fd2); + } else { + /* Should fail with ENOENT (inactive) or ESTALE (gone) */ + TH_LOG("Reopen failed as expected: %s (errno=3D%d)", strerror(errno), er= rno); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 AF50626FDA8; Wed, 22 Oct 2025 16:08:24 +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=1761149304; cv=none; b=knFn+hjjpHp74dPCZQCvPh/CfFncNu2LH5ZUcsH32ojPlptLGIaVwhaLkBDkoUMadG43we744Ryd2ReKq4y+UNXSP3TS8MuF3ETqflonlTqPK302aD+2AlTJeKtwKCIoGMYb9MmUVn0y6L4TFjjGgB1W1dVSN9Voe9s8NJcAxzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149304; c=relaxed/simple; bh=U3JxLSa2fcjBw06O9/5jwtS8zf3ICC+ECTB2/eqH3P8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gSV5MpowvvdagbDkXrFV2I6Q/jhzWs270+bRocLRUsMB9moSUVftLdP8iUrlEPY6uwpFO9xopAqTFQueyekJ464+NDJBP/8Ri2fCLMhbMd1GvT6Q+mWh7JeJq64ziCxRkPbglQyRTguUi/7DWYyoHQBsK/pas7Fzyq70whdUfwo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=iCWQRMQX; 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="iCWQRMQX" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B2F2AC113D0; Wed, 22 Oct 2025 16:08:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149304; bh=U3JxLSa2fcjBw06O9/5jwtS8zf3ICC+ECTB2/eqH3P8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=iCWQRMQXM7IuDfFkw5tiZuK/Jd6uUVmbrGqG9Uyt85osKEgwloJhqnCsMzvl4OQnk v1lc7VajN2MsM4WQ7LobWubUHEvHGKP7ZOBoHgTh/FENq7btg0an9KjZMvVuuxf6Pg fXjXRmD5BoxoXDXWbFjLZ+B5Mh+Yayc3yx8fOhgF8e2grglFFtJ2RKu3yTP9jKLLHB V2DO1qxEvWTHjPKZOuTi4GEbVrzWaVtskTqMoT+zeV4WZxSk9TxueZAb1Mpvn7bL1a NlFcgJwgGSaysZgIG8G74wKei8o+jUXQd8hah+hqUelA9nKayWdllBrJWB4rmLAi+m tM1vWboCpWaLQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:04 +0200 Subject: [PATCH v2 26/63] selftests/namespaces: seventh active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-26-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=9454; i=brauner@kernel.org; h=from:subject:message-id; bh=U3JxLSa2fcjBw06O9/5jwtS8zf3ICC+ECTB2/eqH3P8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj6bftcedXvyzZOcDc1fnnf8O76zYo9U//sD1o3k W2HKQfb5I5SFgYxLgZZMUUWh3aTcLnlPBWbjTI1YOawMoEMYeDiFICJ2PQxMrwurWG5sO2909dV l3WFTjxq3HbA5PRzTUPnm179Jp/9orYx/C+evih8w0ZOE/X9k2zFi9kYX/9zFXEw+Pf+wYK0zb+ yRFgA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test hierarchical active reference propagation. When a child namespace is active, its owning user namespace should also be active automatically due to hierarchical active reference propagation. This ensures parents are always reachable when children are active. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 242 +++++++++++++++++= ++++ 1 file changed, 242 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index dbb1eb8a04b2..6377f5d72ed9 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -20,6 +20,10 @@ #define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */ #endif =20 +#ifndef FILEID_NSFS +#define FILEID_NSFS 0xf1 +#endif + /* * Test that initial namespaces can be reopened via file handle. * Initial namespaces should have active ref count of 1 from boot. @@ -641,4 +645,242 @@ TEST(ns_fd_keeps_active) } } =20 +/* + * Test hierarchical active reference propagation. + * When a child namespace is active, its owning user namespace should also + * be active automatically due to hierarchical active reference propagatio= n. + * This ensures parents are always reachable when children are active. + */ +TEST(ns_parent_always_reachable) +{ + struct file_handle *parent_handle, *child_handle; + int ret; + int child_nsfd; + int pipefd[2]; + pid_t pid; + int status; + __u64 parent_id, child_id; + char parent_buf[sizeof(*parent_handle) + MAX_HANDLE_SZ]; + char child_buf[sizeof(*child_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + + TH_LOG("Child: creating parent user namespace and setting up mappings"); + + /* Create parent user namespace with mappings */ + ret =3D setup_userns(); + if (ret < 0) { + TH_LOG("Child: setup_userns() for parent failed: %s", strerror(errno)); + close(pipefd[1]); + exit(1); + } + + TH_LOG("Child: parent user namespace created, now uid=3D%d gid=3D%d", ge= tuid(), getgid()); + + /* Get namespace ID for parent user namespace */ + int parent_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (parent_fd < 0) { + TH_LOG("Child: failed to open parent /proc/self/ns/user: %s", strerror(= errno)); + close(pipefd[1]); + exit(1); + } + + TH_LOG("Child: opened parent userns fd %d", parent_fd); + + if (ioctl(parent_fd, NS_GET_ID, &parent_id) < 0) { + TH_LOG("Child: NS_GET_ID for parent failed: %s", strerror(errno)); + close(parent_fd); + close(pipefd[1]); + exit(1); + } + close(parent_fd); + + TH_LOG("Child: got parent namespace ID %llu", (unsigned long long)parent= _id); + + /* Create child user namespace within parent */ + TH_LOG("Child: creating nested child user namespace"); + ret =3D setup_userns(); + if (ret < 0) { + TH_LOG("Child: setup_userns() for child failed: %s", strerror(errno)); + close(pipefd[1]); + exit(1); + } + + TH_LOG("Child: nested child user namespace created, uid=3D%d gid=3D%d", = getuid(), getgid()); + + /* Get namespace ID for child user namespace */ + int child_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (child_fd < 0) { + TH_LOG("Child: failed to open child /proc/self/ns/user: %s", strerror(e= rrno)); + close(pipefd[1]); + exit(1); + } + + TH_LOG("Child: opened child userns fd %d", child_fd); + + if (ioctl(child_fd, NS_GET_ID, &child_id) < 0) { + TH_LOG("Child: NS_GET_ID for child failed: %s", strerror(errno)); + close(child_fd); + close(pipefd[1]); + exit(1); + } + close(child_fd); + + TH_LOG("Child: got child namespace ID %llu", (unsigned long long)child_i= d); + + /* Send both namespace IDs to parent */ + TH_LOG("Child: sending both namespace IDs to parent"); + write(pipefd[1], &parent_id, sizeof(parent_id)); + write(pipefd[1], &child_id, sizeof(child_id)); + close(pipefd[1]); + + TH_LOG("Child: exiting - parent userns should become inactive"); + /* Exit - parent user namespace should become inactive */ + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + TH_LOG("Parent: reading both namespace IDs from child"); + + /* Read both namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &parent_id, sizeof(parent_id)); + if (ret !=3D sizeof(parent_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read parent namespace ID from child"); + } + + ret =3D read(pipefd[0], &child_id, sizeof(child_id)); + close(pipefd[0]); + if (ret !=3D sizeof(child_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read child namespace ID from child"); + } + + TH_LOG("Parent: received parent_id=3D%llu, child_id=3D%llu", + (unsigned long long)parent_id, (unsigned long long)child_id); + + /* Construct file handles from namespace IDs */ + parent_handle =3D (struct file_handle *)parent_buf; + parent_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + parent_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *parent_fh =3D (struct nsfs_file_handle *)parent_= handle->f_handle; + parent_fh->ns_id =3D parent_id; + parent_fh->ns_type =3D 0; + parent_fh->ns_inum =3D 0; + + child_handle =3D (struct file_handle *)child_buf; + child_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + child_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *child_fh =3D (struct nsfs_file_handle *)child_ha= ndle->f_handle; + child_fh->ns_id =3D child_id; + child_fh->ns_type =3D 0; + child_fh->ns_inum =3D 0; + + TH_LOG("Parent: opening child namespace BEFORE child exits"); + + /* Open child namespace while child is still alive to keep it active */ + child_nsfd =3D open_by_handle_at(FD_NSFS_ROOT, child_handle, O_RDONLY); + if (child_nsfd < 0) { + TH_LOG("Failed to open child namespace: %s (errno=3D%d)", strerror(errno= ), errno); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open child namespace"); + } + + TH_LOG("Opened child namespace fd %d", child_nsfd); + + /* Now wait for child to exit */ + TH_LOG("Parent: waiting for child to exit"); + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + close(child_nsfd); + SKIP(return, "Child failed to create namespaces"); + } + + TH_LOG("Child process exited, parent holds fd to child namespace"); + + /* + * With hierarchical active reference propagation: + * Since the child namespace is active (parent process holds fd), + * the parent user namespace should ALSO be active automatically. + * This is because when we took an active reference on the child, + * it propagated up to the owning user namespace. + */ + TH_LOG("Attempting to reopen parent namespace (should SUCCEED - hierarchi= cal propagation)"); + int parent_fd =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONLY= ); + if (parent_fd < 0) { + close(child_nsfd); + TH_LOG("ERROR: Parent namespace inactive despite active child: %s (errno= =3D%d)", + strerror(errno), errno); + TH_LOG("This indicates hierarchical active reference propagation is not = working!"); + ASSERT_TRUE(false); + } + + TH_LOG("SUCCESS: Parent namespace is active (fd=3D%d) due to active child= ", parent_fd); + + /* Verify we can also get parent via NS_GET_USERNS */ + TH_LOG("Verifying NS_GET_USERNS also works"); + int parent_fd2 =3D ioctl(child_nsfd, NS_GET_USERNS); + if (parent_fd2 < 0) { + close(parent_fd); + close(child_nsfd); + TH_LOG("NS_GET_USERNS failed: %s (errno=3D%d)", strerror(errno), errno); + SKIP(return, "NS_GET_USERNS not supported or failed"); + } + + TH_LOG("NS_GET_USERNS succeeded, got parent fd %d", parent_fd2); + + /* Verify both methods give us the same namespace */ + struct stat st1, st2; + ASSERT_EQ(fstat(parent_fd, &st1), 0); + ASSERT_EQ(fstat(parent_fd2, &st2), 0); + TH_LOG("Parent namespace inodes: parent_fd=3D%lu, parent_fd2=3D%lu", st1.= st_ino, st2.st_ino); + ASSERT_EQ(st1.st_ino, st2.st_ino); + + /* + * Close child fd - parent should remain active because we still + * hold direct references to it (parent_fd and parent_fd2). + */ + TH_LOG("Closing child fd - parent should remain active (direct refs held)= "); + close(child_nsfd); + + /* Parent should still be openable */ + TH_LOG("Verifying parent still active via file handle"); + int parent_fd3 =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONL= Y); + if (parent_fd3 < 0) { + close(parent_fd); + close(parent_fd2); + TH_LOG("ERROR: Parent became inactive despite holding fds: %s (errno=3D%= d)", + strerror(errno), errno); + ASSERT_TRUE(false); + } + close(parent_fd3); + + TH_LOG("Closing all fds to parent namespace"); + close(parent_fd); + close(parent_fd2); + + /* Both should now be inactive */ + TH_LOG("Attempting to reopen parent (should fail - inactive, no refs)"); + parent_fd =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONLY); + if (parent_fd >=3D 0) { + close(parent_fd); + TH_LOG("ERROR: Parent namespace still active after closing all fds (fd= =3D%d)", parent_fd); + } else { + TH_LOG("Parent inactive as expected: %s (errno=3D%d)", strerror(errno), = errno); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 8002D3563F3; Wed, 22 Oct 2025 16:08:30 +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=1761149310; cv=none; b=ZZq/VVT3v5Q1aQrG+/ozBWRGldD2hBb8GxUZEt5zgeg4EJn/7cHW2txTxp/ujcOwNOXnqUPHVgxzXO6JtsKuXu9XZ6vFS5RYKhrWEdgxAIEAX1/CrHcNellkJQcl4+CRsdHNv24dsC9nvXISjYdbC1R+ZyxrLoIcR8Yjn73g+jg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149310; c=relaxed/simple; bh=2l+rS6eqHz2E2xHEBSJ9zjxwvPPCR3H2Nll2sPPrQIg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rnx1JtX3rYleTp+oLfGCFUw5T+5mGcp7L5rDbSIDwxnG3Ld18gNSKX2LviCRz9fLaUUKcojB4H/S/XdpyLGUfVvRpIjED6bMMNDK8YSJkWFvaWYX9lNWMkcszin/597RLYOvjTdSlU7ttFchQnnQ5YQDf8V44VYYl/YcTlJQVyQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=VnIokx+p; 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="VnIokx+p" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 22453C4CEE7; Wed, 22 Oct 2025 16:08:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149310; bh=2l+rS6eqHz2E2xHEBSJ9zjxwvPPCR3H2Nll2sPPrQIg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=VnIokx+pmBxulEjSulpYWFGElgVNH5ilBZPm6/oKYnxdjIGHOJkBPNNkmcCOGOoMK Qyrhu4kdWVycpezZwSEttYtSIVhyJlsLXsVNIoF/48x10oux2Y3Cb6sYYbo/+6ySpN GtMa742AQZAV8wFF2Mt7HkvpPGTnhZ+ogWWtTwuxdcROuH8m2XdsmbKITShr0LzG+Q z/MCQCtFRp0Lmnf7hvmSUIWmKW1aquMUUJOSmveRnFSaAefchLY4PDsbFn+PXCBlRB w57+XTG6j/EMAEDRE1MmERqP18QNqMwB189ar9+yYFtvFkQ+7RPIH3q6/1MjBAtyHJ bxYJG74QWaLcQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:05 +0200 Subject: [PATCH v2 27/63] selftests/namespaces: eigth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-27-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3580; i=brauner@kernel.org; h=from:subject:message-id; bh=2l+rS6eqHz2E2xHEBSJ9zjxwvPPCR3H2Nll2sPPrQIg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhaa8r1dP1le7/4eY4Pqm9Pv6b9z45P/XVgTME2j qLzNTGeHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPZupuRYbNkceBF6SN+b659 jBb5+/Pcz52lMxSnbs+Vu3Kgru+e3m+Gv3JF3UIl5Xnca21fhG3leiu2sbNo1qmg1eEVe3nXc6m ZcwIA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that bind mounts keep namespaces in the tree even when inactive Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 126 +++++++++++++++++= ++++ 1 file changed, 126 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 6377f5d72ed9..66c9908d4977 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -883,4 +883,130 @@ TEST(ns_parent_always_reachable) } } =20 +/* + * Test that bind mounts keep namespaces in the tree even when inactive + */ +TEST(ns_bind_mount_keeps_in_tree) +{ + struct file_handle *handle; + int mount_id; + int ret; + int fd; + int pipefd[2]; + pid_t pid; + int status; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + char tmpfile[] =3D "/tmp/ns-test-XXXXXX"; + int tmpfd; + + /* Create temporary file for bind mount */ + tmpfd =3D mkstemp(tmpfile); + if (tmpfd < 0) { + SKIP(return, "Cannot create temporary file"); + } + close(tmpfd); + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + + /* Unshare mount namespace and make mounts private to avoid propagation = */ + ret =3D unshare(CLONE_NEWNS); + if (ret < 0) { + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + ret =3D mount(NULL, "/", NULL, MS_PRIVATE | MS_REC, NULL); + if (ret < 0) { + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + + /* Create new network namespace */ + ret =3D unshare(CLONE_NEWNET); + if (ret < 0) { + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + + /* Bind mount the namespace */ + ret =3D mount("/proc/self/ns/net", tmpfile, NULL, MS_BIND, NULL); + if (ret < 0) { + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + + /* Get file handle */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + umount(tmpfile); + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D MAX_HANDLE_SZ; + ret =3D name_to_handle_at(fd, "", handle, &mount_id, AT_EMPTY_PATH); + close(fd); + + if (ret < 0) { + umount(tmpfile); + close(pipefd[1]); + unlink(tmpfile); + exit(1); + } + + /* Send handle to parent */ + write(pipefd[1], buf, sizeof(*handle) + handle->handle_bytes); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + ret =3D read(pipefd[0], buf, sizeof(buf)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + unlink(tmpfile); + SKIP(return, "Child failed to create namespace or bind mount"); + } + + ASSERT_GT(ret, 0); + handle =3D (struct file_handle *)buf; + + /* + * Namespace should be inactive but still in tree due to bind mount. + * Reopening should fail with ENOENT (inactive) not ESTALE (not in tree). + */ + fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (fd >=3D 0) { + /* Unexpected - namespace shouldn't be active */ + close(fd); + TH_LOG("Warning: Namespace still active"); + } else { + /* Should be ENOENT (inactive) since bind mount keeps it in tree */ + if (errno !=3D ENOENT && errno !=3D ESTALE) { + TH_LOG("Unexpected error: %d", errno); + } + } + + /* Cleanup */ + umount(tmpfile); + unlink(tmpfile); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 A64EA36B977; Wed, 22 Oct 2025 16:08: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=1761149315; cv=none; b=cGFmabwdqnrqWF9KGLv4FgTieFyD7k6gLult11eeNShq4IaQdNRoHaGosyn5DwQDyEdvR3tMFf8RLHonwF1QS8JRp8EgWP48r0fBLCxyHQufiNR43k/D6KYOXCOF1Hi7OX9kIWEJiav74UyvWstOwz5z51ceJD//tS3PF7+kPK8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149315; c=relaxed/simple; bh=BymNUOybDFEecH4odJXIxHYLUKctxSR2IXDi+nRlDH8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YbBvSUD8g+ZboTVshJ6SP19OBA75/ByPqSOACClvZSM4NMj6Wgb7uN2vRe8uTpwwbkvSAemXCStBenfsxJmbo8VtD/hqDaA/QsmuFwegWB9Lm/eebV4Bz+MwmAfIfCkYQmDQjU+jcWIgnwEByzCUE71CzJrTvXCLczyAt2DjWAg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fxN7Qboq; 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="fxN7Qboq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B159C4CEF7; Wed, 22 Oct 2025 16:08:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149315; bh=BymNUOybDFEecH4odJXIxHYLUKctxSR2IXDi+nRlDH8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fxN7QboqMB/uZXmJ33kGh8xT3KXDkja2Ji7IarJw1ahYJyQYGSP44tu+0EetwZ1Dx /HROpWICWz0L5AMX/k6zOAkl7nUnkIltHLyud+x6O0Tq1zl2zIREL/0rb9wI+2yMAo T4z1Oi78tJlzzHioMdWdh0NIqZniBqCSr7We1V0ZKwgzBj7q5oRfKIyp8LUHXn7eBa p2H3iaLhoeoNww4pMsb7kMdkIBskGguoBxMEMJPcPXxNixBYyUg2TFCb7VY4AToGFb WN5mQstWr3pTTWdvNg9AmSs7GRZLNYfPSQt4TfoU4ReNqBObWvlBEHicyLIhCCD+vl 0QwpAast1/8vw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:06 +0200 Subject: [PATCH v2 28/63] selftests/namespaces: ninth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-28-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5259; i=brauner@kernel.org; h=from:subject:message-id; bh=BymNUOybDFEecH4odJXIxHYLUKctxSR2IXDi+nRlDH8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg6Q3tvWgTLrKcf10drXNx1QcM009k8MarQ6imnU 8v3xQ5/O0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACbyvZPhf5rR4QcyTBJlvGlz pnHdOs7sxHtxVfPbbwofPlxyOFEkOJGR4aUj5ytGrrr3yle7rViTA7ldTi6TWXPYy/FkMvfiG5F 3GQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test multi-level hierarchy (3+ levels deep). Grandparent =E2=86=92 Parent =E2=86=92 Child When child is active, both parent AND grandparent should be active. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 167 +++++++++++++++++= ++++ 1 file changed, 167 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 66c9908d4977..87b435b64b45 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1009,4 +1009,171 @@ TEST(ns_bind_mount_keeps_in_tree) unlink(tmpfile); } =20 +/* + * Test multi-level hierarchy (3+ levels deep). + * Grandparent =E2=86=92 Parent =E2=86=92 Child + * When child is active, both parent AND grandparent should be active. + */ +TEST(ns_multilevel_hierarchy) +{ + struct file_handle *gp_handle, *p_handle, *c_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 gp_id, p_id, c_id; + char gp_buf[sizeof(*gp_handle) + MAX_HANDLE_SZ]; + char p_buf[sizeof(*p_handle) + MAX_HANDLE_SZ]; + char c_buf[sizeof(*c_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + /* Create grandparent user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int gp_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (gp_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(gp_fd, NS_GET_ID, &gp_id) < 0) { + close(gp_fd); + close(pipefd[1]); + exit(1); + } + close(gp_fd); + + /* Create parent user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int p_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (p_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(p_fd, NS_GET_ID, &p_id) < 0) { + close(p_fd); + close(pipefd[1]); + exit(1); + } + close(p_fd); + + /* Create child user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int c_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (c_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(c_fd, NS_GET_ID, &c_id) < 0) { + close(c_fd); + close(pipefd[1]); + exit(1); + } + close(c_fd); + + /* Send all three namespace IDs */ + write(pipefd[1], &gp_id, sizeof(gp_id)); + write(pipefd[1], &p_id, sizeof(p_id)); + write(pipefd[1], &c_id, sizeof(c_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &gp_id, sizeof(gp_id)); + if (ret !=3D sizeof(gp_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read grandparent namespace ID from child"); + } + + ret =3D read(pipefd[0], &p_id, sizeof(p_id)); + if (ret !=3D sizeof(p_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read parent namespace ID from child"); + } + + ret =3D read(pipefd[0], &c_id, sizeof(c_id)); + close(pipefd[0]); + if (ret !=3D sizeof(c_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read child namespace ID from child"); + } + + /* Construct file handles from namespace IDs */ + gp_handle =3D (struct file_handle *)gp_buf; + gp_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + gp_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *gp_fh =3D (struct nsfs_file_handle *)gp_handle->= f_handle; + gp_fh->ns_id =3D gp_id; + gp_fh->ns_type =3D 0; + gp_fh->ns_inum =3D 0; + + p_handle =3D (struct file_handle *)p_buf; + p_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + p_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *p_fh =3D (struct nsfs_file_handle *)p_handle->f_= handle; + p_fh->ns_id =3D p_id; + p_fh->ns_type =3D 0; + p_fh->ns_inum =3D 0; + + c_handle =3D (struct file_handle *)c_buf; + c_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + c_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *c_fh =3D (struct nsfs_file_handle *)c_handle->f_= handle; + c_fh->ns_id =3D c_id; + c_fh->ns_type =3D 0; + c_fh->ns_inum =3D 0; + + /* Open child before process exits */ + int c_fd =3D open_by_handle_at(FD_NSFS_ROOT, c_handle, O_RDONLY); + if (c_fd < 0) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open child namespace"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(c_fd); + SKIP(return, "Child failed"); + } + + /* + * With 3-level hierarchy and child active: + * - Child is active (we hold fd) + * - Parent should be active (propagated from child) + * - Grandparent should be active (propagated from parent) + */ + TH_LOG("Testing parent active when child is active"); + int p_fd =3D open_by_handle_at(FD_NSFS_ROOT, p_handle, O_RDONLY); + ASSERT_GE(p_fd, 0); + + TH_LOG("Testing grandparent active when child is active"); + int gp_fd =3D open_by_handle_at(FD_NSFS_ROOT, gp_handle, O_RDONLY); + ASSERT_GE(gp_fd, 0); + + close(c_fd); + close(p_fd); + close(gp_fd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 D183436B998; Wed, 22 Oct 2025 16:08:40 +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=1761149320; cv=none; b=e1s0oGWIErEw4DKMTdCMgy2LRrsxQOVV+ASuRcxABBaQJchdbz2HujDoCMAN90yrvOvSmNVLjXLXTFra5CpgdDEsMBjLKDH+Hq9un9ad334jkKf4XLnTb+ZXwVkDEqMn0JCaoQ45y5DczPf7kFxSx9APHX1/Y9Jv8sXjnQ6TjZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149320; c=relaxed/simple; bh=I1mnXxN1C6AOW3tyeK+RAqokVAFrl2UVgQuyKj9qhRM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=biLRsk8WiGgT/2cmP72OPF3wZbKJ67hivMBuHHwlgnOnRO4UmN2W+MQB36caphSZJMoq05ZTcBS4IT7Dm7j7wbwlLfISDbpLbWq/aGVExfWO3nSqYkFTOYCixETmn9Yvs3Lyy0Ar++P0HsIt8AR62WEy2HE9LxJPjc8o2PkkU7U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ae/iL18L; 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="Ae/iL18L" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9397AC4CEE7; Wed, 22 Oct 2025 16:08:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149320; bh=I1mnXxN1C6AOW3tyeK+RAqokVAFrl2UVgQuyKj9qhRM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ae/iL18LvYuWMXvT3qTFVc14meFWYuMAx7p7+uGkmSrRN9PNNVPkh2q/0klv9qXAz tHmZyj5B/oMz1fJTzFSAHulYhfdXDYcFBfWc2fOJyAJE87r2hP15OniryepaoueKcR zk/LuTNjXRAO6HqT9+Hiw53+rtLET0kUZ9xgY/m4spjQlbodgAAvkJZ24TYkG4A8hs DSQBgXWnuvPHygFIAhhcegEaUxxPE6KW9VbRn/7nVaLQm8Rt93mC/ubw1FuiOzCE26 FHKj6thDIOQI5UvCpTi7QUtsMINrcYSyIaDzRzpFX24Tpkm3EQfs4V28AuQDId5FVu Tttk0Uf8w7VZw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:07 +0200 Subject: [PATCH v2 29/63] selftests/namespaces: tenth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-29-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5731; i=brauner@kernel.org; h=from:subject:message-id; bh=I1mnXxN1C6AOW3tyeK+RAqokVAFrl2UVgQuyKj9qhRM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjq9clfrsBLyM3Zfe0lo7zjO9WWx1uxnrz3Wq8uK LPYvj63o5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCKbeRgZNqVv8pYS2/NZeaZN aZz5bbf1s9ICHsWGFLGdiD/m/POjFiPDLPO6jIrGW7JzorXmTHF13vvqVhn3tshzvamrdfof3Fz KCgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test multiple children sharing same parent. Parent should stay active as long as ANY child is active. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 177 +++++++++++++++++= ++++ 1 file changed, 177 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 87b435b64b45..15d001df981c 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1176,4 +1176,181 @@ TEST(ns_multilevel_hierarchy) close(gp_fd); } =20 +/* + * Test multiple children sharing same parent. + * Parent should stay active as long as ANY child is active. + */ +TEST(ns_multiple_children_same_parent) +{ + struct file_handle *p_handle, *c1_handle, *c2_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 p_id, c1_id, c2_id; + char p_buf[sizeof(*p_handle) + MAX_HANDLE_SZ]; + char c1_buf[sizeof(*c1_handle) + MAX_HANDLE_SZ]; + char c2_buf[sizeof(*c2_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + /* Create parent user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int p_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (p_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(p_fd, NS_GET_ID, &p_id) < 0) { + close(p_fd); + close(pipefd[1]); + exit(1); + } + close(p_fd); + + /* Create first child user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int c1_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (c1_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(c1_fd, NS_GET_ID, &c1_id) < 0) { + close(c1_fd); + close(pipefd[1]); + exit(1); + } + close(c1_fd); + + /* Return to parent user namespace and create second child */ + /* We can't actually do this easily, so let's create a sibling namespace + * by creating a network namespace instead */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + int c2_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (c2_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(c2_fd, NS_GET_ID, &c2_id) < 0) { + close(c2_fd); + close(pipefd[1]); + exit(1); + } + close(c2_fd); + + /* Send all namespace IDs */ + write(pipefd[1], &p_id, sizeof(p_id)); + write(pipefd[1], &c1_id, sizeof(c1_id)); + write(pipefd[1], &c2_id, sizeof(c2_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &p_id, sizeof(p_id)); + if (ret !=3D sizeof(p_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read parent namespace ID"); + } + + ret =3D read(pipefd[0], &c1_id, sizeof(c1_id)); + if (ret !=3D sizeof(c1_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read first child namespace ID"); + } + + ret =3D read(pipefd[0], &c2_id, sizeof(c2_id)); + close(pipefd[0]); + if (ret !=3D sizeof(c2_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read second child namespace ID"); + } + + /* Construct file handles from namespace IDs */ + p_handle =3D (struct file_handle *)p_buf; + p_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + p_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *p_fh =3D (struct nsfs_file_handle *)p_handle->f_= handle; + p_fh->ns_id =3D p_id; + p_fh->ns_type =3D 0; + p_fh->ns_inum =3D 0; + + c1_handle =3D (struct file_handle *)c1_buf; + c1_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + c1_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *c1_fh =3D (struct nsfs_file_handle *)c1_handle->= f_handle; + c1_fh->ns_id =3D c1_id; + c1_fh->ns_type =3D 0; + c1_fh->ns_inum =3D 0; + + c2_handle =3D (struct file_handle *)c2_buf; + c2_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + c2_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *c2_fh =3D (struct nsfs_file_handle *)c2_handle->= f_handle; + c2_fh->ns_id =3D c2_id; + c2_fh->ns_type =3D 0; + c2_fh->ns_inum =3D 0; + + /* Open both children before process exits */ + int c1_fd =3D open_by_handle_at(FD_NSFS_ROOT, c1_handle, O_RDONLY); + int c2_fd =3D open_by_handle_at(FD_NSFS_ROOT, c2_handle, O_RDONLY); + + if (c1_fd < 0 || c2_fd < 0) { + if (c1_fd >=3D 0) close(c1_fd); + if (c2_fd >=3D 0) close(c2_fd); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open child namespaces"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(c1_fd); + close(c2_fd); + SKIP(return, "Child failed"); + } + + /* Parent should be active (both children active) */ + TH_LOG("Both children active - parent should be active"); + int p_fd =3D open_by_handle_at(FD_NSFS_ROOT, p_handle, O_RDONLY); + ASSERT_GE(p_fd, 0); + close(p_fd); + + /* Close first child - parent should STILL be active */ + TH_LOG("Closing first child - parent should still be active"); + close(c1_fd); + p_fd =3D open_by_handle_at(FD_NSFS_ROOT, p_handle, O_RDONLY); + ASSERT_GE(p_fd, 0); + close(p_fd); + + /* Close second child - NOW parent should become inactive */ + TH_LOG("Closing second child - parent should become inactive"); + close(c2_fd); + p_fd =3D open_by_handle_at(FD_NSFS_ROOT, p_handle, O_RDONLY); + if (p_fd >=3D 0) { + close(p_fd); + TH_LOG("Warning: Parent still active after all children inactive"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 D1B5436C24C; Wed, 22 Oct 2025 16:08:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149325; cv=none; b=eZ5UMlw8dx/NJcimN5ktxSHNAAet/Qon4aKmYiHjkH7+eRpPYlmoaKTnhkDSk/ksKTUYqoWS3ebaGZc7Iplh1+3VSXiViRtKRfv6nBDUxeOGpayxs7KImnUJAdWT/nzV6pcVK7qLLNadlLQXe+3HnAjJQc7AH4PSnoQH2MoScL8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149325; c=relaxed/simple; bh=H4jWaPD3RLb43DWhIT3tk1IDFLr01dcU/60jks3O+nc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=paudmdrd23WFbweThiJ02dYdVu9SRRLCqtukxZ4/q7RyAuU0P5CP/K0LCOVAdCn6BfSprlaZ7XQ/VStD/ToMpuHYoFJWRKJHwDnYgkbjtLTbndLpXP9Bi882TaykRRInC7QtV05qrMCs+uj0rGiUb4coksOH4VoTqDK3iLAEkgU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MYD5zpTo; 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="MYD5zpTo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DBF3FC4CEF7; Wed, 22 Oct 2025 16:08:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149325; bh=H4jWaPD3RLb43DWhIT3tk1IDFLr01dcU/60jks3O+nc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MYD5zpTo3Uo7bqM+eMBO33qzRIlw2WUzMXB5p0cchxfKBCi1v3ikwIQ/M5WJH+wZ7 y7FsKHjko6Z+cLjrUvPNlOFSyNNzzi7Mp3FsaThJ1eiUbWOpRi815QKxEXp3gRCFZi 4GPz17tvrZHn+fJ1ULp4ab9B/GvFjXKVaXsX3MG/XznY7K+fwUFx+fsoH1dQSr4VuD h3DBGb+5bSYLSc5dnEv4MjH1mluPkRt39bnaDxzf3alpeRc2MrFvv6St04a7JFP+wK sDVtCwjQykobp+LnDyaco2rec5a458T4jL02K3KxQ2HXYyFQQm6hb7+TXX7ssTvFIV p8VptF65Ipbfw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:08 +0200 Subject: [PATCH v2 30/63] selftests/namespaces: eleventh active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-30-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5721; i=brauner@kernel.org; h=from:subject:message-id; bh=H4jWaPD3RLb43DWhIT3tk1IDFLr01dcU/60jks3O+nc=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg2KXTOsv671fUaVxW37uqbW7mnTWTvPv8pqbHNn z2+B3/z7ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZhIwRSG/+nPFjXKbd1+/1Nu Prvalt7OX50RyX21eScTxeb6Wfxbb8HwP/rfNYvHnvEL6zdxdWxc6BFXubDdXOVwtsGsuBaTHXl TmAE= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that different namespace types with same owner all contribute active references to the owning user namespace. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 178 +++++++++++++++++= ++++ 1 file changed, 178 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 15d001df981c..3c2f99b25067 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1353,4 +1353,182 @@ TEST(ns_multiple_children_same_parent) } } =20 +/* + * Test that different namespace types with same owner all contribute + * active references to the owning user namespace. + */ +TEST(ns_different_types_same_owner) +{ + struct file_handle *u_handle, *n_handle, *ut_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 u_id, n_id, ut_id; + char u_buf[sizeof(*u_handle) + MAX_HANDLE_SZ]; + char n_buf[sizeof(*n_handle) + MAX_HANDLE_SZ]; + char ut_buf[sizeof(*ut_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + /* Create user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int u_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (u_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(u_fd, NS_GET_ID, &u_id) < 0) { + close(u_fd); + close(pipefd[1]); + exit(1); + } + close(u_fd); + + /* Create network namespace (owned by user namespace) */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + int n_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (n_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(n_fd, NS_GET_ID, &n_id) < 0) { + close(n_fd); + close(pipefd[1]); + exit(1); + } + close(n_fd); + + /* Create UTS namespace (also owned by user namespace) */ + if (unshare(CLONE_NEWUTS) < 0) { + close(pipefd[1]); + exit(1); + } + + int ut_fd =3D open("/proc/self/ns/uts", O_RDONLY); + if (ut_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ut_fd, NS_GET_ID, &ut_id) < 0) { + close(ut_fd); + close(pipefd[1]); + exit(1); + } + close(ut_fd); + + /* Send all namespace IDs */ + write(pipefd[1], &u_id, sizeof(u_id)); + write(pipefd[1], &n_id, sizeof(n_id)); + write(pipefd[1], &ut_id, sizeof(ut_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &u_id, sizeof(u_id)); + if (ret !=3D sizeof(u_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user namespace ID"); + } + + ret =3D read(pipefd[0], &n_id, sizeof(n_id)); + if (ret !=3D sizeof(n_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read network namespace ID"); + } + + ret =3D read(pipefd[0], &ut_id, sizeof(ut_id)); + close(pipefd[0]); + if (ret !=3D sizeof(ut_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read UTS namespace ID"); + } + + /* Construct file handles from namespace IDs */ + u_handle =3D (struct file_handle *)u_buf; + u_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + u_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *u_fh =3D (struct nsfs_file_handle *)u_handle->f_= handle; + u_fh->ns_id =3D u_id; + u_fh->ns_type =3D 0; + u_fh->ns_inum =3D 0; + + n_handle =3D (struct file_handle *)n_buf; + n_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + n_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *n_fh =3D (struct nsfs_file_handle *)n_handle->f_= handle; + n_fh->ns_id =3D n_id; + n_fh->ns_type =3D 0; + n_fh->ns_inum =3D 0; + + ut_handle =3D (struct file_handle *)ut_buf; + ut_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + ut_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ut_fh =3D (struct nsfs_file_handle *)ut_handle->= f_handle; + ut_fh->ns_id =3D ut_id; + ut_fh->ns_type =3D 0; + ut_fh->ns_inum =3D 0; + + /* Open both non-user namespaces before process exits */ + int n_fd =3D open_by_handle_at(FD_NSFS_ROOT, n_handle, O_RDONLY); + int ut_fd =3D open_by_handle_at(FD_NSFS_ROOT, ut_handle, O_RDONLY); + + if (n_fd < 0 || ut_fd < 0) { + if (n_fd >=3D 0) close(n_fd); + if (ut_fd >=3D 0) close(ut_fd); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open namespaces"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(n_fd); + close(ut_fd); + SKIP(return, "Child failed"); + } + + /* + * Both network and UTS namespaces are active. + * User namespace should be active (gets 2 active refs). + */ + TH_LOG("Both net and uts active - user namespace should be active"); + int u_fd =3D open_by_handle_at(FD_NSFS_ROOT, u_handle, O_RDONLY); + ASSERT_GE(u_fd, 0); + close(u_fd); + + /* Close network namespace - user namespace should STILL be active */ + TH_LOG("Closing network ns - user ns should still be active (uts still ac= tive)"); + close(n_fd); + u_fd =3D open_by_handle_at(FD_NSFS_ROOT, u_handle, O_RDONLY); + ASSERT_GE(u_fd, 0); + close(u_fd); + + /* Close UTS namespace - user namespace should become inactive */ + TH_LOG("Closing uts ns - user ns should become inactive"); + close(ut_fd); + u_fd =3D open_by_handle_at(FD_NSFS_ROOT, u_handle, O_RDONLY); + if (u_fd >=3D 0) { + close(u_fd); + TH_LOG("Warning: User namespace still active after all owned namespaces = inactive"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 8469C36CA73; Wed, 22 Oct 2025 16:08:51 +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=1761149331; cv=none; b=XCJ1mrkiSqQtskcJHohsWdoXJX1xKS8CwM/QTH5IdkyVQNVNHeCaMv7heLGDwEy9v+QeX2v5LcsBlMFuSpJJw0GnbuznYwAEX88HATp09bjqUXlcHIRBhkikQyQn9Ph3AamHMM7ENgQbAJx07Q+ZzkNh02EoLHhLb+uKD/QqH0c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149331; c=relaxed/simple; bh=YF6LlFsedC0FcPBAnpIIRxVh8Wv/PCUOI1UuPciGHmg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=CC/mCsOw/SEkfye4EbEqtC23XceS0d7U5wzjCFnSrh9d1zwj5kCqnLoA6BaVMuqxLlhx43q9UONqr980F4097A8RgJ647YsJkFdEaA97aBuPCiy5wIJDczblyUyJ6he44X5KJhBqbGCGMDN99R4qKFWCi53r2eY+UEv7sNVkdLo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=anhSpSoc; 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="anhSpSoc" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 322CCC4CEE7; Wed, 22 Oct 2025 16:08:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149331; bh=YF6LlFsedC0FcPBAnpIIRxVh8Wv/PCUOI1UuPciGHmg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=anhSpSocL4/Y0wO7SWHo1+WKZyZmaX1PqPELD+iJSgf5O0FBBgxstD49+P6aX20a/ Ndd0oimDGHnrrdjvxvC4ySXLdIHTvE2FS118PmUlXmbPRQ+kmYCDGD/ce/JbTKKUt1 5jsNKZ8PZmiqwynUblI9pu8friTlb9o0l8VxdsGJmA0uAT07Nq11Aj4bz2QM1SkQ73 EL5Frw6tzWjc0W4wIFsXBYVZBn/6AcoN1I2HunYU7BA1Rb16Txgegd8tmEl0RruLCt A6gPMypjB7VyFHv2RdIF0dYSasMkC0a6GxsRLerRjsJWMpl5NJoQO4OZi1n8WrDjZv AG3BKlQqeyDcQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:09 +0200 Subject: [PATCH v2 31/63] selftests/namespaces: twelth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-31-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6173; i=brauner@kernel.org; h=from:subject:message-id; bh=YF6LlFsedC0FcPBAnpIIRxVh8Wv/PCUOI1UuPciGHmg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHhmWHNzW3HXn7tan3lYVqTELgpme15bPfVd2ZT+h Avh/5+YdpSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzk1Q1GhgdH3PiX5ay2+TC7 h42nS4I9yk9a/EntMQ+edsWkl7ciBBgZru5avHZbIIdZcshdFpXn8eUvbHJ/n2ISnqydJH/ufsp TXgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test hierarchical propagation with deep namespace hierarchy. Create: init_user_ns -> user_A -> user_B -> net_ns When net_ns is active, both user_A and user_B should be active. This verifies the conditional recursion in __ns_ref_active_put() works. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 182 +++++++++++++++++= ++++ 1 file changed, 182 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 3c2f99b25067..63cc88fe5cc1 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1531,4 +1531,186 @@ TEST(ns_different_types_same_owner) } } =20 +/* + * Test hierarchical propagation with deep namespace hierarchy. + * Create: init_user_ns -> user_A -> user_B -> net_ns + * When net_ns is active, both user_A and user_B should be active. + * This verifies the conditional recursion in __ns_ref_active_put() works. + */ +TEST(ns_deep_hierarchy_propagation) +{ + struct file_handle *ua_handle, *ub_handle, *net_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 ua_id, ub_id, net_id; + char ua_buf[sizeof(*ua_handle) + MAX_HANDLE_SZ]; + char ub_buf[sizeof(*ub_handle) + MAX_HANDLE_SZ]; + char net_buf[sizeof(*net_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + /* Create user_A -> user_B -> net hierarchy */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int ua_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (ua_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ua_fd, NS_GET_ID, &ua_id) < 0) { + close(ua_fd); + close(pipefd[1]); + exit(1); + } + close(ua_fd); + + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int ub_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (ub_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ub_fd, NS_GET_ID, &ub_id) < 0) { + close(ub_fd); + close(pipefd[1]); + exit(1); + } + close(ub_fd); + + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + int net_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (net_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(net_fd, NS_GET_ID, &net_id) < 0) { + close(net_fd); + close(pipefd[1]); + exit(1); + } + close(net_fd); + + /* Send all three namespace IDs */ + write(pipefd[1], &ua_id, sizeof(ua_id)); + write(pipefd[1], &ub_id, sizeof(ub_id)); + write(pipefd[1], &net_id, sizeof(net_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &ua_id, sizeof(ua_id)); + if (ret !=3D sizeof(ua_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user_A namespace ID"); + } + + ret =3D read(pipefd[0], &ub_id, sizeof(ub_id)); + if (ret !=3D sizeof(ub_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user_B namespace ID"); + } + + ret =3D read(pipefd[0], &net_id, sizeof(net_id)); + close(pipefd[0]); + if (ret !=3D sizeof(net_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read network namespace ID"); + } + + /* Construct file handles from namespace IDs */ + ua_handle =3D (struct file_handle *)ua_buf; + ua_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + ua_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ua_fh =3D (struct nsfs_file_handle *)ua_handle->= f_handle; + ua_fh->ns_id =3D ua_id; + ua_fh->ns_type =3D 0; + ua_fh->ns_inum =3D 0; + + ub_handle =3D (struct file_handle *)ub_buf; + ub_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + ub_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ub_fh =3D (struct nsfs_file_handle *)ub_handle->= f_handle; + ub_fh->ns_id =3D ub_id; + ub_fh->ns_type =3D 0; + ub_fh->ns_inum =3D 0; + + net_handle =3D (struct file_handle *)net_buf; + net_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + net_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *net_fh =3D (struct nsfs_file_handle *)net_handle= ->f_handle; + net_fh->ns_id =3D net_id; + net_fh->ns_type =3D 0; + net_fh->ns_inum =3D 0; + + /* Open net_ns before child exits to keep it active */ + int net_fd =3D open_by_handle_at(FD_NSFS_ROOT, net_handle, O_RDONLY); + if (net_fd < 0) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open network namespace"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(net_fd); + SKIP(return, "Child failed"); + } + + /* With net_ns active, both user_A and user_B should be active */ + TH_LOG("Testing user_B active (net_ns active causes propagation)"); + int ub_fd =3D open_by_handle_at(FD_NSFS_ROOT, ub_handle, O_RDONLY); + ASSERT_GE(ub_fd, 0); + + TH_LOG("Testing user_A active (propagated through user_B)"); + int ua_fd =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + ASSERT_GE(ua_fd, 0); + + /* Close net_ns - user_B should stay active (we hold direct ref) */ + TH_LOG("Closing net_ns, user_B should remain active (direct ref held)"); + close(net_fd); + int ub_fd2 =3D open_by_handle_at(FD_NSFS_ROOT, ub_handle, O_RDONLY); + ASSERT_GE(ub_fd2, 0); + close(ub_fd2); + + /* Close user_B - user_A should stay active (we hold direct ref) */ + TH_LOG("Closing user_B, user_A should remain active (direct ref held)"); + close(ub_fd); + int ua_fd2 =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + ASSERT_GE(ua_fd2, 0); + close(ua_fd2); + + /* Close user_A - everything should become inactive */ + TH_LOG("Closing user_A, all should become inactive"); + close(ua_fd); + + /* All should now be inactive */ + ua_fd =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + if (ua_fd >=3D 0) { + close(ua_fd); + TH_LOG("Warning: user_A still active"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 0524227703C; Wed, 22 Oct 2025 16:08: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=1761149337; cv=none; b=rXkSjPjY5q9PuNlI/z8X5+bB4pRR26QRmJ8jt2qj5+dUrlYy2827fG1zvdTcklkoHD2W1ublaFATsMSxkl5KQSbpS0FGODUK2w1AFTh4MxuP7qW3+YQ8X7yncQxuKKM+GtwUbwPYzT0Tgbl2Me6J0a3EWKuzH34thvt7WTWETfI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149337; c=relaxed/simple; bh=vsrRT4zqgD+nKit9MH7tv6SchshKJx7ljsx1OLBVRIQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QQP9y+qJ3ZQqCuKo2+cuTeAdtwJjyogpln40gn4q9Z9mC2c5DRreFT6BKIcmR2ZeBLEs+wE2YoPasLZh1JZzHmFStXegBvNdruS228LewzwDxBcMa0D4ywsyJi5lFc7Jn/3Ct+dy/YA/yWaXAzFi8SixIFxblIaFzS0GgY8VfQs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UtwSQowD; 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="UtwSQowD" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A4485C4CEFD; Wed, 22 Oct 2025 16:08:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149336; bh=vsrRT4zqgD+nKit9MH7tv6SchshKJx7ljsx1OLBVRIQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UtwSQowDPUxM7jr/H84m9ZfhgSDHxtsMhG5+q1h/gx2UEvOliYJQxs5Wz1DwTRJYS fW8LN542gm+miWCKBsrvJNy33O7E2vehZ68kZSiNWxGivHJVzpxiGSbWfvm7aj+Oaq L4FG73cB2NjR0hV5GZTq4yCZk5O5VZTrX4uFYARmWy0xnLiUvGWA/WIggvOugP1aWx C6ZpARjnsuH/qntEKDx2wopS3apRAm41U4q6QB+DS7IhgVNtpINdwadMvoUzABaYMB b+sdMwOtElmWIth/2xlDW3fiYzTSlrPrg+LkChIFbXXmd004UUg6/JnNgOqyX7W7Tg BWplrksfkeXqw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:10 +0200 Subject: [PATCH v2 32/63] selftests/namespaces: thirteenth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-32-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6611; i=brauner@kernel.org; h=from:subject:message-id; bh=vsrRT4zqgD+nKit9MH7tv6SchshKJx7ljsx1OLBVRIQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg2wfUB7y/phdxZ6hwLG2fOZc9+tWvmCaPpimZmD StcjL9v7yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZhI7HFGhjf1SlqrthX2X00v VDwlU+T958TDU+3qzV8Pi5Z56yeqSjAyPF24IHzP9uW+i5rnPds0oXH7h8UJ2jbMV3fk9ie4yz0 tYgQA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that parent stays active as long as ANY child is active. Create parent user namespace with two child net namespaces. Parent should remain active until BOTH children are inactive. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 201 +++++++++++++++++= ++++ 1 file changed, 201 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 63cc88fe5cc1..4c077223b05c 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1713,4 +1713,205 @@ TEST(ns_deep_hierarchy_propagation) } } =20 +/* + * Test that parent stays active as long as ANY child is active. + * Create parent user namespace with two child net namespaces. + * Parent should remain active until BOTH children are inactive. + */ +TEST(ns_parent_multiple_children_refcount) +{ + struct file_handle *parent_handle, *net1_handle, *net2_handle; + int ret, pipefd[2], syncpipe[2]; + pid_t pid; + int status; + __u64 p_id, n1_id, n2_id; + char p_buf[sizeof(*parent_handle) + MAX_HANDLE_SZ]; + char n1_buf[sizeof(*net1_handle) + MAX_HANDLE_SZ]; + char n2_buf[sizeof(*net2_handle) + MAX_HANDLE_SZ]; + char sync_byte; + + ASSERT_EQ(pipe(pipefd), 0); + ASSERT_EQ(pipe(syncpipe), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + close(syncpipe[1]); + + /* Create parent user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int p_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (p_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(p_fd, NS_GET_ID, &p_id) < 0) { + close(p_fd); + close(pipefd[1]); + exit(1); + } + close(p_fd); + + /* Create first network namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + + int n1_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (n1_fd < 0) { + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + if (ioctl(n1_fd, NS_GET_ID, &n1_id) < 0) { + close(n1_fd); + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + /* Keep n1_fd open so first namespace stays active */ + + /* Create second network namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(n1_fd); + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + + int n2_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (n2_fd < 0) { + close(n1_fd); + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + if (ioctl(n2_fd, NS_GET_ID, &n2_id) < 0) { + close(n1_fd); + close(n2_fd); + close(pipefd[1]); + close(syncpipe[0]); + exit(1); + } + /* Keep both n1_fd and n2_fd open */ + + /* Send all namespace IDs */ + write(pipefd[1], &p_id, sizeof(p_id)); + write(pipefd[1], &n1_id, sizeof(n1_id)); + write(pipefd[1], &n2_id, sizeof(n2_id)); + close(pipefd[1]); + + /* Wait for parent to signal before exiting */ + read(syncpipe[0], &sync_byte, 1); + close(syncpipe[0]); + exit(0); + } + + close(pipefd[1]); + close(syncpipe[0]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &p_id, sizeof(p_id)); + if (ret !=3D sizeof(p_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read parent namespace ID"); + } + + ret =3D read(pipefd[0], &n1_id, sizeof(n1_id)); + if (ret !=3D sizeof(n1_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read first network namespace ID"); + } + + ret =3D read(pipefd[0], &n2_id, sizeof(n2_id)); + close(pipefd[0]); + if (ret !=3D sizeof(n2_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read second network namespace ID"); + } + + /* Construct file handles from namespace IDs */ + parent_handle =3D (struct file_handle *)p_buf; + parent_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + parent_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *p_fh =3D (struct nsfs_file_handle *)parent_handl= e->f_handle; + p_fh->ns_id =3D p_id; + p_fh->ns_type =3D 0; + p_fh->ns_inum =3D 0; + + net1_handle =3D (struct file_handle *)n1_buf; + net1_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + net1_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *n1_fh =3D (struct nsfs_file_handle *)net1_handle= ->f_handle; + n1_fh->ns_id =3D n1_id; + n1_fh->ns_type =3D 0; + n1_fh->ns_inum =3D 0; + + net2_handle =3D (struct file_handle *)n2_buf; + net2_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + net2_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *n2_fh =3D (struct nsfs_file_handle *)net2_handle= ->f_handle; + n2_fh->ns_id =3D n2_id; + n2_fh->ns_type =3D 0; + n2_fh->ns_inum =3D 0; + + /* Open both net namespaces while child is still alive */ + int n1_fd =3D open_by_handle_at(FD_NSFS_ROOT, net1_handle, O_RDONLY); + int n2_fd =3D open_by_handle_at(FD_NSFS_ROOT, net2_handle, O_RDONLY); + if (n1_fd < 0 || n2_fd < 0) { + if (n1_fd >=3D 0) close(n1_fd); + if (n2_fd >=3D 0) close(n2_fd); + sync_byte =3D 'G'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open net namespaces"); + } + + /* Signal child that we have opened the namespaces */ + sync_byte =3D 'G'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(n1_fd); + close(n2_fd); + SKIP(return, "Child failed"); + } + + /* Parent should be active (has 2 active children) */ + TH_LOG("Both net namespaces active - parent should be active"); + int p_fd =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONLY); + ASSERT_GE(p_fd, 0); + close(p_fd); + + /* Close first net namespace - parent should STILL be active */ + TH_LOG("Closing first net ns - parent should still be active"); + close(n1_fd); + p_fd =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONLY); + ASSERT_GE(p_fd, 0); + close(p_fd); + + /* Close second net namespace - parent should become inactive */ + TH_LOG("Closing second net ns - parent should become inactive"); + close(n2_fd); + p_fd =3D open_by_handle_at(FD_NSFS_ROOT, parent_handle, O_RDONLY); + if (p_fd >=3D 0) { + close(p_fd); + TH_LOG("Warning: Parent still active after all children inactive"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 F3598368F52; Wed, 22 Oct 2025 16:09:01 +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=1761149342; cv=none; b=tebqyiKUSEDYAsAaQp93ruXgnqkq2TA2G9aaeK5PWmDGmSIaIRSbvPXd5+wilVyI8PRws2PyNTEzxmZ2Ua0ZIxyoUxrHLV3QhAsRHoRpPWLOuxBSNoSt+P9oXwlwpHNckss0HOwyEYMLPG6rkVNCzlGPwMSPbe3/08vhAhXk2D4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149342; c=relaxed/simple; bh=fdHj1hsijB+BXri97N5cswYO4dlb02Ygb6q9aUmDKdA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bzYlGo4S2Nv0JhiECW7nZR4FcX2ye4rOsFovE7nPIY6gx3WOqu+i2my8j2JHXjGMFPN4UplHlPgzZ2EovgONe63D4Lwvb3mDFG5tTRzKe/9xlh8LjIhyc7k4mDKciSmken21h1A6GcYKhqqCyaXQ0k5PVCiRUjgTDUW6uezFdNY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IKNbJVxO; 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="IKNbJVxO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F27ABC113D0; Wed, 22 Oct 2025 16:08:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149341; bh=fdHj1hsijB+BXri97N5cswYO4dlb02Ygb6q9aUmDKdA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IKNbJVxOWPHbZFlBVVwdlFPbO12K8GPtzoW+y/QvadKR9dYQNcttdp79eTyrrBrkN FNKa6tOe0de7FAjW5tVi1sCBM53Fz2Q1LwQQ9sVBS3IvQF6lTMOYyZp43iO1JLpJbR i0+el02Zzyo+D+ol/h17RCiq537uklBXTShHeRKesakTmaRJpuru/+bCWvGbtecGsi ry0B76HfjUi7+jiLgPyEIqG0ojzmCyp67CRf76wAhUHeo99hYBQLjW8EtpIS0P22xt gyU8+TT300/udIPp5/+f1IQ8hRjQ9UyEh0g+aV2vpknwgR7J/OLsxgfvunneA5Knh2 2qZ+tlzhwFHMQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:11 +0200 Subject: [PATCH v2 33/63] selftests/namespaces: fourteenth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-33-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4527; i=brauner@kernel.org; h=from:subject:message-id; bh=fdHj1hsijB+BXri97N5cswYO4dlb02Ygb6q9aUmDKdA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg2ue27W/vpvv06b7vUHQ7Z+tjPYjQ9rnz5Sevtn e8mcOSXd5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzE8Dgjw6enjn2mqm2TfXQ6 /i0/qWvqG3Y+58NkkUO1nK3fniRuE2dkOL1IeN00FdXq0JoE3f2RdxmmeXrZW65Tm9u4dO/bzdq +PAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that user namespace as a child also propagates correctly. Create user_A -> user_B, verify when user_B is active that user_A is also active. This is different from non-user namespace children. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 138 +++++++++++++++++= ++++ 1 file changed, 138 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 4c077223b05c..1eb4dc07e924 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1914,4 +1914,142 @@ TEST(ns_parent_multiple_children_refcount) } } =20 +/* + * Test that user namespace as a child also propagates correctly. + * Create user_A -> user_B, verify when user_B is active that user_A + * is also active. This is different from non-user namespace children. + */ +TEST(ns_userns_child_propagation) +{ + struct file_handle *ua_handle, *ub_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 ua_id, ub_id; + char ua_buf[sizeof(*ua_handle) + MAX_HANDLE_SZ]; + char ub_buf[sizeof(*ub_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + /* Create user_A */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int ua_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (ua_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ua_fd, NS_GET_ID, &ua_id) < 0) { + close(ua_fd); + close(pipefd[1]); + exit(1); + } + close(ua_fd); + + /* Create user_B (child of user_A) */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int ub_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (ub_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ub_fd, NS_GET_ID, &ub_id) < 0) { + close(ub_fd); + close(pipefd[1]); + exit(1); + } + close(ub_fd); + + /* Send both namespace IDs */ + write(pipefd[1], &ua_id, sizeof(ua_id)); + write(pipefd[1], &ub_id, sizeof(ub_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read both namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &ua_id, sizeof(ua_id)); + if (ret !=3D sizeof(ua_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user_A namespace ID"); + } + + ret =3D read(pipefd[0], &ub_id, sizeof(ub_id)); + close(pipefd[0]); + if (ret !=3D sizeof(ub_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user_B namespace ID"); + } + + /* Construct file handles from namespace IDs */ + ua_handle =3D (struct file_handle *)ua_buf; + ua_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + ua_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ua_fh =3D (struct nsfs_file_handle *)ua_handle->= f_handle; + ua_fh->ns_id =3D ua_id; + ua_fh->ns_type =3D 0; + ua_fh->ns_inum =3D 0; + + ub_handle =3D (struct file_handle *)ub_buf; + ub_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + ub_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ub_fh =3D (struct nsfs_file_handle *)ub_handle->= f_handle; + ub_fh->ns_id =3D ub_id; + ub_fh->ns_type =3D 0; + ub_fh->ns_inum =3D 0; + + /* Open user_B before child exits */ + int ub_fd =3D open_by_handle_at(FD_NSFS_ROOT, ub_handle, O_RDONLY); + if (ub_fd < 0) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open user_B"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(ub_fd); + SKIP(return, "Child failed"); + } + + /* With user_B active, user_A should also be active */ + TH_LOG("Testing user_A active when child user_B is active"); + int ua_fd =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + ASSERT_GE(ua_fd, 0); + + /* Close user_B */ + TH_LOG("Closing user_B"); + close(ub_fd); + + /* user_A should remain active (we hold direct ref) */ + int ua_fd2 =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + ASSERT_GE(ua_fd2, 0); + close(ua_fd2); + + /* Close user_A - should become inactive */ + TH_LOG("Closing user_A - should become inactive"); + close(ua_fd); + + ua_fd =3D open_by_handle_at(FD_NSFS_ROOT, ua_handle, O_RDONLY); + if (ua_fd >=3D 0) { + close(ua_fd); + TH_LOG("Warning: user_A still active"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6B63C374AB5; Wed, 22 Oct 2025 16:09: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=1761149347; cv=none; b=Zrt10kAw+uloymHQr3OJYqiaAn2PkpOGvW8XYGP6P2OhKr9pHElIdm3ngYqAL2gNQQlP9Qs2ApcZGHBmXODf8yBZT3KlsI/+jM3nCxD6Ac+O4jSifMLej2qTlsIrM5CwQN3eAYn/NOZnKL6/ffC6s1JguxsE/QTyfwk6U7H+7Eo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149347; c=relaxed/simple; bh=elfrUH3DfTC46qvkbhHf42IekzBPgA/k+oqQpuntS3A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lcNZIKt/TSf8FyGVtb4+yE7VPclGhisJVUUzpADQPhG/UEVxGUafBTopDDq4QK6dB02cwawEoo6HGSpYdQXMuUJLdEzEmEzPJTk0dfTCsKuMQ77KoHogCysm2ferUDqorW3K2QKw9/TYQMt019RYR29xh8DbtlhjbTSMyw1F/iY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ippgv8ce; 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="ippgv8ce" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 169DCC4CEFD; Wed, 22 Oct 2025 16:09:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149346; bh=elfrUH3DfTC46qvkbhHf42IekzBPgA/k+oqQpuntS3A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ippgv8ce4RsVynXiVpkXCyz27UerBAqyx61/XoDOaRsUJ6OTINJdT07QaZX7zoI4f KGqpzIjSE8tUZMlaakfXZG8mtswha11sVromh+TDU3z4BH6JACmcsf78xM/fOaXopg FLwlXwtIXfPcuBWNV+f30Y1JkUNL6U3XvRFdHPxwWfVfUyvXas201erm326ntV018o 3ghgdeHONztq9qol20Coi0hBrFGk1dpBpGYGnpndc4hu2CDyN1XKRV6W6yHULaZe6j zyLAJ9hpmiHZhsHY1vCMVCYMGc6aMGrv81F8gG89WZJYXLZmwFg59jAhhE5BfK5tbe IqMK7vr6NghPQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:12 +0200 Subject: [PATCH v2 34/63] selftests/namespaces: fifteenth active reference count tests Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-34-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5425; i=brauner@kernel.org; h=from:subject:message-id; bh=elfrUH3DfTC46qvkbhHf42IekzBPgA/k+oqQpuntS3A=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi253im8uH2tqU/M37NtLGMnu42taE/brnvq5LAw v6LybapHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABNps2NkeBBofeaVw8R+npV7 43ewVt6okDmvwV+VwFu7LnT3t4wbpxn+KZT/O3VAfeYUdRfzV7XTXK49ymFJ/DzFoXdRKH/s/Ks JrAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test different namespace types (net, uts, ipc) all contributing active references to the same owning user namespace. Signed-off-by: Christian Brauner --- .../selftests/namespaces/ns_active_ref_test.c | 171 +++++++++++++++++= ++++ 1 file changed, 171 insertions(+) diff --git a/tools/testing/selftests/namespaces/ns_active_ref_test.c b/tool= s/testing/selftests/namespaces/ns_active_ref_test.c index 1eb4dc07e924..8b1553be6881 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -2052,4 +2052,175 @@ TEST(ns_userns_child_propagation) } } =20 +/* + * Test different namespace types (net, uts, ipc) all contributing + * active references to the same owning user namespace. + */ +TEST(ns_mixed_types_same_owner) +{ + struct file_handle *user_handle, *net_handle, *uts_handle; + int ret, pipefd[2]; + pid_t pid; + int status; + __u64 u_id, n_id, ut_id; + char u_buf[sizeof(*user_handle) + MAX_HANDLE_SZ]; + char n_buf[sizeof(*net_handle) + MAX_HANDLE_SZ]; + char ut_buf[sizeof(*uts_handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + close(pipefd[0]); + + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + int u_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (u_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(u_fd, NS_GET_ID, &u_id) < 0) { + close(u_fd); + close(pipefd[1]); + exit(1); + } + close(u_fd); + + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + int n_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (n_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(n_fd, NS_GET_ID, &n_id) < 0) { + close(n_fd); + close(pipefd[1]); + exit(1); + } + close(n_fd); + + if (unshare(CLONE_NEWUTS) < 0) { + close(pipefd[1]); + exit(1); + } + + int ut_fd =3D open("/proc/self/ns/uts", O_RDONLY); + if (ut_fd < 0) { + close(pipefd[1]); + exit(1); + } + if (ioctl(ut_fd, NS_GET_ID, &ut_id) < 0) { + close(ut_fd); + close(pipefd[1]); + exit(1); + } + close(ut_fd); + + /* Send all namespace IDs */ + write(pipefd[1], &u_id, sizeof(u_id)); + write(pipefd[1], &n_id, sizeof(n_id)); + write(pipefd[1], &ut_id, sizeof(ut_id)); + close(pipefd[1]); + exit(0); + } + + close(pipefd[1]); + + /* Read all three namespace IDs - fixed size, no parsing needed */ + ret =3D read(pipefd[0], &u_id, sizeof(u_id)); + if (ret !=3D sizeof(u_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user namespace ID"); + } + + ret =3D read(pipefd[0], &n_id, sizeof(n_id)); + if (ret !=3D sizeof(n_id)) { + close(pipefd[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read network namespace ID"); + } + + ret =3D read(pipefd[0], &ut_id, sizeof(ut_id)); + close(pipefd[0]); + if (ret !=3D sizeof(ut_id)) { + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read UTS namespace ID"); + } + + /* Construct file handles from namespace IDs */ + user_handle =3D (struct file_handle *)u_buf; + user_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + user_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *u_fh =3D (struct nsfs_file_handle *)user_handle-= >f_handle; + u_fh->ns_id =3D u_id; + u_fh->ns_type =3D 0; + u_fh->ns_inum =3D 0; + + net_handle =3D (struct file_handle *)n_buf; + net_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + net_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *n_fh =3D (struct nsfs_file_handle *)net_handle->= f_handle; + n_fh->ns_id =3D n_id; + n_fh->ns_type =3D 0; + n_fh->ns_inum =3D 0; + + uts_handle =3D (struct file_handle *)ut_buf; + uts_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + uts_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *ut_fh =3D (struct nsfs_file_handle *)uts_handle-= >f_handle; + ut_fh->ns_id =3D ut_id; + ut_fh->ns_type =3D 0; + ut_fh->ns_inum =3D 0; + + /* Open both non-user namespaces */ + int n_fd =3D open_by_handle_at(FD_NSFS_ROOT, net_handle, O_RDONLY); + int ut_fd =3D open_by_handle_at(FD_NSFS_ROOT, uts_handle, O_RDONLY); + if (n_fd < 0 || ut_fd < 0) { + if (n_fd >=3D 0) close(n_fd); + if (ut_fd >=3D 0) close(ut_fd); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to open namespaces"); + } + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + close(n_fd); + close(ut_fd); + SKIP(return, "Child failed"); + } + + /* User namespace should be active (2 active children) */ + TH_LOG("Both net and uts active - user ns should be active"); + int u_fd =3D open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); + ASSERT_GE(u_fd, 0); + close(u_fd); + + /* Close net - user ns should STILL be active (uts still active) */ + TH_LOG("Closing net - user ns should still be active"); + close(n_fd); + u_fd =3D open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); + ASSERT_GE(u_fd, 0); + close(u_fd); + + /* Close uts - user ns should become inactive */ + TH_LOG("Closing uts - user ns should become inactive"); + close(ut_fd); + u_fd =3D open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); + if (u_fd >=3D 0) { + close(u_fd); + TH_LOG("Warning: User ns still active"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 AABEF2C031B; Wed, 22 Oct 2025 16:09:12 +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=1761149352; cv=none; b=KXHlFfRdbq+sdHpk4RJGETyzkfuCz7Eir9OcduiAUIRjPHVC11IBlHYzyb3RkrtZhd1VNY/ar2yOEbBScsGOiDkl+jSudgg717fSLWFVD7rJzDNrTAlT8UzU9zpHD2KC7i9dTXfJG/AA+jYkaqcCcpf9RUr+9OcpYLgO1sUNCU4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149352; c=relaxed/simple; bh=WU3OpDiHSBOB5eonlPoaP8MJGbmszqupW5dQlbeASiQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Czwkl89iVPCQk3nw85zCBQU9wijuxU83PeXxrWcZFCzxyQfSfspX4g3ap6wCs2Ej4nBOVxO59iilx6hfXNXHdPB/341ycd9Vn8bBo0tOk98DJ+GOb0QFnFmSwgDZqbJuwxy+Hu2SI7nkE11vVpVt0+wOdc5vsCad9Ha6+HXwYwo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jayDfAsx; 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="jayDfAsx" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63A1CC4CEE7; Wed, 22 Oct 2025 16:09:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149352; bh=WU3OpDiHSBOB5eonlPoaP8MJGbmszqupW5dQlbeASiQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jayDfAsxEpv1UY1fJryg7y7EeOxwiMC1cKs8w1p0nHsQpiK0O/UbR+dyzTdud+Fy1 Ll5/TQUjsIse2mYrFq36nYQbHz57QZAIX3oa9WlDn7L5ZiPBJug913YFlQNlqA07TN aB+vQhZCtdQYUx9dvK08JK9eQ54d3WUtdZtrvdwM9SPosd6PXb9ztnXVZuiA0qCDmY jejQlxn95GwqDUZ+U+SckQcuJqUi0SXa4zLc2UI0+IUZyykX6y+PPKhtPLqaUGgxZr L16DVIi+qPKk/C5vk3LI2sc/wjJmfKOSKSG71b6mwOIsfvMz0oLxSU/8NdjtNLAlwz nWgRZz6GVmdRA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:13 +0200 Subject: [PATCH v2 35/63] selftests/namespaces: add listns() wrapper Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-35-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1405; i=brauner@kernel.org; h=from:subject:message-id; bh=WU3OpDiHSBOB5eonlPoaP8MJGbmszqupW5dQlbeASiQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgWIjlFZn1OzuJ+JqeLLcYOputc9k9sVfk083rt4 SwmrYfaHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABM5Npvhn5n9I6mXv1k/Gsps 2+fC+PXvHtm2l9ncvtK6tpw/P9fw3WBk+BstnTNt4p19J/f8zV772mbn8kRrg2tF/tpGK85LbVn hxwgA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a wrapper for the listns() system call. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/wrappers.h | 35 +++++++++++++++++++++++= ++++ 1 file changed, 35 insertions(+) diff --git a/tools/testing/selftests/namespaces/wrappers.h b/tools/testing/= selftests/namespaces/wrappers.h new file mode 100644 index 000000000000..9741a64a5b1d --- /dev/null +++ b/tools/testing/selftests/namespaces/wrappers.h @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include + +#ifndef __SELFTESTS_NAMESPACES_WRAPPERS_H__ +#define __SELFTESTS_NAMESPACES_WRAPPERS_H__ + +#ifndef __NR_listns + #if defined __alpha__ + #define __NR_listns 580 + #elif defined _MIPS_SIM + #if _MIPS_SIM =3D=3D _MIPS_SIM_ABI32 /* o32 */ + #define __NR_listns 4470 + #endif + #if _MIPS_SIM =3D=3D _MIPS_SIM_NABI32 /* n32 */ + #define __NR_listns 6470 + #endif + #if _MIPS_SIM =3D=3D _MIPS_SIM_ABI64 /* n64 */ + #define __NR_listns 5470 + #endif + #else + #define __NR_listns 470 + #endif +#endif + +static inline int sys_listns(const struct ns_id_req *req, __u64 *ns_ids, + size_t nr_ns_ids, unsigned int flags) +{ + return syscall(__NR_listns, req, ns_ids, nr_ns_ids, flags); +} + +#endif /* __SELFTESTS_NAMESPACES_WRAPPERS_H__ */ --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 A78F335773D; Wed, 22 Oct 2025 16:09:17 +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=1761149357; cv=none; b=LZ7kP+9bAy+Ex4CAr/r46Yysu59a2IGvF2fNbZjQ5y3oYxMB71GG737i+o1SjXmQjpsvcI467dI+GRzlPbiE4myKNntfLJC+jGu5MUHQuELJbAUE9zZ42Is8gJt55UiE+kdSrSkXPa21U7F+VthwTi7yu4GvwpP43gAurC+nwx4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149357; c=relaxed/simple; bh=NAhtGlBVfCqrlTfWbGN1zDMklE1n7EKY3e8ekT2vQ0Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hOjcNQCRJrDn2FCZm3Jd/mK8V92W3SQHJp8LytHGK8fLtq42cuwsPCd0LrdBEUyyRDtOPquz6pIKQ5jw/gQ0Nh5PpS/g+oJ1VKGcbsV1tStW2nWk1adsIM2jXAP/kCmZpqUPJXHycAhnnze8M+vCxahnMGXigITHcsiJrLvKZsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=KmhtEIrB; 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="KmhtEIrB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 90250C4CEF7; Wed, 22 Oct 2025 16:09:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149357; bh=NAhtGlBVfCqrlTfWbGN1zDMklE1n7EKY3e8ekT2vQ0Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=KmhtEIrBRkeyMEsu4AooHO/8X7U3hah6e1DRrtmxOGwN9G0ZwiI8b9qG3MdOYPUwn ylzFan+Jw0iB2Bd+zdWBHnBdyK5WBSTaFScZa2HWUK3HPN8BOJsY/cRdeLKcWiIDLa BRK2Oi7CUU2/SfvIobaT+tINSasLarirde8Jv0nCHSUQt2OtEhoWIRw6iwOxmojvy+ qcuwEuykj/lJ3WHbf56WXl/JJklZB7Jx/E+VtWjSKn/mhjNslkLiD9TEd88NCB/lcl a37CgEPLPnT44TaBt886ovW3PspMKv0w/ixoIacJnZX8uxvWmduvdnTRk9pXudPoyH 0NRU6Ntli+g5A== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:14 +0200 Subject: [PATCH v2 36/63] selftests/namespaces: first listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-36-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3148; i=brauner@kernel.org; h=from:subject:message-id; bh=NAhtGlBVfCqrlTfWbGN1zDMklE1n7EKY3e8ekT2vQ0Y=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHh258H3vXV+Gm28XR6Pyk/81vp1a6pI6GO9pWVbu 66u22szp6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAi+ucZ/tlO3fdlTjuT36ue /14bduZviN3He01IRyllvcqBczMrDAUZ/pd9mlFz0dLuntEk4RnXApl31uoKnbSVPN9jdvCuduC EK0wA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test basic listns() functionality with the unified namespace tree. List all active namespaces globally. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 3 +- tools/testing/selftests/namespaces/listns_test.c | 57 ++++++++++++++++++++= ++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index 100cc5bfef04..5065f07e92c9 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -2,3 +2,4 @@ nsid_test file_handle_test init_ino_test ns_active_ref_test +listns_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index 5cea938cdde8..de708f4df159 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -2,9 +2,10 @@ CFLAGS +=3D -Wall -O0 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) LDLIBS +=3D -lcap =20 -TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test +TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test listns_test =20 include ../lib.mk =20 $(OUTPUT)/ns_active_ref_test: ../filesystems/utils.c +$(OUTPUT)/listns_test: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c new file mode 100644 index 000000000000..cb42827d3dfe --- /dev/null +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +/* + * Test basic listns() functionality with the unified namespace tree. + * List all active namespaces globally. + */ +TEST(listns_basic_unified) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, /* All types */ + .spare2 =3D 0, + .user_ns_id =3D 0, /* Global listing */ + }; + __u64 ns_ids[100]; + ssize_t ret; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + + /* Should find at least the initial namespaces */ + ASSERT_GT(ret, 0); + TH_LOG("Found %zd active namespaces", ret); + + /* Verify all returned IDs are non-zero */ + for (ssize_t i =3D 0; i < ret; i++) { + ASSERT_NE(ns_ids[i], 0); + TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); + } +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 130922C0294; Wed, 22 Oct 2025 16:09:22 +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=1761149363; cv=none; b=efTIpoZzWuRtngLEWpYaLgwWo1/tkJRrpvxVsc6xIHXgT0p5zf9DWnwHrJPcKAynvR26dxMOm9YEARPRw6CrvcoawIS7tnJm3t8/yOIoNuIaqDtwpH60axHsDrN7aPWqGzvORAFhctv37Pl2aWUCWfOdoYbS0lJ4jugb1f//Mac= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149363; c=relaxed/simple; bh=gPBGu8BceJ6oHRtyp7iwBf16DUj5zY+HNikOeiNBVYw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=muqCJbh7jPH92qP06wHC0FUENfvsOnyE1i88BAc86Ll1FVVqmzeUkOZLXe3xmNq9OrXNDCyT6Rzo9iMKPLZcXhXJZLoen3QqrJ97G0rICwh6vWK8m0BPxi6sFFKt6H5uryrURbfkpb1Vi0Ckx5o5CXRSU39q0+6eaBv7ApC2V/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qwpeLoQw; 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="qwpeLoQw" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBD33C4CEE7; Wed, 22 Oct 2025 16:09:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149362; bh=gPBGu8BceJ6oHRtyp7iwBf16DUj5zY+HNikOeiNBVYw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qwpeLoQwHUP+jIbSHho17fazbBhdWrnY8PGq+1hRylkJ62nGHDyDISgaU3DzgVtB2 Mu45jdUNVK/3HfDWYjiuXw5so1XA/mt8y20HxGf871d03AaV4rOY7VVPvqP+UDcEY0 C1vC4L1FWSWkn0Y8zmSgTVU/Rf/ZM6F4aXNjPFxuZn9qdLM/F5UlLaWdiYqusdgV5j HLHiOfMQL5zvgYv43xcIFxBFt57pSsK91yjGULpP9x5Wivvm3xzpQF+ThpNavugtYY UCt1xNgt3dam4l//GaQ5FxWeK+cIUjKwRRO/TAZoksgxr3e0fwGgaFak4t2CvyE0PQ jHpLLi2u5bRUA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:15 +0200 Subject: [PATCH v2 37/63] selftests/namespaces: second listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-37-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2143; i=brauner@kernel.org; h=from:subject:message-id; bh=gPBGu8BceJ6oHRtyp7iwBf16DUj5zY+HNikOeiNBVYw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjW+LXlaP1l/9aAv5zu5RFF7ou+VXKfPbJFa+fsx T1eR+L3dJSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExk00RGhqVsy1W5JHcekp/e NqvuidKDt38WO8drbZQ7cTnyUJNNnRkjw5pgM7bJ0wo2+7KKHnTPltxu/eas9ow3Qao6DYumTXq 8lwsA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 test listns() with type filtering. List only network namespaces. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 61 ++++++++++++++++++++= ++++ 1 file changed, 61 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index cb42827d3dfe..64249502ac49 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -54,4 +54,65 @@ TEST(listns_basic_unified) } } =20 +/* + * Test listns() with type filtering. + * List only network namespaces. + */ +TEST(listns_filter_by_type) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, /* Only network namespaces */ + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[100]; + ssize_t ret; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + ASSERT_GE(ret, 0); + + /* Should find at least init_net */ + ASSERT_GT(ret, 0); + TH_LOG("Found %zd active network namespaces", ret); + + /* Verify we can open each namespace and it's actually a network namespac= e */ + for (ssize_t i =3D 0; i < ret && i < 5; i++) { + struct nsfs_file_handle nsfh =3D { + .ns_id =3D ns_ids[i], + .ns_type =3D CLONE_NEWNET, + .ns_inum =3D 0, + }; + struct file_handle *fh; + int fd; + + fh =3D (struct file_handle *)malloc(sizeof(*fh) + sizeof(nsfh)); + ASSERT_NE(fh, NULL); + fh->handle_bytes =3D sizeof(nsfh); + fh->handle_type =3D 0; + memcpy(fh->f_handle, &nsfh, sizeof(nsfh)); + + fd =3D open_by_handle_at(-10003, fh, O_RDONLY); + free(fh); + + if (fd >=3D 0) { + int ns_type; + /* Verify it's a network namespace via ioctl */ + ns_type =3D ioctl(fd, NS_GET_NSTYPE); + if (ns_type >=3D 0) { + ASSERT_EQ(ns_type, CLONE_NEWNET); + } + close(fd); + } + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 8EDDF357A4D; Wed, 22 Oct 2025 16:09:28 +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=1761149368; cv=none; b=R+ejym+hBRLyQDqBMwhqwdj3Te0BFFle+puiG6U8/KgXJ2eMUBsEhEFwkK3Kl8/WxBTgRj9TXJlc/a5Kz7+yq5qYCwXHp45pGvZ5lNyl4ITF3S1JZpp/86XeWTLlRlcAY5LbsAyEg51Gz2J5TFa8eefZRbGKKqXEt21hFJ1bPe8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149368; c=relaxed/simple; bh=16wgRCEaRGE6KnaGWYUsE3X1jinLIZr1ZBK0aXw4RfM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=q7Obk/rYXHcngLxnQLrTx1PHaTiaQeEVHlziuJqUAtVL1uN8R2laM32sMwtaaKisIDC8hyo1sjFkGj4KQMRGcnPog5oiSaPvFlQ/7fQL4JSGTj9vs9gM1m2aq4pJty6yzzi/LigVqyaaUpaSL6Vf4nXsngaSDAxuHeui/0BgYrU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dQaucCEg; 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="dQaucCEg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 065E8C4CEFD; Wed, 22 Oct 2025 16:09:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149368; bh=16wgRCEaRGE6KnaGWYUsE3X1jinLIZr1ZBK0aXw4RfM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dQaucCEg9zWuTo2j0GT7Yfn1WV4C4miqTbNJWueKuGma6eAIjxGqViOm6Xm5qfYr7 9BVhyyQORFkLWcbvtZmfoCuUGY11P6mDhenyWUItdf44QuiUdfLBHjpsd0X3PrNzgm spubxGcBJwjnBGTKS1sIBVatQnHBVncrMQ2pX7mkEUXVEaD+w3Rl2pmK+FxKYtprEB 9GrPO1Qpt01gofiqaT75trr5+mlZBGH54RcCUotil1L32ksTie0Y3f4D1nIra8JzOw Lupxp/KVw0y4wDHhp5MV93qD9/P99pIk6kjD6HbNpHGef6KjmM11blWXXXQcdRdw3u z2K/1uOmXUSNQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:16 +0200 Subject: [PATCH v2 38/63] selftests/namespaces: third listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-38-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2006; i=brauner@kernel.org; h=from:subject:message-id; bh=16wgRCEaRGE6KnaGWYUsE3X1jinLIZr1ZBK0aXw4RfM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjWtW6FktvaaQcmmrk/evDnckrFYeE1mYfdst9uv bOEXYPdtKOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAijy4xMnzqrE1zLFl/o2/m g2O23zZuXnlApmTqm2ulKz0OFS+coPaPkeHgipure3Qkjy2pb9fZPefI9jMh4Vfu7W/Olpznz33 NX4oLAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() pagination. List namespaces in batches. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 53 ++++++++++++++++++++= ++++ 1 file changed, 53 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index 64249502ac49..7dff63a00263 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -115,4 +115,57 @@ TEST(listns_filter_by_type) } } =20 +/* + * Test listns() pagination. + * List namespaces in batches. + */ +TEST(listns_pagination) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 batch1[2], batch2[2]; + ssize_t ret1, ret2; + + /* Get first batch */ + ret1 =3D sys_listns(&req, batch1, ARRAY_SIZE(batch1), 0); + if (ret1 < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + ASSERT_GE(ret1, 0); + + if (ret1 =3D=3D 0) + SKIP(return, "No namespaces found"); + + TH_LOG("First batch: %zd namespaces", ret1); + + /* Get second batch using last ID from first batch */ + if (ret1 =3D=3D ARRAY_SIZE(batch1)) { + req.ns_id =3D batch1[ret1 - 1]; + ret2 =3D sys_listns(&req, batch2, ARRAY_SIZE(batch2), 0); + ASSERT_GE(ret2, 0); + + TH_LOG("Second batch: %zd namespaces (after ns_id=3D%llu)", + ret2, (unsigned long long)req.ns_id); + + /* If we got more results, verify IDs are monotonically increasing */ + if (ret2 > 0) { + ASSERT_GT(batch2[0], batch1[ret1 - 1]); + TH_LOG("Pagination working: %llu > %llu", + (unsigned long long)batch2[0], + (unsigned long long)batch1[ret1 - 1]); + } + } else { + TH_LOG("All namespaces fit in first batch"); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 95C4C37DBD1; Wed, 22 Oct 2025 16:09:33 +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=1761149373; cv=none; b=Nj1b4jdhht1iv7ttIkjqmjrpHYhaYKdc7Me8y9ihPyY3WQ8EtuU7F79bhNA2yeWJx7uFJqb9Lu+2pI6M8jgBqPcW4Nvtr/Z7b3xZEQxU+5ioMztnKJ5386vaP9kwbN8GWaB4dBb5UODClFQa9Q9UP1WeJaWXJYVZWCjG4Y3xz7U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149373; c=relaxed/simple; bh=UxNNzwwfXU08oQlPAvQ0Gj3cx0fWVzo9FwN6OUP3IWE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sPwwzxgnY7IdWUITlfF4FisNd2QJ1kHrsjb0Ww5pUloHx/VzVwnQbX50GWPTkjBQ2D/WLWVkihg007flEXgzoPEy73Y39xrPx2yvRYMtE7HYYPZVNTeK2UF/ijHuwFPtk6Fk2pu6J5TCjquBaDQxd0qXi4QCQyXSQ5ytbjY3vTQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pbPziWur; 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="pbPziWur" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8FDE9C4CEE7; Wed, 22 Oct 2025 16:09:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149373; bh=UxNNzwwfXU08oQlPAvQ0Gj3cx0fWVzo9FwN6OUP3IWE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pbPziWurzZXsIhxuB+HDNzhxnMAdP+UkGsueFIkOGWKkNIS2oPe2dn1qyYb5LEDWT Jw6uje+s9hTZf9vqdbrRcOWa2eqMwLljmM+wRDxEmsWDV0Msug9IXjWcrB7dpGGuGc 7MPHvwM/EuhokGIVvEvLEGdoLax+ujvxANqNvqx8MBIJ6n4lB1lYAVp7JzRc37hv8V 2Ht0KDPbLgo+YO0WTdR3faDP9Y+cb8nG3fVkApMa7So/ScmWXkouYjQloL4bH3ZnvL c9DFXh9KG5KwaMoU+903V5IVWnsiDhrqEX/YjJPByyJaW3AiBryx6LPPLfDtSbo8y3 /8l7TgG80RlgQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:17 +0200 Subject: [PATCH v2 39/63] selftests/namespaces: fourth listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-39-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1513; i=brauner@kernel.org; h=from:subject:message-id; bh=UxNNzwwfXU08oQlPAvQ0Gj3cx0fWVzo9FwN6OUP3IWE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj2corZm0rB+u7KDz/2BH3t+5/J47IofP2zhbf2T jWzM/v8rqOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAikosZGV7HXuri0FOWuvBa VOlHtfkVqa7Ez1fFD5Xqq+0TO+Mt58bwh2fqP/3dJ7e9Pn/4b7OJlSvz9w+/lA8f3FMq8ij2hHV BIR8A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() with LISTNS_CURRENT_USER. List namespaces owned by current user namespace. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 33 ++++++++++++++++++++= ++++ 1 file changed, 33 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index 7dff63a00263..457298cb4c64 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -168,4 +168,37 @@ TEST(listns_pagination) } } =20 +/* + * Test listns() with LISTNS_CURRENT_USER. + * List namespaces owned by current user namespace. + */ +TEST(listns_current_user) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, + .spare2 =3D 0, + .user_ns_id =3D LISTNS_CURRENT_USER, + }; + __u64 ns_ids[100]; + ssize_t ret; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + ASSERT_GE(ret, 0); + + /* Should find at least the initial namespaces if we're in init_user_ns */ + TH_LOG("Found %zd namespaces owned by current user namespace", ret); + + for (ssize_t i =3D 0; i < ret; i++) + TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 EB41C27A465; Wed, 22 Oct 2025 16:09:38 +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=1761149379; cv=none; b=tp5Xo0yAG06ZSiGx6BRGKZU1hZESC9SK9ZholYOuEPnllTKpVaiO9hu9YEU9Ih1VNr8ihnp6m/Jb2HX7bSnXdVEq0gJI/DpF8QpMHYkwUBM5UCFwaoboQcvgY5z5d4J8slR6xd1d+VyB2RgZIOITSN323NULhRVQ0HoJsdl5eHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149379; c=relaxed/simple; bh=8oUiPySwgEUEU/08UclINQ2fnNQXoryHtImyDaO/kZg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LGfRDR3ZUSU3QOiiKYV5LQfpUE3GSYI0iKyYi5jpUMWWFdpqszlEf7HSY6UN2gUuWpPFf1OLv+sD1/sy9c9z8V9auE3rHW+RttUTcIMum0ke+iF0JdpDoYj3fZgxORA4wl4tBEEcalOXLvZZKiTjYUtdzHy1Xk1Lv+XaJNDLhT4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=b9BI9zeR; 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="b9BI9zeR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ECAB2C4CEE7; Wed, 22 Oct 2025 16:09:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149378; bh=8oUiPySwgEUEU/08UclINQ2fnNQXoryHtImyDaO/kZg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=b9BI9zeRJlolNXcp0GbP2UqWwI/wWzKIfLVBfPG6P6fd6maXSc1H5ONlwSwybGuHS k9URvwdN7VFIaKkeYAXXCTsOoSIDQ8QIknZ1eBwONGVXqgAGUtYlHogba0hO15Q0ta zsX9j6ZOs3ourdhUU5LU1ngITYwCQ4sLamUY/X6zve1bee8dDIyuxxU+oxML15JOHr l65SlEUbQPW9Wu36GYqi15mEt8VN2l+mpU2O6Jy6Df4bLFsxXLK+jJBqUqVq59vjfm PMOVdcjoiDsDiljlVRB8gmwqW8b7YyAzKU71IPyWvDJRq+A3vOCalW3jZzX6k2jxlQ 0PgIwhbvqkt8A== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:18 +0200 Subject: [PATCH v2 40/63] selftests/namespaces: fifth listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-40-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3866; i=brauner@kernel.org; h=from:subject:message-id; bh=8oUiPySwgEUEU/08UclINQ2fnNQXoryHtImyDaO/kZg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj2o9Utw1uHP0rp4uaDQT0Xz8VPPLrLfcrm316SV 88fyy1R6yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiIahDDH74ZHl+qknqORr7y 2/kz36EjVJajSsCxZuKbfQr6tmI68YwMJ25xuCiFLv9qcsaoxtcnOHLp/r89RxfKsagtXdbaf+s 5IwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that listns() only returns active namespaces. Create a namespace, let it become inactive, verify it's not listed. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 126 +++++++++++++++++++= ++++ 1 file changed, 126 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index 457298cb4c64..e854794abe56 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -201,4 +201,130 @@ TEST(listns_current_user) TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); } =20 +/* + * Test that listns() only returns active namespaces. + * Create a namespace, let it become inactive, verify it's not listed. + */ +TEST(listns_only_active) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids_before[100], ns_ids_after[100]; + ssize_t ret_before, ret_after; + int pipefd[2]; + pid_t pid; + __u64 new_ns_id =3D 0; + int status; + + /* Get initial list */ + ret_before =3D sys_listns(&req, ns_ids_before, ARRAY_SIZE(ns_ids_before),= 0); + if (ret_before < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + ASSERT_GE(ret_before, 0); + + TH_LOG("Before: %zd active network namespaces", ret_before); + + /* Create a new namespace in a child process and get its ID */ + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 ns_id; + + close(pipefd[0]); + + /* Create new network namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get its ID */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &ns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send ID to parent */ + write(pipefd[1], &ns_id, sizeof(ns_id)); + close(pipefd[1]); + + /* Keep namespace active briefly */ + usleep(100000); + exit(0); + } + + /* Parent reads the new namespace ID */ + { + int bytes; + + close(pipefd[1]); + bytes =3D read(pipefd[0], &new_ns_id, sizeof(new_ns_id)); + close(pipefd[0]); + + if (bytes =3D=3D sizeof(new_ns_id)) { + __u64 ns_ids_during[100]; + int ret_during; + + TH_LOG("Child created namespace with ID %llu", (unsigned long long)new_= ns_id); + + /* List namespaces while child is still alive - should see new one */ + ret_during =3D sys_listns(&req, ns_ids_during, ARRAY_SIZE(ns_ids_during= ), 0); + ASSERT_GE(ret_during, 0); + TH_LOG("During: %d active network namespaces", ret_during); + + /* Should have more namespaces than before */ + ASSERT_GE(ret_during, ret_before); + } + } + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + + /* Give time for namespace to become inactive */ + usleep(100000); + + /* List namespaces after child exits - should not see new one */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + TH_LOG("After: %zd active network namespaces", ret_after); + + /* Verify the new namespace ID is not in the after list */ + if (new_ns_id !=3D 0) { + bool found =3D false; + + for (ssize_t i =3D 0; i < ret_after; i++) { + if (ns_ids_after[i] =3D=3D new_ns_id) { + found =3D true; + break; + } + } + if (found) { + TH_LOG("Warning: Namespace %llu still active after process exit", + (unsigned long long)new_ns_id); + } + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 BF2052773D2; Wed, 22 Oct 2025 16:09: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=1761149384; cv=none; b=LlB3kVqhpcIVuHPrggLivEchkXD23b+3MihBWAUv0LHOsjAYQudPXqupaV+al70DVrpleERTI+xeWQMor9iasUE0+GqDeV4nqJYPW+l35/vivZvE/hKX1YzBG+f8idrgK6B+MvW65ZOmK259JRG4JoopJ2UBGcb1FAE+BGwy03s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149384; c=relaxed/simple; bh=4vBs0iC1GliO+F4XrLBJxRIywFUw/24vdpBSDdc51/s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZDqvT4dtN6YuUTVhCxP8yiBkgFDhWcbMqk3Yek7B2Pe6viz0bHZ8aoAdcRUDiDsE3OfxHWk7vFb7PF3o/vkpEW9X7VFyM8Rk570aYoQgTsiotdMMUnpfyzaTlALhOVN9HqrZJ99wRun3hFNyq79aTi1Y9aEdeCCfQgZy9z664Ic= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=segBop61; 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="segBop61" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 487EFC116B1; Wed, 22 Oct 2025 16:09:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149384; bh=4vBs0iC1GliO+F4XrLBJxRIywFUw/24vdpBSDdc51/s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=segBop61K5CiFuINcw38i+jzw/Ejfd4any0YnKLytyJjAfjWwfjj5bsytutEQzXOH NZ8UK/ak2PNLzajBn3fTTcmW1lOWkae1lcRCFl6L4GcHsTO5kJMyAmOlsMtB0XNGr+ vGGF3bv2Vrt8ZUDNZmA9qOJ5rweRGu+vmt/hIZg144J4CiYp1vGUXEhM/wyYzyFJke zDVNmznDs7z7sReoyEoy0V74F2pLhd/Ncrio0CpfCTroeFW4EWtgsVJ5nbRTaIgOMu 2grX3+W2pRWCoG7JwY+mGJo+7e8yTGWn1bWu9rKFbC+5B/tZ8qUv5CfIxMRyxhkXDF 2GFFzEcc/g8qQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:19 +0200 Subject: [PATCH v2 41/63] selftests/namespaces: sixth listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-41-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3170; i=brauner@kernel.org; h=from:subject:message-id; bh=4vBs0iC1GliO+F4XrLBJxRIywFUw/24vdpBSDdc51/s=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgm+EP3RaW4VNXkwo8RsRkOefM1N1h9Wn1w4p8n6 xoLD5xv7ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIkfWMDGe/iu68J+63qmn7 Wa2Mtw/+cd6ZyBzy4Al/xdy92R/eljAx/E+NvrDqfVfew6Xie0KTrMp+hc63edu27YqF7qke9V1 bZ7ADAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() with specific user namespace ID. Create a user namespace and list namespaces it owns. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 109 +++++++++++++++++++= ++++ 1 file changed, 109 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index e854794abe56..e1e90ef933cf 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -327,4 +327,113 @@ TEST(listns_only_active) } } =20 +/* + * Test listns() with specific user namespace ID. + * Create a user namespace and list namespaces it owns. + */ +TEST(listns_specific_userns) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, + .spare2 =3D 0, + .user_ns_id =3D 0, /* Will be filled with created userns ID */ + }; + __u64 ns_ids[100]; + int pipefd[2]; + pid_t pid; + int status; + __u64 user_ns_id =3D 0; + int bytes; + ssize_t ret; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 ns_id; + char buf; + + close(pipefd[0]); + + /* Create new user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &ns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send ID to parent */ + write(pipefd[1], &ns_id, sizeof(ns_id)); + + /* Create some namespaces owned by this user namespace */ + unshare(CLONE_NEWNET); + unshare(CLONE_NEWUTS); + + /* Wait for parent signal */ + read(pipefd[1], &buf, 1); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + bytes =3D read(pipefd[0], &user_ns_id, sizeof(user_ns_id)); + + if (bytes !=3D sizeof(user_ns_id)) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get user namespace ID from child"); + } + + TH_LOG("Child created user namespace with ID %llu", (unsigned long long)u= ser_ns_id); + + /* List namespaces owned by this user namespace */ + req.user_ns_id =3D user_ns_id; + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + if (ret < 0) { + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + if (errno =3D=3D ENOSYS) { + SKIP(return, "listns() not supported"); + } + ASSERT_GE(ret, 0); + } + + TH_LOG("Found %zd namespaces owned by user namespace %llu", ret, + (unsigned long long)user_ns_id); + + /* Should find at least the network and UTS namespaces we created */ + if (ret > 0) { + for (ssize_t i =3D 0; i < ret && i < 10; i++) + TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); + } + + /* Signal child to exit */ + close(pipefd[0]); + waitpid(pid, &status, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 E74BB3587CD; Wed, 22 Oct 2025 16:09:49 +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=1761149390; cv=none; b=iDR//icmcKSc3LztYSeNG41Y3sI/SaIwhAf5fbH0UcAAiEY49TXpK26fHODL2QFn8tgP38/GukV4GKt5cuehNAiUUQqE+b7kLfrOZ2ImpRN5CWBQrSopf57nsr5VtsnAUPwWEpjPfpqbmlOGvyq5aMLMTeV3Ailm6FbqyPoBZhM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149390; c=relaxed/simple; bh=zSBiD0DmDYcPFHCmh4S9YgYEBZCkP3T4DUO3iD7+Aw0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sF7C/qLwD6EXaQl0GLX6eKeBCWwcLlP8gfgpqjaJmFxLDtEWOYgU1Bh68uanAlni9rCgUcN48FHVHRj773uqtnllhQyvoPBCN1mC1XquZyT7Z+8nXp4Uv5SkRcqbmYI771qsLTS6WcjqUcNiSNS5Ox4B1uGFHvIDVwuDJyRn4XA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JWuMwFcf; 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="JWuMwFcf" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C5DF5C4CEE7; Wed, 22 Oct 2025 16:09:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149389; bh=zSBiD0DmDYcPFHCmh4S9YgYEBZCkP3T4DUO3iD7+Aw0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JWuMwFcfFVHeohkDUR7yKhVbNjItZsw7rpK1Fg8MObxzX+C+i1Vvnf4ghdAty6TIv JhlqZS3z5NUEV56kHwkN8L5daIlecaMhX3RQk89Y7hUddeVmDqQpa67dDw4FutnnhZ tGy9gI8oYjq9UCTv2XgbR4cxma4N4DPVkS/LSKsxUQf1y5ACjqSYGR6pgparv3C1BR 0qbD5m5vqEZ8m2l3QA/MDaV/MPv4vD3iu0BNjU70/oT5VHLb2TW31sD52bZ6jwMMEr OgtSoR0OLns/YnwNhgNkiBE9eb9di8UvFLVLNIewwLgw5f1yE8T7NjNz+2XWS23CVz iyxfM3z51xeSQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:20 +0200 Subject: [PATCH v2 42/63] selftests/namespaces: seventh listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-42-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1404; i=brauner@kernel.org; h=from:subject:message-id; bh=zSBiD0DmDYcPFHCmh4S9YgYEBZCkP3T4DUO3iD7+Aw0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHh27XyDevCyzhX1fhkcfj6LKvdob1qQ9e3cr7zY1 mdMsqzyHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABORnsbIsKdg+um162OzBYRu zXx0YfO9BaJZ03TWlmzWz1RbE3YjeC0jw5HOL8rfn5loR+x4foJznUU/T62J9roz61kWJ7Cs89o 8gREA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() with multiple namespace types filter. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 31 ++++++++++++++++++++= ++++ 1 file changed, 31 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index e1e90ef933cf..6afffddf9764 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -436,4 +436,35 @@ TEST(listns_specific_userns) waitpid(pid, &status, 0); } =20 +/* + * Test listns() with multiple namespace types filter. + */ +TEST(listns_multiple_types) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET | CLONE_NEWUTS, /* Network and UTS */ + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[100]; + ssize_t ret; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s (errno=3D%d)", strerror(errno), errno); + ASSERT_TRUE(false); + } + ASSERT_GE(ret, 0); + + TH_LOG("Found %zd active network/UTS namespaces", ret); + + for (ssize_t i =3D 0; i < ret; i++) + TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 633D8358D26; Wed, 22 Oct 2025 16:09:55 +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=1761149395; cv=none; b=qVChMW+yr2W4nZDxk0Bi2yEKD7xAZgBtdDvs2s08gxfnbEB5QlYHK76kGCKBZfxvx+dxzGrHxV/DSQXyp5Fen8PJlgDWv4gigWvijp+f9DckRFDlIgTZeYJFGWVj9xRol/fHqK4KYvWeOD9X+aDM8BAfe2DyqoWVgmYHxASj0J0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149395; c=relaxed/simple; bh=V4fLSyijbME7l6bI490uSVspsEhpOL9UHRqTJM6dwA8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=q6Yrt2AchikRDyYMkJXtl1zap6TKJWYJV33E6p2J+IROmnx5pL7q0/MJIG7DJqmuvxULl31YqCK7yEghOfK70eEo4FYOccacEcNzcg2OdNzbWJPi0Wiq3HUs6uOG5e2XkVQLMN44bngXxpBJzri6Xb6xLuWwCS92JqwZdjMdOnE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r9+5Q+wQ; 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="r9+5Q+wQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1B2A5C4CEF7; Wed, 22 Oct 2025 16:09:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149395; bh=V4fLSyijbME7l6bI490uSVspsEhpOL9UHRqTJM6dwA8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=r9+5Q+wQtrvIl/42nprWF6mcRZjwgXTGkTMjLqYZyHohNs+fbs9fTzMm1Fwpma9gE qVa6l7QLDO3EgOZoEf78DDt+tnrCH8H3iysm0Q4dhx1zco7A4cMbVjysm1RjlmheqS FOAtWWE/KBoZL2PjGtZat0OTYM/3GC/wj4eAb03Rl8v1EnQ54uu1x8QFw8XY5Rimd2 7O9xGSbPduNKQmOR4G/baupt5JJPfM8QzFeVK79l0Nfjs8j5NNDl9P4zdqpkPz/nn4 IiWD2+GG4uqmv1yZmvItLUcq6mCkv+w254tIICqWpYvygcskUAqboWryTAzv1DfZdQ 78Vlo/P4yGpYw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:21 +0200 Subject: [PATCH v2 43/63] selftests/namespaces: ninth listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-43-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3882; i=brauner@kernel.org; h=from:subject:message-id; bh=V4fLSyijbME7l6bI490uSVspsEhpOL9UHRqTJM6dwA8=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi2/fNrydyog4pnb1wL0eLa/EFrf+TZiCkZPouSF p9avSOlqqOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiB9Yx/Hd03X7Srb9Iwqt7 RcX5/Op8nefPj5f/15m9IeNQ68bXLrUMf7jtnb7Ly5y36XDzFV6rPHHi2q1uR6TXRpnI3831e86 3nQ8A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that hierarchical active reference propagation keeps parent user namespaces visible in listns(). Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 135 +++++++++++++++++++= ++++ 1 file changed, 135 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index 6afffddf9764..ddf4509d5cd6 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -467,4 +467,139 @@ TEST(listns_multiple_types) TH_LOG(" [%zd] ns_id: %llu", i, (unsigned long long)ns_ids[i]); } =20 +/* + * Test that hierarchical active reference propagation keeps parent + * user namespaces visible in listns(). + */ +TEST(listns_hierarchical_visibility) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWUSER, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 parent_ns_id =3D 0, child_ns_id =3D 0; + int pipefd[2]; + pid_t pid; + int status; + int bytes; + __u64 ns_ids[100]; + ssize_t ret; + bool found_parent, found_child; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + char buf; + + close(pipefd[0]); + + /* Create parent user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &parent_ns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Create child user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &child_ns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send both IDs to parent */ + write(pipefd[1], &parent_ns_id, sizeof(parent_ns_id)); + write(pipefd[1], &child_ns_id, sizeof(child_ns_id)); + + /* Wait for parent signal */ + read(pipefd[1], &buf, 1); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + /* Read both namespace IDs */ + bytes =3D read(pipefd[0], &parent_ns_id, sizeof(parent_ns_id)); + bytes +=3D read(pipefd[0], &child_ns_id, sizeof(child_ns_id)); + + if (bytes !=3D (int)(2 * sizeof(__u64))) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace IDs from child"); + } + + TH_LOG("Parent user namespace ID: %llu", (unsigned long long)parent_ns_id= ); + TH_LOG("Child user namespace ID: %llu", (unsigned long long)child_ns_id); + + /* List all user namespaces */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + if (ret < 0 && errno =3D=3D ENOSYS) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "listns() not supported"); + } + + ASSERT_GE(ret, 0); + TH_LOG("Found %zd active user namespaces", ret); + + /* Both parent and child should be visible (active due to child process) = */ + found_parent =3D false; + found_child =3D false; + for (ssize_t i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D parent_ns_id) + found_parent =3D true; + if (ns_ids[i] =3D=3D child_ns_id) + found_child =3D true; + } + + TH_LOG("Parent namespace %s, child namespace %s", + found_parent ? "found" : "NOT FOUND", + found_child ? "found" : "NOT FOUND"); + + ASSERT_TRUE(found_child); + /* With hierarchical propagation, parent should also be active */ + ASSERT_TRUE(found_parent); + + /* Signal child to exit */ + close(pipefd[0]); + waitpid(pid, &status, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6195337EE08; Wed, 22 Oct 2025 16:10: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=1761149400; cv=none; b=icMn9qeXt38zkGsDJ/gpa3kY/GOYeq2CPX8HPzdzdrZQXDhN6RBBYYI5Mi39ZWZvhJuGdAH4fMfPC26fbMoPAUfMll+kSX1yTZ2fZmBoNatdZRf1xKR+XDIYyQJdNGtB/o3HWEuVJl6lYp6Q8KIm0eMarZ+lQhUr3CQmwgAlzi4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149400; c=relaxed/simple; bh=77H7R88MI0EUUkshwD3/5/W86ZbXu7/L538OO/0/fLQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NXQlJByz3VVHrDV151GX6659fj2FNmTEUi77Z3p73bTIrrULKLF+BQsodObhPE15cXKy9alJRdcodIMK+dHXzfHpYGwPEd5YzTPg6lkl+4oLlybgjVF85072g+h4BfYGyQpEfVHRVtmLe8XpEx+m4+We0kY5wGIrGK2uAz/h0E8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=R4eKSwkQ; 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="R4eKSwkQ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8371FC4CEE7; Wed, 22 Oct 2025 16:09:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149400; bh=77H7R88MI0EUUkshwD3/5/W86ZbXu7/L538OO/0/fLQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=R4eKSwkQDqZaCtIWAOSE7NRGorNZP/AGowKJHORKcQmyMDbgfuDjGDTXtniVh/zlE 1mMt4IbNhlg7hgorI+r2cxBimnLQkrRbTAJMElftDLuTeuR2XtX1Bf+pOMsuraGjSh 5wFJ5qyg2X79Z5MfKojOIPQDt0sYhchD/XmmufoUzT9OlGO/ObNBqAQrpZsfBidSrQ wo1utPJ0ZV0E61p4Q0lw10Lc4Z0TN4FGIBTn4gGXpqKED0yhonSMPN8AyZ6zEJp2q8 0/NDpvH9y+DY07OQ2J1ga/kgSIXXd4KFv5o/eXh65aBoBNtrPEzeLGRGwRvI/7Ie1q dWXvO0ksr9RTg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:22 +0200 Subject: [PATCH v2 44/63] selftests/namespaces: ninth listns() test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-44-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1852; i=brauner@kernel.org; h=from:subject:message-id; bh=77H7R88MI0EUUkshwD3/5/W86ZbXu7/L538OO/0/fLQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjmFPlIsIl7adLlO+t4Z4RPfOLg+f18ttJ2lfU3a 5+smT3rQkcpC4MYF4OsmCKLQ7tJuNxynorNRpkaMHNYmUCGMHBxCsBEzp1lZPiwMHry6veHIldw dToH8bM+dn98VvHsGtH7/2WNrrxYN+cTI8PBOfY/KhuurhK5/OTU6RKby7vjJz1ql2V0WMTAvj1 bz58LAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test error cases for listns(). Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/listns_test.c | 51 ++++++++++++++++++++= ++++ 1 file changed, 51 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index ddf4509d5cd6..eb44f50ab77a 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -602,4 +602,55 @@ TEST(listns_hierarchical_visibility) waitpid(pid, &status, 0); } =20 +/* + * Test error cases for listns(). + */ +TEST(listns_error_cases) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[10]; + int ret; + + /* Test with invalid flags */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0xFFFF); + if (ret >=3D 0 || errno =3D=3D ENOSYS) { + if (errno !=3D ENOSYS) { + TH_LOG("Warning: Expected EINVAL for invalid flags, got success"); + } + } else { + ASSERT_EQ(errno, EINVAL); + } + + /* Test with NULL ns_ids array */ + ret =3D sys_listns(&req, NULL, 10, 0); + if (ret >=3D 0) { + TH_LOG("Warning: Expected EFAULT for NULL array, got success"); + } + + /* Test with invalid spare field */ + req.spare =3D 1; + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret >=3D 0 || errno =3D=3D ENOSYS) { + if (errno !=3D ENOSYS) { + TH_LOG("Warning: Expected EINVAL for non-zero spare, got success"); + } + } + req.spare =3D 0; + + /* Test with huge nr_ns_ids */ + ret =3D sys_listns(&req, ns_ids, 2000000, 0); + if (ret >=3D 0 || errno =3D=3D ENOSYS) { + if (errno !=3D ENOSYS) { + TH_LOG("Warning: Expected EOVERFLOW for huge count, got success"); + } + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 9FCD437EE2F; Wed, 22 Oct 2025 16:10:05 +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=1761149405; cv=none; b=ueMdRK/fDFKJMTLWxc3VJXvUGu5zg7y2vKTyMwo2z/bQiJG0jaSI+7GfxAamfLcJJE+FlLAYIzl9RAkbAltLv2SOK4ZyxbIZ0GKGITPHZst8mHrxbmtcD/OELx0dEs09+S2pZy77gB3MpB9Slx7B9JoVdeFaUAOYY8FgfOpd8JU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149405; c=relaxed/simple; bh=5YqEIrDVXqnPIx61aY2UFkn7520IFi2bPLuDDoqZd4M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=spVX0JLy0Lj7N3NOQc7hz+Dr47I9Trhpyi+RwO/CQPvtoPksW+K2CvVDR+ofqh6uaTj501xze4jiK8yv5egv6Zpp56T1n5I6S3HeTkKQIdcSh2u1onmyq0gtcjidCn1PmXUvgzgOk7RTNW38na+OswL0GsFPHkfI/uJeFt4I8ns= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IkQBdlrq; 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="IkQBdlrq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B5700C4CEE7; Wed, 22 Oct 2025 16:10:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149405; bh=5YqEIrDVXqnPIx61aY2UFkn7520IFi2bPLuDDoqZd4M=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IkQBdlrq/Foh5U4Si0HKsuRF2nrTlbOKWCMtKyopgFeyUoIR8G1BnEEGtvXYRbbie ZB/x5/qgnqMem9FgkHzGbd9vgUMHfK/syK/lLjkEayhVPJFRMQrBBiCrvUg422cLQg w/9nhJJi+eu2MS98+n+IRuZOG5B8bYohKkZawdmnkq+3qgVQugOD78knMu2R4ACm5/ NrFh9cydNE0GX1bxw8KvBhx5pktqvrAGUQCWvJuddCknBQ+GQhzr89dCJak/4QHcox H/FK9Z265JTjKNZ6o/Uv8VDBvNi6Ka+Ffit+UrsfCaWmPNy023UZX+so8uPgYtQntD /LQqtalc6lUFQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:23 +0200 Subject: [PATCH v2 45/63] selftests/namespaces: first listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-45-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5030; i=brauner@kernel.org; h=from:subject:message-id; bh=5YqEIrDVXqnPIx61aY2UFkn7520IFi2bPLuDDoqZd4M=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgmFXGmnTHkXO/U4vmOQZ2y5drTjCQuVPnlrtpnt ngf3+mejlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIk0OTAyXEj9o6jj+VBCoat9 dlpU/lX7d9FOLmvfqbtIGqs0t8cpMzI09v6sONfOLL5y2tNvs0tOKHRxusWUfn+ffVHYoUxo21R mAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that unprivileged users can only see namespaces they're currently in. Create a namespace, drop privileges, verify we can only see our own namespaces. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 3 +- .../selftests/namespaces/listns_permissions_test.c | 134 +++++++++++++++++= ++++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index 5065f07e92c9..17f9c675a60b 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -3,3 +3,4 @@ file_handle_test init_ino_test ns_active_ref_test listns_test +listns_permissions_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index de708f4df159..2dd22bc68b89 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -2,10 +2,11 @@ CFLAGS +=3D -Wall -O0 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) LDLIBS +=3D -lcap =20 -TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test listns_test +TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test listns_test listns_permissions_test =20 include ../lib.mk =20 $(OUTPUT)/ns_active_ref_test: ../filesystems/utils.c $(OUTPUT)/listns_test: ../filesystems/utils.c +$(OUTPUT)/listns_permissions_test: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c new file mode 100644 index 000000000000..87ec71560d99 --- /dev/null +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +/* + * Test that unprivileged users can only see namespaces they're currently = in. + * Create a namespace, drop privileges, verify we can only see our own nam= espaces. + */ +TEST(listns_unprivileged_current_only) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[100]; + ssize_t ret; + int pipefd[2]; + pid_t pid; + int status; + bool found_ours; + int unexpected_count; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 our_netns_id; + bool found_ours; + int unexpected_count; + + close(pipefd[0]); + + /* Create user namespace to be unprivileged */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Create a network namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get our network namespace ID */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &our_netns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Now we're unprivileged - list all network namespaces */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* We should only see our own network namespace */ + found_ours =3D false; + unexpected_count =3D 0; + + for (ssize_t i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D our_netns_id) { + found_ours =3D true; + } else { + /* This is either init_net (which we can see) or unexpected */ + unexpected_count++; + } + } + + /* Send results to parent */ + write(pipefd[1], &found_ours, sizeof(found_ours)); + write(pipefd[1], &unexpected_count, sizeof(unexpected_count)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + found_ours =3D false; + unexpected_count =3D 0; + read(pipefd[0], &found_ours, sizeof(found_ours)); + read(pipefd[0], &unexpected_count, sizeof(unexpected_count)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespaces or run listns"); + } + + /* Child should have seen its own namespace */ + ASSERT_TRUE(found_ours); + + TH_LOG("Unprivileged child saw its own namespace, plus %d others (likely = init_net)", + unexpected_count); +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 22C6B3590C7; Wed, 22 Oct 2025 16:10:10 +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=1761149411; cv=none; b=kVooqoK9drDwiWylapN/9C5AI0Zi8ARtm8N+Y9Dxh0YkbOpVSU4+D7K6jc7jhNEGZC/vSoWJ22jHRs61UIpS3OwWNsN8BciVaUrAkrvq6bV+JsTx7TwCT4udugab0nv3thuo7EqWJr+s1ewJHWpE4etqxSKi+X8rgtBo8clKSlA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149411; c=relaxed/simple; bh=rZyevUn6hfyhcE1DB3cv3yJAhND3Rlxt9xlbt7Q4T1s=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=URu6oZxaOQMLqVi21L6l9BpV89MpdD94BZq4tAZ++o6cY4xbGHm0A86wCh2ySw2+lPWT/I2eWkFHfKYzKioCwUMV1wf5tsP/Cc+wC1p8jCneiL5iTFuz+9SA5SbROOWiieOJGSDY4nsD+R6+KOWoTOkpcXq6b6AeyM9nMU0X2rc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=aynBCV14; 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="aynBCV14" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 011EDC4CEE7; Wed, 22 Oct 2025 16:10:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149410; bh=rZyevUn6hfyhcE1DB3cv3yJAhND3Rlxt9xlbt7Q4T1s=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=aynBCV14drdvlkI5OVh+cSdoZLeVi/bTdUqgyN7c3RkCKDaZ+vwnfSIPPIZ5v+k2+ U0m9fnt0pUN1+J5sDp/hHwVJtveTwMlvZbmdxNNlf4AbkdomL1ZOj8yclNK6y3ZCpr sjAopqmouzgRc3hBKc+iC/rvt3lxB+2Q5H5OR0mqnr8k6cF+lat94pi8zILk/u5Xt4 myVVzsbBpPA+oiirsVywgKB0SjPdKabavkb49tjjMvpl9nj5PYsPm53UJ6mxLyXt1q rwvAqf9qLggKfAwlvSDgPu4Vr8r78mq5eeJlznXCYoSSCynlj1n0137RtxiAuW/c1t B3Cf3+iXR/5Bg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:24 +0200 Subject: [PATCH v2 46/63] selftests/namespaces: second listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-46-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3077; i=brauner@kernel.org; h=from:subject:message-id; bh=rZyevUn6hfyhcE1DB3cv3yJAhND3Rlxt9xlbt7Q4T1s=; b=kA0DAAoWkcYbwGV43KIByyZiAGj5AOfIqo/5x+ugoJC4nLGfrMBsvIibNo7EcJDWtGAtVxRHQ Yh1BAAWCgAdFiEEQIc0Vx6nDHizMmkokcYbwGV43KIFAmj5AOcACgkQkcYbwGV43KI0nAD/WFlN wFDkt6TQIIXbHcevpPbxDm3Lp9gD8OWj6b+YDRwBAN2RrRhb1dUXuKKmdEo0QxmJOc734pdoX8p 4YABB5ncB X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that users with CAP_SYS_ADMIN in a user namespace can see all namespaces owned by that user namespace. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 103 +++++++++++++++++= ++++ 1 file changed, 103 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 87ec71560d99..803c42fc76ec 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -131,4 +131,107 @@ TEST(listns_unprivileged_current_only) unexpected_count); } =20 +/* + * Test that users with CAP_SYS_ADMIN in a user namespace can see + * all namespaces owned by that user namespace. + */ +TEST(listns_cap_sys_admin_in_userns) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, /* All types */ + .spare2 =3D 0, + .user_ns_id =3D 0, /* Will be set to our created user namespace */ + }; + __u64 ns_ids[100]; + int pipefd[2]; + pid_t pid; + int status; + bool success; + ssize_t count; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 userns_id; + ssize_t ret; + int min_expected; + bool success; + + close(pipefd[0]); + + /* Create user namespace - we'll have CAP_SYS_ADMIN in it */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get the user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Create several namespaces owned by this user namespace */ + unshare(CLONE_NEWNET); + unshare(CLONE_NEWUTS); + unshare(CLONE_NEWIPC); + + /* List namespaces owned by our user namespace */ + req.user_ns_id =3D userns_id; + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + close(pipefd[1]); + exit(1); + } + + /* + * We have CAP_SYS_ADMIN in this user namespace, + * so we should see all namespaces owned by it. + * That includes: net, uts, ipc, and the user namespace itself. + */ + min_expected =3D 4; + success =3D (ret >=3D min_expected); + + write(pipefd[1], &success, sizeof(success)); + write(pipefd[1], &ret, sizeof(ret)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + success =3D false; + count =3D 0; + read(pipefd[0], &success, sizeof(success)); + read(pipefd[0], &count, sizeof(count)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespaces"); + } + + ASSERT_TRUE(success); + TH_LOG("User with CAP_SYS_ADMIN saw %zd namespaces owned by their user na= mespace", + count); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 4B88B37FC5B; Wed, 22 Oct 2025 16:10:15 +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=1761149416; cv=none; b=DRyr5u5tEHRdRZtCmlqdzfZ8GiNnJBw2QD/wbrTvmlCjuhzU8Bkq4Mmb59eKLfklEY8gGhDPwsUlavQaMa0Z9AJBh7T8MPwPLQwtsc5cmuh2FWqiJRt4tUL1c9N9DMv6an2mVV9FJCF4pld9bLiDgBXYvbvROxeS98V4m17HWEY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149416; c=relaxed/simple; bh=qOQpMwb8a6Ty7XQD33x8dOA998CFgN+vzt4Bsk/lfA4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dlSzAHorJzpHGQwWrOVwAG+2AlJgbjBc8euDk45HMCw5sKPM2MI7/qgwcZzoOl+Y88lUF3dfjazT6D6WQLaXVTLv5vOGa49iyP25TbjrX4E31Ipfwh8M4yaaKkrjEyFb6RJH6jjToLi+HQXBXuKXXa0vMNeDu+6oEwLnXN98ick= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FtdmpXdj; 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="FtdmpXdj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 28D28C4CEF7; Wed, 22 Oct 2025 16:10:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149415; bh=qOQpMwb8a6Ty7XQD33x8dOA998CFgN+vzt4Bsk/lfA4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=FtdmpXdjcoLjDkPgpSLlDilqCrpZNSnfn4396unQVd8AW3KRo1I5lMs8V4Qn1HnyO sumthwFqvJF1H4howfvqeQoMSuZhcnsH0XdnGDHZDiVJYNm7Uqf2kBwoTOWZbPK6VM bqI/9L704ets4vTPrWZLkjiBIeeWZJb/KA6qokZ/Xrwn1I4HbixVsLQ2b81/jwQb6l v+7+vSli17ixrbAjKwp1BKnglXXHYquqeLNLKcLZjSixKSebyVfhVrPwRsBPR30oPi MVuq2GpduoZjj+FZvjd2flPkJkQt0GtIOi48jNnakihvBIn9R82FVzdLMump6s797n ihv3HjfhMUL8w== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:25 +0200 Subject: [PATCH v2 47/63] selftests/namespaces: third listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-47-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4038; i=brauner@kernel.org; h=from:subject:message-id; bh=qOQpMwb8a6Ty7XQD33x8dOA998CFgN+vzt4Bsk/lfA4=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg+R6FvjsbloJdPXZyWHOOcs2y9bEH055D/VZ5J9 /M+b4rk7ihlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIhURGhh1NnIbL8pw3sD5Y wx9+VrjwyrR31o+cL5Q+LX+YbqzW/4mRYYHJy5X3ct1PhNgLrG9+on2m++7Hu5z8Gs6Cppn/L/Y sYgQA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that users cannot see namespaces from unrelated user namespaces. Create two sibling user namespaces, verify they can't see each other's owned namespaces. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 138 +++++++++++++++++= ++++ 1 file changed, 138 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 803c42fc76ec..4e47b4c82c56 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -234,4 +234,142 @@ TEST(listns_cap_sys_admin_in_userns) count); } =20 +/* + * Test that users cannot see namespaces from unrelated user namespaces. + * Create two sibling user namespaces, verify they can't see each other's + * owned namespaces. + */ +TEST(listns_cannot_see_sibling_userns_namespaces) +{ + int pipefd[2]; + pid_t pid1, pid2; + int status; + __u64 netns_a_id; + int pipefd2[2]; + bool found_sibling_netns; + + ASSERT_EQ(pipe(pipefd), 0); + + /* Fork first child - creates user namespace A */ + pid1 =3D fork(); + ASSERT_GE(pid1, 0); + + if (pid1 =3D=3D 0) { + int fd; + __u64 netns_a_id; + char buf; + + close(pipefd[0]); + + /* Create user namespace A */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Create network namespace owned by user namespace A */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get network namespace ID */ + fd =3D open("/proc/self/ns/net", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &netns_a_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send namespace ID to parent */ + write(pipefd[1], &netns_a_id, sizeof(netns_a_id)); + + /* Keep alive for sibling to check */ + read(pipefd[1], &buf, 1); + close(pipefd[1]); + exit(0); + } + + /* Parent reads namespace A ID */ + close(pipefd[1]); + netns_a_id =3D 0; + read(pipefd[0], &netns_a_id, sizeof(netns_a_id)); + + TH_LOG("User namespace A created network namespace with ID %llu", + (unsigned long long)netns_a_id); + + /* Fork second child - creates user namespace B */ + ASSERT_EQ(pipe(pipefd2), 0); + + pid2 =3D fork(); + ASSERT_GE(pid2, 0); + + if (pid2 =3D=3D 0) { + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[100]; + ssize_t ret; + bool found_sibling_netns; + + close(pipefd[0]); + close(pipefd2[0]); + + /* Create user namespace B (sibling to A) */ + if (setup_userns() < 0) { + close(pipefd2[1]); + exit(1); + } + + /* Try to list all network namespaces */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + found_sibling_netns =3D false; + if (ret > 0) { + for (ssize_t i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_a_id) { + found_sibling_netns =3D true; + break; + } + } + } + + /* We should NOT see the sibling's network namespace */ + write(pipefd2[1], &found_sibling_netns, sizeof(found_sibling_netns)); + close(pipefd2[1]); + exit(0); + } + + /* Parent reads result from second child */ + close(pipefd2[1]); + found_sibling_netns =3D false; + read(pipefd2[0], &found_sibling_netns, sizeof(found_sibling_netns)); + close(pipefd2[0]); + + /* Signal first child to exit */ + close(pipefd[0]); + + /* Wait for both children */ + waitpid(pid2, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + waitpid(pid1, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + /* Second child should NOT have seen first child's namespace */ + ASSERT_FALSE(found_sibling_netns); + TH_LOG("User namespace B correctly could not see sibling namespace A's ne= twork namespace"); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 67C7C27CB04; Wed, 22 Oct 2025 16:10:21 +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=1761149421; cv=none; b=a7gyqx8nmuD4KFHM9EjUivAqR/yaES4MziwHXLLJIDmjH1GOMOsUNoi97hMB0Bc50sI2P0PGdIMLWUi7DuXYXpFMggelERXgKwcDv83nIvTiMboFs0yJhAJfZeqmZntAMViGIBOgL/W/GTGnoW3ZlUPgMj/VpJyNgE8e6FvvIYw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149421; c=relaxed/simple; bh=+NPTtaVGIJjtOfL6a6/pXZ3Jnd+MAnJdtzTqZX7/Ujw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mUXoNrasFmnxPTH2V5OukdZiSG0vqVMmsMkkzbsbhV84FfBlQGCQTNcjyGF6uu6XpvvvYotOC94hwlbR0cbXWjjLGWulPC7up63ruDsVrp+4h3ZS5IFHp+PWykRLakLNkGnL/6VrzgT2eY+pJBmC4xDlea5W7kLmrzjnt1ZJaEc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PIHwQsrK; 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="PIHwQsrK" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5B943C4CEE7; Wed, 22 Oct 2025 16:10:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149421; bh=+NPTtaVGIJjtOfL6a6/pXZ3Jnd+MAnJdtzTqZX7/Ujw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=PIHwQsrKY+HJJMKbr8/FAAHVsbomjOxoIqYyM+FJtfAkCbMKTWZosaJzWIvDDlb2o qDj6ac7hJRSxYPfCWrj3yI2QVxS+iCF/cebVtVLQYiDXwDR2w+vg1g/Up58fGhFu9q oAKYPWGKQ8BXBjrJXz5NCfiEMbkZhvMYkwVQvwTfCIFnhuSOYOWObSM0VYvg9XFlh4 2IQCkkPtU2IyPee1otUawM30CGYKKzp7pbeF3NzT8oHdeJsb6BygMPtoHwGA3drNyU +vhf2se+8Zw9EW6Cf7zb7ZF7CeRqANLuvtLrEXJqka29SN6O2F36GJQz29XTtxZYTu jKqsODHOmSD9Q== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:26 +0200 Subject: [PATCH v2 48/63] selftests/namespaces: fourth listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-48-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2557; i=brauner@kernel.org; h=from:subject:message-id; bh=+NPTtaVGIJjtOfL6a6/pXZ3Jnd+MAnJdtzTqZX7/Ujw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHguZH1/7QV9yUPzG4ud0w8VnfpXfOrROs/kTxPT2 JJ1J86t7ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiIRA8jw+/sGh6h8obpnc/5 p2j9F5/q3yT3UDChwLBmyq2w9Mo5BYwM51JtzEz7lnXPfaTxZmWDzyrjG/bW7ztrC/rK9+xuVN/ KBAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test permission checking with LISTNS_CURRENT_USER. Verify that listing with LISTNS_CURRENT_USER respects permissions. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 79 ++++++++++++++++++= ++++ 1 file changed, 79 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 4e47b4c82c56..ff42109779ca 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -372,4 +372,83 @@ TEST(listns_cannot_see_sibling_userns_namespaces) TH_LOG("User namespace B correctly could not see sibling namespace A's ne= twork namespace"); } =20 +/* + * Test permission checking with LISTNS_CURRENT_USER. + * Verify that listing with LISTNS_CURRENT_USER respects permissions. + */ +TEST(listns_current_user_permissions) +{ + int pipefd[2]; + pid_t pid; + int status; + bool success; + ssize_t count; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D 0, + .spare2 =3D 0, + .user_ns_id =3D LISTNS_CURRENT_USER, + }; + __u64 ns_ids[100]; + ssize_t ret; + bool success; + + close(pipefd[0]); + + /* Create user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Create some namespaces owned by this user namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + if (unshare(CLONE_NEWUTS) < 0) { + close(pipefd[1]); + exit(1); + } + + /* List with LISTNS_CURRENT_USER - should see our owned namespaces */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + success =3D (ret >=3D 3); /* At least user, net, uts */ + write(pipefd[1], &success, sizeof(success)); + write(pipefd[1], &ret, sizeof(ret)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + success =3D false; + count =3D 0; + read(pipefd[0], &success, sizeof(success)); + read(pipefd[0], &count, sizeof(count)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespaces"); + } + + ASSERT_TRUE(success); + TH_LOG("LISTNS_CURRENT_USER returned %zd namespaces", count); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 B9DAF359705; Wed, 22 Oct 2025 16:10:26 +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=1761149426; cv=none; b=L3TalmqZ5ELrwG9qJTalktRhZWTNAGU5acEoq0/RHlGwXKqjYuCzgy/gFaKLjjvjymw2p1tulHZNBIISGNo1J0Y4pBXayfoS//Q/lodsTd5i+8Jh7yCs9wRQKkkBUSt5MI36mQul/DhDQeFsl23Iv/h0OXH/jaOS0QxRY1DtSTM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149426; c=relaxed/simple; bh=W101eyhrLICscf7roVQMEA8GrDRzuQACPaa4FbASft0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=f4ZAMH+K1mSrACYN0ZLEnzLoeYgaGZEFMn7MgJ/svqk8HOWv4O1t85WndGVZqB4LYd1vFFGDRwoLsBJwLKLAUWJxXSOtvPiway1FZOtTPpd1Sql5clznNHXsY7oe6nOmRvRPzNrMpxFZ6fOHJjYyx3MU9i4MkjEJYQrXH/xRpvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jpKfz1kr; 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="jpKfz1kr" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D1C08C4CEE7; Wed, 22 Oct 2025 16:10:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149426; bh=W101eyhrLICscf7roVQMEA8GrDRzuQACPaa4FbASft0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jpKfz1krkE7610Pnfxf3fdl9ixPsI1cQOT5vFIECUfBcCYPiouFUUCQqb1Sf8Bvo1 BbpmN98V4ZV67xOK2wfeYl/fAbQGK7RvB5jVhlDV7CrpyEazdmMXa1kfjngx1kCBdG kbJk+8MO9CiWYlWtSi4DUFDhyKhv86TUnX9X5AGfrWAgpBiy6twkOFMuuBevxAn8WN F16N/WXMbuj5FZvPPtkOQRgx4B3yYAX5f8jcsQTDKIYfqy6WHM8ZxEFfy7Rkk2/kcz oRorrDUMh9pt8CS4aOZHKMr5HCJE0dOkqWLS+lOkhUGsV15mz8lN1+l+7D1W/MHleW eCvBo/L7ulk1Q== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:27 +0200 Subject: [PATCH v2 49/63] selftests/namespaces: fifth listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-49-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3512; i=brauner@kernel.org; h=from:subject:message-id; bh=W101eyhrLICscf7roVQMEA8GrDRzuQACPaa4FbASft0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHiec9F1gdKt5JLq/mudy/ILO/4tVtNT3WRas3lPx q6IpRIzO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACZyeiXD/+qqV88K63l1n/DM CZ++of+ommnin+y8q3NE1vqLdqqU6jMC7VU3rpn0SGvpq+ln2bsnWy59KDZl2s42gWfte5eW/7L mAAA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that CAP_SYS_ADMIN in parent user namespace allows seeing child user namespace's owned namespaces. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 122 +++++++++++++++++= ++++ 1 file changed, 122 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index ff42109779ca..07c0c2be0aa5 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -451,4 +451,126 @@ TEST(listns_current_user_permissions) TH_LOG("LISTNS_CURRENT_USER returned %zd namespaces", count); } =20 +/* + * Test that CAP_SYS_ADMIN in parent user namespace allows seeing + * child user namespace's owned namespaces. + */ +TEST(listns_parent_userns_cap_sys_admin) +{ + int pipefd[2]; + pid_t pid; + int status; + bool found_child_userns; + ssize_t count; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 parent_userns_id; + __u64 child_userns_id; + struct ns_id_req req; + __u64 ns_ids[100]; + ssize_t ret; + bool found_child_userns; + + close(pipefd[0]); + + /* Create parent user namespace - we have CAP_SYS_ADMIN in it */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get parent user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &parent_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Create child user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get child user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Create namespaces owned by child user namespace */ + if (unshare(CLONE_NEWNET) < 0) { + close(pipefd[1]); + exit(1); + } + + /* List namespaces owned by parent user namespace */ + req.size =3D sizeof(req); + req.spare =3D 0; + req.ns_id =3D 0; + req.ns_type =3D 0; + req.spare2 =3D 0; + req.user_ns_id =3D parent_userns_id; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + /* Should see child user namespace in the list */ + found_child_userns =3D false; + if (ret > 0) { + for (ssize_t i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D child_userns_id) { + found_child_userns =3D true; + break; + } + } + } + + write(pipefd[1], &found_child_userns, sizeof(found_child_userns)); + write(pipefd[1], &ret, sizeof(ret)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + found_child_userns =3D false; + count =3D 0; + read(pipefd[0], &found_child_userns, sizeof(found_child_userns)); + read(pipefd[0], &count, sizeof(count)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespaces"); + } + + ASSERT_TRUE(found_child_userns); + TH_LOG("Process with CAP_SYS_ADMIN in parent user namespace saw child use= r namespace (total: %zd)", + count); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 47A4138084F; Wed, 22 Oct 2025 16:10:32 +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=1761149432; cv=none; b=CS1rckqs7hilA3IzINE/T8VmADwveQYrGouUXGtrw6p+/wwwJZs1M78mOSfcw9CP/29t0uUQMdsxwZCVMZtOY4znCr/8LxQkPK1iVM3TeSO5Gv5+COCowgFj13r1Ej2Sq1CVUdyAO0OdFXM37iRp9U65ZpkuK0FaEZ8XI82wcoQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149432; c=relaxed/simple; bh=zyvSyEvHN08sO6ilDq1bp8H9I2nWZ5I4e4dJ8kwOeEM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Pqnbsd3bRq9Yitr5suEpeWOFjGw+SZvpAdpd2ICLpxHjsEqISrLzq5Fdx7vW/MmfETXws2du9lFIMKGyzOmx10/6eNlT/SN68Tbk+usQ1/tTzdS+qxjd5y0G8hV6AONrVS8Aysajtw0+JFOno6+Sbb+VFYseP4R6C6UPvRiw/qk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Yx/8vL6f; 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="Yx/8vL6f" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 31559C4CEE7; Wed, 22 Oct 2025 16:10:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149431; bh=zyvSyEvHN08sO6ilDq1bp8H9I2nWZ5I4e4dJ8kwOeEM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Yx/8vL6fbS2LQX0vxugkE9sEUoAY1yOkiPImm4ADxTm9aFcGAVM9hJ9vsOFBD46eI gL+/R95gRhkoAbGrTnMXmdTZuX8EvWb4VaEshScjzwNhFhwCRCRdiZPvyZbHOVUSYi YlMfIbRg5bNwMgeuIdh79Jjte8DAJFTjTVPy9uENz29faVRbLggEeX7hKfTIic0zon f94ZAXjbKuCFR/QpEPxWMoY12r6R6rNPBHalwgZYOMp98PHqpWz93/hH4wPKBRxXpl l2goOHuJXJpCX54xU8nZrmPHewbuiIg/ymVcNIlDd435BE8/kshORJiGqxrfydwBKN X1ZPat1SoKMxg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:28 +0200 Subject: [PATCH v2 50/63] selftests/namespaces: sixth listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-50-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2704; i=brauner@kernel.org; h=from:subject:message-id; bh=zyvSyEvHN08sO6ilDq1bp8H9I2nWZ5I4e4dJ8kwOeEM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg+y/j+8oNrTL7dcLNuDnyTdlq3euPkw7wRUse4T +5zSPwS21HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRa3MY/sfycbmtznLfdern qbyaZwJt62LF1S9UqjZwmH65ceff7yxGhsWS7/Y8zdeYxma6m+uh2o5YSwc5zZZNJ4QMGu0kNwv k8AIA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that we can see user namespaces we have CAP_SYS_ADMIN inside of. This is different from seeing namespaces owned by a user namespace. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 90 ++++++++++++++++++= ++++ 1 file changed, 90 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 07c0c2be0aa5..709250ce1542 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -573,4 +573,94 @@ TEST(listns_parent_userns_cap_sys_admin) count); } =20 +/* + * Test that we can see user namespaces we have CAP_SYS_ADMIN inside of. + * This is different from seeing namespaces owned by a user namespace. + */ +TEST(listns_cap_sys_admin_inside_userns) +{ + int pipefd[2]; + pid_t pid; + int status; + bool found_ours; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 our_userns_id; + struct ns_id_req req; + __u64 ns_ids[100]; + ssize_t ret; + bool found_ours; + + close(pipefd[0]); + + /* Create user namespace - we have CAP_SYS_ADMIN inside it */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Get our user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &our_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* List all user namespaces globally */ + req.size =3D sizeof(req); + req.spare =3D 0; + req.ns_id =3D 0; + req.ns_type =3D CLONE_NEWUSER; + req.spare2 =3D 0; + req.user_ns_id =3D 0; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + + /* We should be able to see our own user namespace */ + found_ours =3D false; + if (ret > 0) { + for (ssize_t i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D our_userns_id) { + found_ours =3D true; + break; + } + } + } + + write(pipefd[1], &found_ours, sizeof(found_ours)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + found_ours =3D false; + read(pipefd[0], &found_ours, sizeof(found_ours)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespace"); + } + + ASSERT_TRUE(found_ours); + TH_LOG("Process can see user namespace it has CAP_SYS_ADMIN inside of"); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 7194B380F36; Wed, 22 Oct 2025 16:10: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=1761149437; cv=none; b=mvnXtvTXQmZKYCl/G87EhouSZO/Am9RsDp8/21vPbymRxzIzk4inBjXSPQy+A/wYi9loa5oYpRDm+t6BKpBTxj3V7H502XRz7wkvaxA+InG6SqYNGw27N54a50Ukv5qTHbxgvBWBruzr1yiChjFL2ClUGIK8vmvxeCnVdihX7Sc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149437; c=relaxed/simple; bh=Jz2qZpRe8+RR2mHCIjuTDi9/gaS5B8ErVeSfakXzmUk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N7F8meEGyiSzRi2b5PztyhinLHEvUdwqMzW06BUzZaub1IY0qyIdtvbV4MoWsC26WMhua39YUMd+Mpu0trQvTGngqkACK2gNT8lz8+cUGR9lXCmiDPZKldKVoS8gl+akgrGYadiWHa88Z1zcGbgM4IbAn0FWS1e18bfQQCZY7NY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CKNeh0Es; 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="CKNeh0Es" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 61B97C4CEFD; Wed, 22 Oct 2025 16:10:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149437; bh=Jz2qZpRe8+RR2mHCIjuTDi9/gaS5B8ErVeSfakXzmUk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CKNeh0Esf68YkqbfBA7BnsGES8vnsy3bC4GL/TbxCX+CjBSohB+fqiaCzc2U/gdk/ CNBMsnejsaFHJUZeNyT39s4ZJdJAa9UhH2tZdggwBTQJP2ConKKY2dX3R6GfUTFeFx jVLhpSXEGuAsRGgTn8b9vESouduRugivaVMo7C6u9cL4bKO2/pnaD3gi0J3VgdF5GA TWpeNoovW4Zvx3EgvqgkulEimoKLfeoVKM7fHIjXJfHcu65NAQJE6PGJaIyuUxjhO6 um+TlRDuP/NdByRfrQToM7G4p+wfiDit3CFveMhP4YcNbg49jzJmSJcDAmafcofdqs 7ZpOqzdW9223A== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:29 +0200 Subject: [PATCH v2 51/63] selftests/namespaces: seventh listns() permission test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-51-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3549; i=brauner@kernel.org; h=from:subject:message-id; bh=Jz2qZpRe8+RR2mHCIjuTDi9/gaS5B8ErVeSfakXzmUk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHjO9p3XTJtl0rI3+hoLpm1kaLJ9pHl4o953ycu1/ aY3ZRnedpSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzE3o7hf4LhhvbAZHvj4w58 1xJrOOWe5S+TlVr6697LIgd1gayzzAz/HU5IKvj7ehZfWG6YqMruYqFkye5rOn3BK5YEiU2sUnO ZAQ== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that dropping CAP_SYS_ADMIN restricts what we can see. Signed-off-by: Christian Brauner --- .../selftests/namespaces/listns_permissions_test.c | 111 +++++++++++++++++= ++++ 1 file changed, 111 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 709250ce1542..9d1767e8b804 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -663,4 +663,115 @@ TEST(listns_cap_sys_admin_inside_userns) TH_LOG("Process can see user namespace it has CAP_SYS_ADMIN inside of"); } =20 +/* + * Test that dropping CAP_SYS_ADMIN restricts what we can see. + */ +TEST(listns_drop_cap_sys_admin) +{ + cap_t caps; + cap_value_t cap_list[1] =3D { CAP_SYS_ADMIN }; + + /* This test needs to start with CAP_SYS_ADMIN */ + caps =3D cap_get_proc(); + if (!caps) { + SKIP(return, "Cannot get capabilities"); + } + + cap_flag_value_t cap_val; + if (cap_get_flag(caps, CAP_SYS_ADMIN, CAP_EFFECTIVE, &cap_val) < 0) { + cap_free(caps); + SKIP(return, "Cannot check CAP_SYS_ADMIN"); + } + + if (cap_val !=3D CAP_SET) { + cap_free(caps); + SKIP(return, "Test needs CAP_SYS_ADMIN to start"); + } + cap_free(caps); + + int pipefd[2]; + pid_t pid; + int status; + bool correct; + ssize_t count_before, count_after; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, + .spare2 =3D 0, + .user_ns_id =3D LISTNS_CURRENT_USER, + }; + __u64 ns_ids_before[100]; + ssize_t count_before; + __u64 ns_ids_after[100]; + ssize_t count_after; + bool correct; + + close(pipefd[0]); + + /* Create user namespace */ + if (setup_userns() < 0) { + close(pipefd[1]); + exit(1); + } + + /* Count namespaces with CAP_SYS_ADMIN */ + count_before =3D sys_listns(&req, ns_ids_before, ARRAY_SIZE(ns_ids_befor= e), 0); + + /* Drop CAP_SYS_ADMIN */ + caps =3D cap_get_proc(); + if (caps) { + cap_set_flag(caps, CAP_EFFECTIVE, 1, cap_list, CAP_CLEAR); + cap_set_flag(caps, CAP_PERMITTED, 1, cap_list, CAP_CLEAR); + cap_set_proc(caps); + cap_free(caps); + } + + /* Ensure we can't regain the capability */ + prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + + /* Count namespaces without CAP_SYS_ADMIN */ + count_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after),= 0); + + /* Without CAP_SYS_ADMIN, we should see same or fewer namespaces */ + correct =3D (count_after <=3D count_before); + + write(pipefd[1], &correct, sizeof(correct)); + write(pipefd[1], &count_before, sizeof(count_before)); + write(pipefd[1], &count_after, sizeof(count_after)); + close(pipefd[1]); + exit(0); + } + + /* Parent */ + close(pipefd[1]); + + correct =3D false; + count_before =3D 0; + count_after =3D 0; + read(pipefd[0], &correct, sizeof(correct)); + read(pipefd[0], &count_before, sizeof(count_before)); + read(pipefd[0], &count_after, sizeof(count_after)); + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + if (WEXITSTATUS(status) !=3D 0) { + SKIP(return, "Child failed to setup namespace"); + } + + ASSERT_TRUE(correct); + TH_LOG("With CAP_SYS_ADMIN: %zd namespaces, without: %zd namespaces", + count_before, count_after); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 EE57A359F8B; Wed, 22 Oct 2025 16:10:42 +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=1761149443; cv=none; b=ArxCUMumJNjN7SLKh/d4MEogqmJYgVPj7bydxBgTHeS+xqIYHtM+IvjQimQg88cYCpnTydiZOGMubkbXv5SLRPFlHBQ/ZAJWXH5BKmccCcjsLvDq2yFsp8LlpjPdpf0wi6cqMiMMOvevBStMbGXC/9Mz7YwOnOFW/jHHLiY/Fv0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149443; c=relaxed/simple; bh=YEySNnwHHlcAx8fWB+paH4j8S+yvwldW7xKcAutT9lM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Au1yUX1WcmNdWQZ499PX3iUTDejc5OH2Nm2VdeUiDOvoxtsQwikS1j/krBQ9sx4aCklr3Zewbd5Ct+1vALONwyXxYrB45IB2nIjVd1QXELWriWVEmJBrjKYQGmh52atBc6P3Xl4gEVAST8cE4OMbgHme9xb40mvOSxX3QOlAckQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=SYYCH3pi; 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="SYYCH3pi" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89EB1C4CEE7; Wed, 22 Oct 2025 16:10:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149442; bh=YEySNnwHHlcAx8fWB+paH4j8S+yvwldW7xKcAutT9lM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=SYYCH3piPyE/tqFlyW7bswylX36pM0Q8PLc5qrNfmZkr2hEgRZS1QqjBt0T1s46yJ MSZYvmrn6sORK88o844JWiPUO7WvDQovQ7egn54vaDAFcRMF9ajwS34D9xt6C8XuDf E2b9cMhMNTQlyLXyE2DaAitgdLQh3rb/Q2l6X9ipQAVsP3kAW0MiswPX5PWaixDbPd w3DE2LXiZrwCKtbcJ4sY+U1AbS8OwYsxS7qqraukV3VMlio8+c+OG1RiAc7GIMPcXd EPMeI8k08Cr2FXxQrqUAzfmrmodsP7hy2AeCjHZIspw9i2jTpmS4Y2ND6Ki7OZ4wIq 0AAD1Cd5WxDLg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:30 +0200 Subject: [PATCH v2 52/63] selftests/namespaces: first inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-52-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=3689; i=brauner@kernel.org; h=from:subject:message-id; bh=YEySNnwHHlcAx8fWB+paH4j8S+yvwldW7xKcAutT9lM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHh+Vn5ZZ9yVPwyOwocOe3le1mf928+/p13Oe7LKG kOnV10HO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACZyTYqRoZ3djvuJ+vmJJ09H 3FD2tYh/FWa6ULfw4Hl3ie1N/tq3lzMyNDWX5wueq9ot+/vQfF/rkI6tdVWeLV+P7z3Qn/Sc+cR pVgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test basic SIOCGSKNS functionality. Create a socket and verify SIOCGSKNS returns the correct network namespace. Signed-off-by: Christian Brauner --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 9 ++- .../testing/selftests/namespaces/siocgskns_test.c | 72 ++++++++++++++++++= ++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index 17f9c675a60b..aeb5f2711ff6 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -4,3 +4,4 @@ init_ino_test ns_active_ref_test listns_test listns_permissions_test +siocgskns_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index 2dd22bc68b89..d456505189cd 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -2,11 +2,18 @@ CFLAGS +=3D -Wall -O0 -g $(KHDR_INCLUDES) $(TOOLS_INCLUDES) LDLIBS +=3D -lcap =20 -TEST_GEN_PROGS :=3D nsid_test file_handle_test init_ino_test ns_active_ref= _test listns_test listns_permissions_test +TEST_GEN_PROGS :=3D nsid_test \ + file_handle_test \ + init_ino_test \ + ns_active_ref_test \ + listns_test \ + listns_permissions_test \ + siocgskns_test =20 include ../lib.mk =20 $(OUTPUT)/ns_active_ref_test: ../filesystems/utils.c $(OUTPUT)/listns_test: ../filesystems/utils.c $(OUTPUT)/listns_permissions_test: ../filesystems/utils.c +$(OUTPUT)/siocgskns_test: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c new file mode 100644 index 000000000000..0c9098624cd4 --- /dev/null +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +#ifndef SIOCGSKNS +#define SIOCGSKNS 0x894C +#endif + +#ifndef FD_NSFS_ROOT +#define FD_NSFS_ROOT -10003 +#endif + +#ifndef FILEID_NSFS +#define FILEID_NSFS 0xf1 +#endif + +/* + * Test basic SIOCGSKNS functionality. + * Create a socket and verify SIOCGSKNS returns the correct network namesp= ace. + */ +TEST(siocgskns_basic) +{ + int sock_fd, netns_fd, current_netns_fd; + struct stat st1, st2; + + /* Create a TCP socket */ + sock_fd =3D socket(AF_INET, SOCK_STREAM, 0); + ASSERT_GE(sock_fd, 0); + + /* Use SIOCGSKNS to get network namespace */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + /* Get current network namespace */ + current_netns_fd =3D open("/proc/self/ns/net", O_RDONLY); + ASSERT_GE(current_netns_fd, 0); + + /* Verify they match */ + ASSERT_EQ(fstat(netns_fd, &st1), 0); + ASSERT_EQ(fstat(current_netns_fd, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + + close(sock_fd); + close(netns_fd); + close(current_netns_fd); +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 0ED2A359F8B; Wed, 22 Oct 2025 16:10: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=1761149448; cv=none; b=HJOpZJRwQGodBjZmepzZQE6PL9SYB2M0yaoyAHmJFUMT3bvbeijB4znbJcpOEGya5vNLEXRl/6uurrgvBg1QFy4VgU02vkn3aj9+ViUY3VhFj+eYugzMEIHfm5w0IjK0OdBlR8/bG4mWD7vo+URE2+gqBsOkNRssF+prIltz+2s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149448; c=relaxed/simple; bh=M5JYL/ItXnif2Vw7+GSIT6vFRcZ0KyLdqVkykps56SU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pbWv9gTzoyeC1MIWw3bgJO1vE51Utn5zjTQIRKEtRRWniPrDsn8xtTtNQpFyawsFPKUICmQ2/4tO7hwkcWQ4B2/Xy+iAqtJQDsV7a6AYRrOE2lnDggWvN9AsWzPXctFEEEK6mo7aQJo9/lAafBB7dQ5isqggQB3ekKiABh6x1vw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Z4Zi7+HU; 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="Z4Zi7+HU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D80DC4CEF7; Wed, 22 Oct 2025 16:10:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149447; bh=M5JYL/ItXnif2Vw7+GSIT6vFRcZ0KyLdqVkykps56SU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Z4Zi7+HUkhTnZ2cGIpIl7U4sr67DnfiQEBRzTV2iwZ9d/FhE+lD87TzlRIaDWOEpX yxK/TydkHNg5XJPqYp2F+sI6nzVNZRvz7ZMBq9znfC4HMJ0K/Rz0r1kHHzDQBz+Ghr NsvppqEZCtbT/GKVq9zpsOkdGJ8oimsuqfOgeZQOXr0d/+FSRS1tbhfiA2Wzc6Z3Gu 4jJ3SRatJOXIhgB61n138FebEnYwhn91qUb2DZm86Rr9jmQoA2uPZ00w2ACNKnxl4R b74nS8+luv0+4iEUMC69efP74EYdIy9fxqA5rmAdyqZj1XV93Td00I9Fes8+ru/aw7 LD+4gg7sboFng== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:31 +0200 Subject: [PATCH v2 53/63] selftests/namespaces: second inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-53-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4149; i=brauner@kernel.org; h=from:subject:message-id; bh=M5JYL/ItXnif2Vw7+GSIT6vFRcZ0KyLdqVkykps56SU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi+wUroGKdm/4Ra+4Dc/wveKN/PP69V8fCMn9sbg RV9LkFbO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyewYjw1GpPap3di5nmH/4 8NlmxdmrOAwt+kOm17IbdCnyTaqslmBk+H+p3GvRI+aGeVb/lhx8F+v2Qlfv4dSjUVm/Tk0+12r pzgcA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that socket file descriptors keep network namespaces active. Create a network namespace, create a socket in it, then exit the namespace. The namespace should remain active while the socket FD is held. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 126 +++++++++++++++++= ++++ 1 file changed, 126 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 0c9098624cd4..0ad5e39b7e16 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -69,4 +69,130 @@ TEST(siocgskns_basic) close(current_netns_fd); } =20 +/* + * Test that socket file descriptors keep network namespaces active. + * Create a network namespace, create a socket in it, then exit the namesp= ace. + * The namespace should remain active while the socket FD is held. + */ +TEST(siocgskns_keeps_netns_active) +{ + int sock_fd, netns_fd, test_fd; + int ipc_sockets[2]; + pid_t pid; + int status; + struct stat st; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create new netns and socket */ + close(ipc_sockets[0]); + + if (unshare(CLONE_NEWNET) < 0) { + TH_LOG("unshare(CLONE_NEWNET) failed: %s", strerror(errno)); + close(ipc_sockets[1]); + exit(1); + } + + /* Create a socket in the new network namespace */ + sock_fd =3D socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + TH_LOG("socket() failed: %s", strerror(errno)); + close(ipc_sockets[1]); + exit(1); + } + + /* Send socket FD to parent via SCM_RIGHTS */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_sockets[1]); + exit(1); + } + + close(sock_fd); + close(ipc_sockets[1]); + exit(0); + } + + /* Parent: receive socket FD */ + close(ipc_sockets[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + ASSERT_EQ(n, 1); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + ASSERT_NE(cmsg, NULL); + ASSERT_EQ(cmsg->cmsg_type, SCM_RIGHTS); + + memcpy(&sock_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) + SKIP(close(sock_fd); return, "Child failed to create namespace"); + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + ASSERT_EQ(fstat(netns_fd, &st), 0); + + /* + * Namespace should still be active because socket FD keeps it alive. + * Try to access it via /proc/self/fd/. + */ + char path[64]; + snprintf(path, sizeof(path), "/proc/self/fd/%d", netns_fd); + test_fd =3D open(path, O_RDONLY); + ASSERT_GE(test_fd, 0); + close(test_fd); + close(netns_fd); + + /* Close socket - namespace should become inactive */ + close(sock_fd); + + /* Try SIOCGSKNS again - should fail since socket is closed */ + ASSERT_LT(ioctl(sock_fd, SIOCGSKNS), 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 59B92381E61; Wed, 22 Oct 2025 16:10:53 +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=1761149453; cv=none; b=CFJOARXS4D4aGHdnm+VMYZJ3QxB1yW/VtiEIKr/mYIanx7giEpige1ySyWBsIc5BvPm26OBHPcnnQgGFsVd9iKvhuWewBjfjlDUHBh0sg2OQMKnNhVwzDc9C7bEdYXUqL1iDv2kuNhIFBJD9DzBQJpuXLCE8CQalEAt8wWLbC3Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149453; c=relaxed/simple; bh=1BIiJuH8iVaCzmqGXRHvJojCs6tQ4qxTFg36CiNtCEM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qKIeIcUF48ki+nQA5sUT4/EJUP1EQy+kQEPYf4y5LkaIzx82p7qvagXEkVt4p1GqZmHpG/Gn0Py05Qr3bSF5ItWxxdnm0ezeTdIrCECVs4cRp8K526iU3CHSw7SubUpO6irjmMymA6eyznkVHwQbWcVZHpczpkMaGhC+NRpkKV8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sWI/SeLO; 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="sWI/SeLO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5BDF1C4CEE7; Wed, 22 Oct 2025 16:10:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149453; bh=1BIiJuH8iVaCzmqGXRHvJojCs6tQ4qxTFg36CiNtCEM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sWI/SeLO8WHcXknT6WwQ+WwdSYxz519zxSiNun1JKcSSlM4fMBWEsMHgZocFRFNfL /C+h/hKPrSkKOoBK4whrx/CrsUMNJf7BpvhCHFyzHOfe83cTeE7tctLhfMmDouHwq9 ENypwJQHoR5WgsEyb5lTm779zLLOptX+iliqsA8iD8NOXCV1/IHGDlEWoXn2GPNr9y DG/pdJ/Y4XUuU192fYMyWllsOoxfACxlG073CMN9iwnUcy77EW8E2lUQJ8CYx68lPA fWRCQWvfPJCAVCmIvCmSHI01edXgDNXjmh4vs11TqLfPlG4c4bRjrqVPby+tqV00tj ezoRFQwANkgXw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:32 +0200 Subject: [PATCH v2 54/63] selftests/namespaces: third inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-54-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2308; i=brauner@kernel.org; h=from:subject:message-id; bh=1BIiJuH8iVaCzmqGXRHvJojCs6tQ4qxTFg36CiNtCEM=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHj+IjNoPcM68/D5l+oS687N5yg6nhkou1r0zqXt7 6MPf/l3vKOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAi1ksYfrO+/58brtF43LE3 1j/NSvz97UetLLpP5to3SrbEHNh4NpDhfyDDmoLzf+QkecM7ErxSX+14Gpds5rxo+ekL7h7GJos 4mAE= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test SIOCGSKNS with different socket types (TCP, UDP, RAW). Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 62 ++++++++++++++++++= ++++ 1 file changed, 62 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 0ad5e39b7e16..3f46ac0c96df 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -195,4 +195,66 @@ TEST(siocgskns_keeps_netns_active) ASSERT_LT(ioctl(sock_fd, SIOCGSKNS), 0); } =20 +/* + * Test SIOCGSKNS with different socket types (TCP, UDP, RAW). + */ +TEST(siocgskns_socket_types) +{ + int sock_tcp, sock_udp, sock_raw; + int netns_tcp, netns_udp, netns_raw; + struct stat st_tcp, st_udp, st_raw; + + /* TCP socket */ + sock_tcp =3D socket(AF_INET, SOCK_STREAM, 0); + ASSERT_GE(sock_tcp, 0); + + /* UDP socket */ + sock_udp =3D socket(AF_INET, SOCK_DGRAM, 0); + ASSERT_GE(sock_udp, 0); + + /* RAW socket (may require privileges) */ + sock_raw =3D socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sock_raw < 0 && (errno =3D=3D EPERM || errno =3D=3D EACCES)) { + sock_raw =3D -1; /* Skip raw socket test */ + } + + /* Test SIOCGSKNS on TCP */ + netns_tcp =3D ioctl(sock_tcp, SIOCGSKNS); + if (netns_tcp < 0) { + close(sock_tcp); + close(sock_udp); + if (sock_raw >=3D 0) close(sock_raw); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_tcp, 0); + } + + /* Test SIOCGSKNS on UDP */ + netns_udp =3D ioctl(sock_udp, SIOCGSKNS); + ASSERT_GE(netns_udp, 0); + + /* Test SIOCGSKNS on RAW (if available) */ + if (sock_raw >=3D 0) { + netns_raw =3D ioctl(sock_raw, SIOCGSKNS); + ASSERT_GE(netns_raw, 0); + } + + /* Verify all return the same network namespace */ + ASSERT_EQ(fstat(netns_tcp, &st_tcp), 0); + ASSERT_EQ(fstat(netns_udp, &st_udp), 0); + ASSERT_EQ(st_tcp.st_ino, st_udp.st_ino); + + if (sock_raw >=3D 0) { + ASSERT_EQ(fstat(netns_raw, &st_raw), 0); + ASSERT_EQ(st_tcp.st_ino, st_raw.st_ino); + close(netns_raw); + close(sock_raw); + } + + close(netns_tcp); + close(netns_udp); + close(sock_tcp); + close(sock_udp); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 18900382865; Wed, 22 Oct 2025 16:10: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=1761149459; cv=none; b=eXdHnSwRN2LMVRuy5Iq3yyCGOcdhcyU8IPY110DOKj0091wif4Ol/5fWzEzHQt+ZRWTxXmwdQ8HwSFJ9VvXXMAy8z+o8wtX4AFW5EXjKBcC+Vuqso5ORjncFb4jxesxbNSCk3bOMEWSbappDjCTXuT3qEIiM+JC0GPJOijhIWNE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149459; c=relaxed/simple; bh=Gh/yPS1NyhqsBzLO+DmIzxsHN6EXBn9HWj+WnIyz1JI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F0mQwk0ErjcWfw8NQ3g+Mle8wDhANW/G7SLgleBp4J/3DMtqLhIoebKho9pybp8x19YcgNSVB8TQzYTlIMpKY9lqJ/wkXifoJM8O/gLFRHeRjDzme0VvNEqudFmuvbD/1aEL07wMJlNZIadrO7C8wXjyTuvnQVzBzW2JQRvqYjo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OTtsET+w; 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="OTtsET+w" Received: by smtp.kernel.org (Postfix) with ESMTPSA id ADA2EC4CEE7; Wed, 22 Oct 2025 16:10:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149458; bh=Gh/yPS1NyhqsBzLO+DmIzxsHN6EXBn9HWj+WnIyz1JI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OTtsET+wiMrbHLQTHVyTKNyKffGvyp+8IrYbC4ycd1U7SM2yWIfYM4661F0CJ72ej ev05/DU7TlZrq170dY9mvbo5SGjKNvgy9cRAiGquMc4OC6f4lXNpcrpYbPqz3WQPco AiH0QkQnHtqj9KdJAyavmxWR+ZmAkP/DKciXvwwk0pdYWvqgAFjS955a4THbTQ0A3k PX68bKFwmhvjxZ857SWzYwpgXgBFi1vR4d39U1aJmTXOp+yUc/777Iyu4dukXlSDIJ meXFrhD9vn8e9U0rYJbwB8P6HjGBFnD2oshYOc06Qv5MO03flZDZ4MdJSfp3ZoDGOg 6sk8jXnKouHlw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:33 +0200 Subject: [PATCH v2 55/63] selftests/namespaces: fourth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-55-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2063; i=brauner@kernel.org; h=from:subject:message-id; bh=Gh/yPS1NyhqsBzLO+DmIzxsHN6EXBn9HWj+WnIyz1JI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi+j/eNPTfPjyVnEvgPaxU/Xz773fP1fqXJp+fec +J7d3F+a0cpC4MYF4OsmCKLQ7tJuNxynorNRpkaMHNYmUCGMHBxCsBELn9m+J9U+ME6julV8G3J pPmm5/TL5svMTy4pLf63UntPzuvDCZKMDBNfvp20UyDjVTzfT7ET6qdCz2rrPE9dNee5lYjJn3l vy9kA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test SIOCGSKNS across setns. Create a socket in netns A, switch to netns B, verify SIOCGSKNS still returns netns A. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 51 ++++++++++++++++++= ++++ 1 file changed, 51 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 3f46ac0c96df..3aed6e3d60a3 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -257,4 +257,55 @@ TEST(siocgskns_socket_types) close(sock_udp); } =20 +/* + * Test SIOCGSKNS across setns. + * Create a socket in netns A, switch to netns B, verify SIOCGSKNS still + * returns netns A. + */ +TEST(siocgskns_across_setns) +{ + int sock_fd, netns_a_fd, netns_b_fd, result_fd; + struct stat st_a; + + /* Get current netns (A) */ + netns_a_fd =3D open("/proc/self/ns/net", O_RDONLY); + ASSERT_GE(netns_a_fd, 0); + ASSERT_EQ(fstat(netns_a_fd, &st_a), 0); + + /* Create socket in netns A */ + sock_fd =3D socket(AF_INET, SOCK_STREAM, 0); + ASSERT_GE(sock_fd, 0); + + /* Create new netns (B) */ + ASSERT_EQ(unshare(CLONE_NEWNET), 0); + + netns_b_fd =3D open("/proc/self/ns/net", O_RDONLY); + ASSERT_GE(netns_b_fd, 0); + + /* Get netns from socket created in A */ + result_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (result_fd < 0) { + close(sock_fd); + setns(netns_a_fd, CLONE_NEWNET); + close(netns_a_fd); + close(netns_b_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(result_fd, 0); + } + + /* Verify it still points to netns A */ + struct stat st_result_stat; + ASSERT_EQ(fstat(result_fd, &st_result_stat), 0); + ASSERT_EQ(st_a.st_ino, st_result_stat.st_ino); + + close(result_fd); + close(sock_fd); + close(netns_b_fd); + + /* Restore original netns */ + ASSERT_EQ(setns(netns_a_fd, CLONE_NEWNET), 0); + close(netns_a_fd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 7E947382865; Wed, 22 Oct 2025 16:11: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=1761149464; cv=none; b=V44g1c7/I3gP6SPgfSiPgcpwL7wHP3EHYoz4CPA6x61WkH94KXQzTm5stkMceGiTSjPbIPorQfpe5739QCEe3N4xUvxQgm+p9mk3Ju+jgACf11NNOw5S8h2DOQy4BdG23iJI2d67IKagXSqINTpJw3KIXJUQVa2esohronvzllw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149464; c=relaxed/simple; bh=ufWjPwiVFUvMc1yUrgMdzg/t00J0XDkru7okPfPAtyE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=onBz+9DeHJeqOB3yfVs4NSaoic3DuGpUZgAQvBv2e3ElgiSYaSHduIQV118D24Nlvg+iwEbxEQdbfnHdrmKa1jB3Qqdr7uT3oKPlOwmARlKN/P/S70m6UU3XJdRb8iMPVaUxn+5GE/SL2sRkjFTU+P7AWpddSBvAu3nUrfFqtMc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=n7XU/sVa; 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="n7XU/sVa" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1F30EC4CEFD; Wed, 22 Oct 2025 16:10:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149464; bh=ufWjPwiVFUvMc1yUrgMdzg/t00J0XDkru7okPfPAtyE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=n7XU/sVaIYqM0xGtka3zmyCDO/RnWLcgBOSjQvF9DL2clSpBoTCjkSJk0xfOmNFml Hd6YgdSSXVvjT+GYTfhQeK9magtak62q0fb8/GQlPz96yJ84f039H2mIjiFiK/6jSi pq0OcH++X43g5QOvJnP16aqlcc4I6qqt+ERNHe/Bw6WvFOwP06YVUb90rydUvte6U2 +teBWDKL5BkkKGG1DDfzS0R37k4swXCW+GCRTKhsPRsKQIQpaqLdBGmUtW0YFfvsqO Bizh32o4u8sWJiu/RSPmXdC/qsl0jaUN+C6Diuc0E1uBTfu5HQ3BTrrq5mKUYsT8gt NEiWAsZXObdHw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:34 +0200 Subject: [PATCH v2 56/63] selftests/namespaces: fifth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-56-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1167; i=brauner@kernel.org; h=from:subject:message-id; bh=ufWjPwiVFUvMc1yUrgMdzg/t00J0XDkru7okPfPAtyE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHg+b3lyQM0OvdZWtWliia/Z7u8Syzy5+EfiRR0jO bFLp/b6d5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzE6xgjwyPOVYp6/x5y/Tu1 opHrxduTeU6cwcm161erzlCWEj4RXMfIsPHzMtmQcxOWTjx5K9x/md3zqh1e3GeTBY+UzVvCUsL 5iQMA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test SIOCGSKNS fails on non-socket file descriptors. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 26 ++++++++++++++++++= ++++ 1 file changed, 26 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 3aed6e3d60a3..4134a13c2f74 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -308,4 +308,30 @@ TEST(siocgskns_across_setns) close(netns_a_fd); } =20 +/* + * Test SIOCGSKNS fails on non-socket file descriptors. + */ +TEST(siocgskns_non_socket) +{ + int fd; + int pipefd[2]; + + /* Test on regular file */ + fd =3D open("/dev/null", O_RDONLY); + ASSERT_GE(fd, 0); + + ASSERT_LT(ioctl(fd, SIOCGSKNS), 0); + ASSERT_TRUE(errno =3D=3D ENOTTY || errno =3D=3D EINVAL); + close(fd); + + /* Test on pipe */ + ASSERT_EQ(pipe(pipefd), 0); + + ASSERT_LT(ioctl(pipefd[0], SIOCGSKNS), 0); + ASSERT_TRUE(errno =3D=3D ENOTTY || errno =3D=3D EINVAL); + + close(pipefd[0]); + close(pipefd[1]); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6DB7A35A122; Wed, 22 Oct 2025 16:11:09 +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=1761149469; cv=none; b=YSSMQaxXS03osGKJx2nulReY/536rC/XJ1VkyyVHJe9LnM5mMpkJGxpTgVMDYDzpHBwK0P9Ei+UlmrkoFhO/cd8pObn0/Uaz/tXcic7ZeukPNuispR8y0lgsERKKbcN5Tz2TcW3yC1mWjbwfzmukQBnYZTvoHjov2w7BKLlx71g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149469; c=relaxed/simple; bh=udWXbE5GIXnpNt82C6OUf1abPXO2lL6zpT/iVGrkFOU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=f7x1bpe73t9fmzNBg67wdJVvE6wmojYp4fJ2Zjzce+3yUuRuIp017moFUq2BKP1I0A+3nhGJsj0eAuTB+4HUZG8h2uVeNRd23bkUzi+cpdgyoSoaQWy31M8K+UatAEwNheKsi0uBdk9hAMmDHVsuD8jJ/7azhxxU4AAzkbW+P1E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hxxZxfWW; 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="hxxZxfWW" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 676E6C4CEF7; Wed, 22 Oct 2025 16:11:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149469; bh=udWXbE5GIXnpNt82C6OUf1abPXO2lL6zpT/iVGrkFOU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=hxxZxfWWABrUFXrO/bZG0jmsm/Cx6NWBnP3oaWY9gDoYKBGY01W1AA1u5cmhY8aLI K6LGQ+SA4RSZzTfGA6CaHz/2AA7R0mxXpD9RGPC0RrFH6KSnxBnXkFWWcnT1Bc5+ym 444k3iKuG6ZB030Rw0u8GZnac/pdCx03H5VfnarcwJl0kmkWxloBnNECT9xInwcpqf sccmq8R1po/dbc3mgcnA0eUzxf6xMu+9JcijcwNWTrPfUGqj4TWUZDn3OVESy4LlvM lriv3h4KIB+ig/nmusMCXx3y6zCEKVq2mPEMnxWafwgYg3YEpFNJTJivI/k9vYxNti RTXJ6/gnw+Wog== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:35 +0200 Subject: [PATCH v2 57/63] selftests/namespaces: sixth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-57-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=2328; i=brauner@kernel.org; h=from:subject:message-id; bh=udWXbE5GIXnpNt82C6OUf1abPXO2lL6zpT/iVGrkFOU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHie7zDhYp3Dqp7nC3f/k1h/mlP3XfRW028z3trPf P3ru5vclo5SFgYxLgZZMUUWh3aTcLnlPBWbjTI1YOawMoEMYeDiFICJSJ5lZHi9UUjmz/zFC2Wf rIsJrnp1f9vGd9fmbXW9e6Wsjaun7bs/wz9DwSxF10tWRy6+ij/4qKi3+eDTXAOBT9ffZHbdaFG X3MsOAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test multiple sockets keep the same network namespace active. Create multiple sockets, verify closing some doesn't affect others. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 68 ++++++++++++++++++= ++++ 1 file changed, 68 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 4134a13c2f74..d11b3a9c4cfd 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -334,4 +334,72 @@ TEST(siocgskns_non_socket) close(pipefd[1]); } =20 +/* + * Test multiple sockets keep the same network namespace active. + * Create multiple sockets, verify closing some doesn't affect others. + */ +TEST(siocgskns_multiple_sockets) +{ + int socks[5]; + int netns_fds[5]; + int i; + struct stat st; + ino_t netns_ino; + + /* Create new network namespace */ + ASSERT_EQ(unshare(CLONE_NEWNET), 0); + + /* Create multiple sockets */ + for (i =3D 0; i < 5; i++) { + socks[i] =3D socket(AF_INET, SOCK_STREAM, 0); + ASSERT_GE(socks[i], 0); + } + + /* Get netns from all sockets */ + for (i =3D 0; i < 5; i++) { + netns_fds[i] =3D ioctl(socks[i], SIOCGSKNS); + if (netns_fds[i] < 0) { + int j; + for (j =3D 0; j <=3D i; j++) { + close(socks[j]); + if (j < i && netns_fds[j] >=3D 0) + close(netns_fds[j]); + } + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fds[i], 0); + } + } + + /* Verify all point to same netns */ + ASSERT_EQ(fstat(netns_fds[0], &st), 0); + netns_ino =3D st.st_ino; + + for (i =3D 1; i < 5; i++) { + ASSERT_EQ(fstat(netns_fds[i], &st), 0); + ASSERT_EQ(st.st_ino, netns_ino); + } + + /* Close some sockets */ + for (i =3D 0; i < 3; i++) { + close(socks[i]); + } + + /* Remaining netns FDs should still be valid */ + for (i =3D 3; i < 5; i++) { + char path[64]; + snprintf(path, sizeof(path), "/proc/self/fd/%d", netns_fds[i]); + int test_fd =3D open(path, O_RDONLY); + ASSERT_GE(test_fd, 0); + close(test_fd); + } + + /* Cleanup */ + for (i =3D 0; i < 5; i++) { + if (i >=3D 3) + close(socks[i]); + close(netns_fds[i]); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 D9A84383366; Wed, 22 Oct 2025 16:11:14 +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=1761149475; cv=none; b=seK1aW13T2Te79LnhsLLf6jmxAmjVPBfS/CJVBX2UOx0SDU8ihaPKCJuHz/RyRmA7xaqHezygY+qvdp7NjmIcEn4YpTHeg1aaT78UaAuIKc9Pp2CpZ6t8sxJHp0n/mJtRGZhW53ZKU7DcnTrn3/i2zOc5xlHTSfS3A3PIdIR6Z8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149475; c=relaxed/simple; bh=GsTFrZ8P1sWrb+90uv1i8VCB1pEYoHIvAvoNNGUl0r4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XhTdOA9Q71zEqrA67LcHeqF5vbX5ZMaOEcKzWQ1pB1owRhZXlVJL+Fk/9EZPvl22nFibBeoScFMLAJSdO4vtsMAnWpUEtjMGr3DiwAeVkFPpIVVULQMWp94dBdQsO9MgCy/vl8Ii60f19pHQInjtSz28P8J4nSwLNusoM5IRH40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=MYR59V8u; 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="MYR59V8u" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C2453C4CEE7; Wed, 22 Oct 2025 16:11:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149474; bh=GsTFrZ8P1sWrb+90uv1i8VCB1pEYoHIvAvoNNGUl0r4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=MYR59V8uDNaPYb1rZmXgVKZO4afxZivUdkh0g49G2Fgz0HJ0HYNH0o4FjtGuUoU9s UBd0hhEYUSb1lhtgLR76KLfFftrw5kCZ8PP2K7pEsJiX+2VUUvjHRFwt3Wm+aAhN6y nWfm5ytZMEbpNOw/QB703ChW71uLIkhbFFfKFYS9R8l2719fbU1iygSQI094UaG462 VDTMcH7b/hQdU23lOKZ7rclgUbmxMdcBTwl29rJGJIVPK/HSm8QYFCv+xI2i8BDfpW +RmXKMMbBzX+Fo5rojMQRjkA0Tr9lP5V2mr0TIJ9LymCPvpk3Tr5QuyHLhvM+eyEfv VgJr11SvzDGMg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:36 +0200 Subject: [PATCH v2 58/63] selftests/namespaces: seventh inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-58-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=4066; i=brauner@kernel.org; h=from:subject:message-id; bh=GsTFrZ8P1sWrb+90uv1i8VCB1pEYoHIvAvoNNGUl0r4=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi+qsjVvTappvyU/n0hlWkTc5T6fyX9OTLt3TU5m +QFd1bd7yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiI6yZGhq03auc9LoyQeVy7 z3yLXEfKzmuuTUXucra8kk9OCm/o4WFkmP10jdZEqcWpdUfDQxK/1v3cuuDqwtsMP1POF37t+G5 8mxMA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test socket keeps netns active after creating process exits. Verify that as long as the socket FD exists, the namespace remains active. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 141 +++++++++++++++++= ++++ 1 file changed, 141 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index d11b3a9c4cfd..17f2cafb75a7 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -402,4 +402,145 @@ TEST(siocgskns_multiple_sockets) } } =20 +/* + * Test socket keeps netns active after creating process exits. + * Verify that as long as the socket FD exists, the namespace remains acti= ve. + */ +TEST(siocgskns_netns_lifecycle) +{ + int sock_fd, netns_fd; + int ipc_sockets[2]; + int syncpipe[2]; + pid_t pid; + int status; + char sync_byte; + struct stat st; + ino_t netns_ino; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + ASSERT_EQ(pipe(syncpipe), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child */ + close(ipc_sockets[0]); + close(syncpipe[1]); + + if (unshare(CLONE_NEWNET) < 0) { + close(ipc_sockets[1]); + close(syncpipe[0]); + exit(1); + } + + sock_fd =3D socket(AF_INET, SOCK_STREAM, 0); + if (sock_fd < 0) { + close(ipc_sockets[1]); + close(syncpipe[0]); + exit(1); + } + + /* Send socket to parent */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_sockets[1]); + close(syncpipe[0]); + exit(1); + } + + close(sock_fd); + close(ipc_sockets[1]); + + /* Wait for parent signal */ + read(syncpipe[0], &sync_byte, 1); + close(syncpipe[0]); + exit(0); + } + + /* Parent */ + close(ipc_sockets[1]); + close(syncpipe[0]); + + /* Receive socket FD */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + ASSERT_EQ(n, 1); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + ASSERT_NE(cmsg, NULL); + memcpy(&sock_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Get netns from socket while child is alive */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + sync_byte =3D 'G'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + close(sock_fd); + waitpid(pid, NULL, 0); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + ASSERT_EQ(fstat(netns_fd, &st), 0); + netns_ino =3D st.st_ino; + + /* Signal child to exit */ + sync_byte =3D 'G'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + + /* + * Socket FD should still keep namespace active even after + * the creating process exited. + */ + int test_fd =3D ioctl(sock_fd, SIOCGSKNS); + ASSERT_GE(test_fd, 0); + + struct stat st_test; + ASSERT_EQ(fstat(test_fd, &st_test), 0); + ASSERT_EQ(st_test.st_ino, netns_ino); + + close(test_fd); + close(netns_fd); + + /* Close socket - namespace should become inactive */ + close(sock_fd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 CD52F34B18F; Wed, 22 Oct 2025 16:11:19 +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=1761149479; cv=none; b=P5HSNRnphRXmTrPIc+hoFrr/QHiHTuRY1FIThQW/mRDt+ZIkndnduzb3ECwBpO6DH8njAIT4qw3jlhQQTgRjiRpkpvaVuZFUg80QdO0shf24OTziUW5I3Xyjd0jFiJNBXuFncQ8u4D5HXBRm5LUvt12WzRbPpLD71ChgKY52/Zs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149479; c=relaxed/simple; bh=pqDbtFvmIISrOx6K7KWbVnqojUaOo6VRP9RWZVJYLQI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OKd6y+LZs/t5eAbA1dv+LQf4qRVkN5P+Mac8YWvGqNO7XCjHoCfdbjZpADUvOjBfBdVQfE7zs0w88fSkihtOWu1m6JGAU9pMKcvbTVDOIq93GiLgm6X5ABgSNlo20R9FVJb1Lmi9Nj8OSjb1dET8Kxqe0KDsHbTlwE4TmSYR4LM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rT6uLl14; 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="rT6uLl14" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E3C53C4CEF7; Wed, 22 Oct 2025 16:11:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149479; bh=pqDbtFvmIISrOx6K7KWbVnqojUaOo6VRP9RWZVJYLQI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rT6uLl14V1T/r2lFY23lNT4HxYTQTpV70Zw+fxSD8XbzRDb1hgoHvt3qR4m+yVC4w MchbmBqsoQsEuwMSMh4WhvLqgF5Gq1TS6EiJDRu+Sbr2ZHbYXwntyLOsjZKOdFyMD2 D7G8/ikVLlHJg2jYZs/THddDx9Nh9gvf+0p6vj01r5ETxfOtoDkSHkqVw2DgKofTHM fWNPQv1uKEtKuqgMlYJCGV0UEebEhFBrOZyBkCALXN2GFns+wjSv22JK5LBb58CTwt MP/DhnSg9mOZXr1KAKnBRi9KxlJMY9EfvgRMrVFyZT+sJZHRRZSDdWhANrASnPOisd ebs+nCMb7Yozg== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:37 +0200 Subject: [PATCH v2 59/63] selftests/namespaces: eigth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-59-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=1467; i=brauner@kernel.org; h=from:subject:message-id; bh=pqDbtFvmIISrOx6K7KWbVnqojUaOo6VRP9RWZVJYLQI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHievFVr2qJre5ZrSSSbFuj4KL/S0Vj+4gzXc5G7C RF/nXYXdJSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEwkwZ3hn6roy4XV+QnLLk+w FeZU0n3xfpo8z5xQfR/LrpodeT0p5xn+ykg5XjLO/O9tpcXiYWjRduDIl6OPm5t+3FWaqWx1X3U SOwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test IPv6 sockets also work with SIOCGSKNS. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 34 ++++++++++++++++++= ++++ 1 file changed, 34 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 17f2cafb75a7..1c40c7772ad4 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -543,4 +543,38 @@ TEST(siocgskns_netns_lifecycle) close(sock_fd); } =20 +/* + * Test IPv6 sockets also work with SIOCGSKNS. + */ +TEST(siocgskns_ipv6) +{ + int sock_fd, netns_fd, current_netns_fd; + struct stat st1, st2; + + /* Create an IPv6 TCP socket */ + sock_fd =3D socket(AF_INET6, SOCK_STREAM, 0); + ASSERT_GE(sock_fd, 0); + + /* Use SIOCGSKNS */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + /* Verify it matches current namespace */ + current_netns_fd =3D open("/proc/self/ns/net", O_RDONLY); + ASSERT_GE(current_netns_fd, 0); + + ASSERT_EQ(fstat(netns_fd, &st1), 0); + ASSERT_EQ(fstat(current_netns_fd, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + + close(sock_fd); + close(netns_fd); + close(current_netns_fd); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 19E5C34A781; Wed, 22 Oct 2025 16:11:25 +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=1761149485; cv=none; b=srXeIIoAqjFQPg4l9UNyjIODH3zAszwXXz0tnfkBLmZ94jpXRAA66QTwnXshinjfZ2pHz0z6S29Fe97laC1hr3v33mIi3DSYeafwGn/HCN8ZarxPB3THsSG6s/1VXjGmyENBDVshvHIV9N3FJCENkTsB3Qz7nYf55lCtmd1yE14= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149485; c=relaxed/simple; bh=9gt1tGf0xzLbqqMQlOif9Kfq8cZPXlqC1fDbDaJd8HY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XcegZvEpSPgRRqoSxp6tQV6L8fspdhTlT/097NLV96CEiys5lo9Dh1+gUBDafuPUHH3pmot2Gg2Uozm6DFOYosQ6YTxZJSwcyK1UZjS7wKSKkjibmNmdI+bKAfz9IdveHf1udIzCPuoqBM92/1d6fWF+k3bsZ6rBM7mK+8yfFfo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=TK5GFEEn; 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="TK5GFEEn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 29C98C4CEFD; Wed, 22 Oct 2025 16:11:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149485; bh=9gt1tGf0xzLbqqMQlOif9Kfq8cZPXlqC1fDbDaJd8HY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=TK5GFEEnmZrfv6GsUBTQz62dn/rSmX2tK5q7zHxzNNDif6hvZo3xBdfrdk/uKqzJB 86TjnIxufVb6avZlalC38ubTu0DUAfF/uF3MZ9yJhyYISlQQ2Oul6TPgqpGRjphdsU KsgiTQCpTfSdIhV+SDJ3mL23G1pgfxTV7xMvzRqKxeuOzL4ZwOaNC1AMqaLEUqxkCr nY1PUiE9FMjBJCJvmYHZsa+rKx3bWm1tQAtbfftCaX0O4SqINkhG6ZLEgE6MbKFFDO ziioRYG7FGA2bhXhcGJE1oJzw/g82omBkhvhU5Z+PRyuWSyMnkdVv4YBaj/l3tJzYh /zRM7mwuBvP6w== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:38 +0200 Subject: [PATCH v2 60/63] selftests/namespaces: ninth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-60-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=5959; i=brauner@kernel.org; h=from:subject:message-id; bh=9gt1tGf0xzLbqqMQlOif9Kfq8cZPXlqC1fDbDaJd8HY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHi+48Ub8awebSYZqQBe41V3p6yYwf3qv9T+9nsJ8 62E10w931HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRI2cZ/spKfFRXWnv9gbBi 83GvVafCZKNWv7rbe1R83Yznt/gY5DcxMlw+vetx0uX+VTNu1X/b8N9vCze/yvlXK+Sjshw5n/9 yi+cCAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that socket-kept netns appears in listns() output. Verify that a network namespace kept alive by a socket FD appears in listns() output even after the creating process exits, and that it disappears when the socket is closed. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 204 +++++++++++++++++= ++++ 1 file changed, 204 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 1c40c7772ad4..7b3133f3898c 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -577,4 +577,208 @@ TEST(siocgskns_ipv6) close(current_netns_fd); } =20 +/* + * Test that socket-kept netns appears in listns() output. + * Verify that a network namespace kept alive by a socket FD appears in + * listns() output even after the creating process exits, and that it + * disappears when the socket is closed. + */ +TEST(siocgskns_listns_visibility) +{ + int sock_fd, netns_fd, owner_fd; + int ipc_sockets[2]; + pid_t pid; + int status; + __u64 netns_id, owner_id; + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[256]; + int ret, i; + bool found_netns =3D false; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create new netns and socket */ + close(ipc_sockets[0]); + + if (unshare(CLONE_NEWNET) < 0) { + close(ipc_sockets[1]); + exit(1); + } + + sock_fd =3D socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + close(ipc_sockets[1]); + exit(1); + } + + /* Send socket FD to parent via SCM_RIGHTS */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_sockets[1]); + exit(1); + } + + close(sock_fd); + close(ipc_sockets[1]); + exit(0); + } + + /* Parent: receive socket FD */ + close(ipc_sockets[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + ASSERT_EQ(n, 1); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + ASSERT_NE(cmsg, NULL); + memcpy(&sock_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) + SKIP(close(sock_fd); return, "Child failed to create namespace"); + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + /* Get namespace ID */ + ret =3D ioctl(netns_fd, NS_GET_ID, &netns_id); + if (ret < 0) { + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_ID not supported"); + ASSERT_EQ(ret, 0); + } + + /* Get owner user namespace */ + owner_fd =3D ioctl(netns_fd, NS_GET_USERNS); + if (owner_fd < 0) { + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_USERNS not supported"); + ASSERT_GE(owner_fd, 0); + } + + /* Get owner namespace ID */ + ret =3D ioctl(owner_fd, NS_GET_ID, &owner_id); + if (ret < 0) { + close(owner_fd); + close(sock_fd); + close(netns_fd); + ASSERT_EQ(ret, 0); + } + close(owner_fd); + + /* Namespace should appear in listns() output */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s", strerror(errno)); + ASSERT_GE(ret, 0); + } + + /* Search for our network namespace in the list */ + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) { + found_netns =3D true; + break; + } + } + + ASSERT_TRUE(found_netns); + TH_LOG("Found netns %llu in listns() output (kept alive by socket)", netn= s_id); + + /* Now verify with owner filtering */ + req.user_ns_id =3D owner_id; + found_netns =3D false; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) { + found_netns =3D true; + break; + } + } + + ASSERT_TRUE(found_netns); + TH_LOG("Found netns %llu owned by userns %llu", netns_id, owner_id); + + /* Close socket - namespace should become inactive and disappear from lis= tns() */ + close(sock_fd); + close(netns_fd); + + /* Verify it's no longer in listns() output */ + req.user_ns_id =3D 0; + found_netns =3D false; + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) { + found_netns =3D true; + break; + } + } + + ASSERT_FALSE(found_netns); + TH_LOG("Netns %llu correctly disappeared from listns() after socket close= d", netns_id); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 6AC1135A93A; Wed, 22 Oct 2025 16:11:30 +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=1761149490; cv=none; b=Q7CHPSrnPXf1KltJQPx81lpY2eyCag8aWFLyqgRwLOSE3wGHrJnCqYAF5ZAfjF6o3vCm78F8Xh+pc6ObOeJtnCKGpjEMkdTn9Sz7Dta4S2RQeZoexRuot/C/E6vqpdUYmsg3aA0jnkAE13vVvO54Bu5brlJpJSkyus5LchyLPsM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149490; c=relaxed/simple; bh=No7FiVmWoBp1LOFVcEEf9bBTlBW0Ya8SnK2b2s5KfDo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=H6PhyBEVVyi0uom4V1yEx7bht9xu+ZUFn6fEZfzG2T4VTsOeaa0wDlkyy0eHGDS+kz2O6G/pZZBd0MWzwy83quQw3xN3lOYNfof29k1aRkWGmg3koHayeVkqKR+FtAd9gbByFt/IC0gosmVdQP5E9mS5P46bMU7XZfVEu+H8Oug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nZddKlBn; 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="nZddKlBn" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B315C4CEE7; Wed, 22 Oct 2025 16:11:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149490; bh=No7FiVmWoBp1LOFVcEEf9bBTlBW0Ya8SnK2b2s5KfDo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nZddKlBna4fqY2Z96NW1OaUqRogY36gdzzIAaUyv6P/jceOUpY+um2wnamSO7H3Pv Vh5aAivZx08izL1IWCZsAXLuUmBHGtUna2CpCEROjVmNkmCzGcK6LAFdWpmHJRhH/R qED2Xtzpkq1WjJ3W2Yo5isCxM8LAzfBH12HK+nJyyZmsOGS+u+nQA04tnRZGCBpsxy SYE7XxVeF9TCM+aKmg4evL/Eq5bs1eixxl4OEw168a73tXGb9fCKUQyeyLPI4f7kOb qBD2enf3WIb/l/UAWerlKXarOWJNcYVYCHLtgui+EppY3J1Eb0adK6M6Ack6Zx8QIe Rt3BElwGpE7AA== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:39 +0200 Subject: [PATCH v2 61/63] selftests/namespaces: tenth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-61-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=6827; i=brauner@kernel.org; h=from:subject:message-id; bh=No7FiVmWoBp1LOFVcEEf9bBTlBW0Ya8SnK2b2s5KfDo=; b=kA0DAAoWkcYbwGV43KIByyZiAGj5AOegnCkeUijWzfVAEMyJlkANXq7MHw3xv0VPMhSQUgk27 oh1BAAWCgAdFiEEQIc0Vx6nDHizMmkokcYbwGV43KIFAmj5AOcACgkQkcYbwGV43KKm7QD+KvUq LTR/jdn7CU/P8vBUMdgL2KpFtWz6H72ubYzc3+4BAMUpTJ81orfwmq6x9IgTAK5LOkAW8BarmKC lpSXSodMN X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that socket-kept netns can be reopened via file handle. Verify that a network namespace kept alive by a socket FD can be reopened using file handles even after the creating process exits. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 203 +++++++++++++++++= ++++ 1 file changed, 203 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 7b3133f3898c..0ea5241f2b6f 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -781,4 +781,207 @@ TEST(siocgskns_listns_visibility) TH_LOG("Netns %llu correctly disappeared from listns() after socket close= d", netns_id); } =20 +/* + * Test that socket-kept netns can be reopened via file handle. + * Verify that a network namespace kept alive by a socket FD can be + * reopened using file handles even after the creating process exits. + */ +TEST(siocgskns_file_handle) +{ + int sock_fd, netns_fd, reopened_fd; + int ipc_sockets[2]; + pid_t pid; + int status; + struct stat st1, st2; + ino_t netns_ino; + __u64 netns_id; + struct file_handle *handle; + struct nsfs_file_handle *nsfs_fh; + int ret; + + /* Allocate file_handle structure for nsfs */ + handle =3D malloc(sizeof(struct file_handle) + sizeof(struct nsfs_file_ha= ndle)); + ASSERT_NE(handle, NULL); + handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + handle->handle_type =3D FILEID_NSFS; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create new netns and socket */ + close(ipc_sockets[0]); + + if (unshare(CLONE_NEWNET) < 0) { + close(ipc_sockets[1]); + exit(1); + } + + sock_fd =3D socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + close(ipc_sockets[1]); + exit(1); + } + + /* Send socket FD to parent via SCM_RIGHTS */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_sockets[1]); + exit(1); + } + + close(sock_fd); + close(ipc_sockets[1]); + exit(0); + } + + /* Parent: receive socket FD */ + close(ipc_sockets[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + ASSERT_EQ(n, 1); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + ASSERT_NE(cmsg, NULL); + memcpy(&sock_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + free(handle); + SKIP(close(sock_fd); return, "Child failed to create namespace"); + } + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + ASSERT_EQ(fstat(netns_fd, &st1), 0); + netns_ino =3D st1.st_ino; + + /* Get namespace ID */ + ret =3D ioctl(netns_fd, NS_GET_ID, &netns_id); + if (ret < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_ID not supported"); + ASSERT_EQ(ret, 0); + } + + /* Construct file handle from namespace ID */ + nsfs_fh =3D (struct nsfs_file_handle *)handle->f_handle; + nsfs_fh->ns_id =3D netns_id; + nsfs_fh->ns_type =3D 0; /* Type field not needed for reopening */ + nsfs_fh->ns_inum =3D 0; /* Inum field not needed for reopening */ + + TH_LOG("Constructed file handle for netns %lu (id=3D%llu)", netns_ino, ne= tns_id); + + /* Reopen namespace using file handle (while socket still keeps it alive)= */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D EOPNOTSUPP || errno =3D=3D ENOSYS || errno =3D=3D EBADF) + SKIP(return, "open_by_handle_at with FD_NSFS_ROOT not supported"); + TH_LOG("open_by_handle_at failed: %s", strerror(errno)); + ASSERT_GE(reopened_fd, 0); + } + + /* Verify it's the same namespace */ + ASSERT_EQ(fstat(reopened_fd, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + ASSERT_EQ(st1.st_dev, st2.st_dev); + + TH_LOG("Successfully reopened netns %lu via file handle", netns_ino); + + close(reopened_fd); + + /* Close the netns FD */ + close(netns_fd); + + /* Try to reopen via file handle - should fail since namespace is now ina= ctive */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd >=3D 0) { + /* This might succeed if there's still a reference somewhere */ + TH_LOG("Warning: reopened netns after socket closed (fd=3D%d)", reopened= _fd); + close(reopened_fd); + } else { + TH_LOG("Correctly failed to reopen inactive netns: %s", strerror(errno)); + } + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + /* Reopen namespace using file handle (while socket still keeps it alive)= */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D EOPNOTSUPP || errno =3D=3D ENOSYS || errno =3D=3D EBADF) + SKIP(return, "open_by_handle_at with FD_NSFS_ROOT not supported"); + TH_LOG("open_by_handle_at failed: %s", strerror(errno)); + ASSERT_GE(reopened_fd, 0); + } + + /* Verify it's the same namespace */ + ASSERT_EQ(fstat(reopened_fd, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + ASSERT_EQ(st1.st_dev, st2.st_dev); + + TH_LOG("Successfully reopened netns %lu via file handle", netns_ino); + + /* Close socket - namespace should become inactive */ + close(sock_fd); + free(handle); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 43F40384BA6; Wed, 22 Oct 2025 16:11: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=1761149496; cv=none; b=KHHMCwHgOJDfdYsodENV1aCWtpexzWBO5AiGtT51Dx0H0ybLJ4z1YAdWCTfHdsIR1R/z23COMZDOlezYTIsQvMiLU98HLPFDGhpexsamqKxrCovV8xcSBMjuJoYqPOODV2zGJngkOxcqSyMqvrN0U1J9+ZhVSYYFTKe0i1xf53o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149496; c=relaxed/simple; bh=vC413nkir1j9papm9PzpXouMCCkVqBfBTukOkwiE2ps=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ElZjebn/FADPygEJkAWh9sZKNlY0H0qnKG7H9SfndoCjV5tgOdX1qMPx5KsaEs5rBw171tOxlxLCldU/YlSnd8drRHIWmsaNy54n9RrMFtlZNq0pb8qveBNN7WMObKG6y3sUTKHQfIwdIIUGJ29AyU3z7oSoSxXr5g6UnTKXjJM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=sMFWKdF3; 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="sMFWKdF3" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B39C9C4CEE7; Wed, 22 Oct 2025 16:11:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149495; bh=vC413nkir1j9papm9PzpXouMCCkVqBfBTukOkwiE2ps=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=sMFWKdF3UWHhJjinRWS6t7J+srITxH0StIoTHUJbLPaE/BD+rIWJi3Vf4rAvg0X90 ZrW/pJ+gAAZr2IxxJcceTv1H1ja7ucKL6I0J8/HOPHxGfqoTMLy2rFOmN7/vT+6gMH JEsqjxm/TJRmhtufARhiH32nY5Sq0nGhheNaf+gk0S9B3LGiRM85O1nVUoqQhKIIKd YNTTLtANyp4IrDNKhdTbQ7F1X8P1Egw7IK+JrgNYkS7MHox7LK5JuK9uwUQ2e7N/wu d0J8aPWKzuTv7FwVpr7ZDLQgXr7xeUJkO2UCBuZBeUc55d4xsWajR8EDKOSReCOaB8 4ByNpecUxxmXQ== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:40 +0200 Subject: [PATCH v2 62/63] selftests/namespaces: eleventh inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-62-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=8746; i=brauner@kernel.org; h=from:subject:message-id; bh=vC413nkir1j9papm9PzpXouMCCkVqBfBTukOkwiE2ps=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHgR6bK8LsE0v3cGQ3a1tNTnqUz28iEqsV3Hg3WiF J+9vNDdUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMJGwWwz/M7eIPX2TF7mAaWKZ r0p69r7lKjevv98rUcfwb9rebYYSqxn+l2z+yd6x63zpbekN5uqTi7u8E6af/XNigkLUVd9HX45 JMQMA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test combined listns() and file handle operations with socket-kept netns. Create a netns, keep it alive with a socket, verify it appears in listns(), then reopen it via file handle obtained from listns() entry. Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 291 +++++++++++++++++= ++++ 1 file changed, 291 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 0ea5241f2b6f..a5a96509661e 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -984,4 +984,295 @@ TEST(siocgskns_file_handle) free(handle); } =20 +/* + * Test combined listns() and file handle operations with socket-kept netn= s. + * Create a netns, keep it alive with a socket, verify it appears in listn= s(), + * then reopen it via file handle obtained from listns() entry. + */ +TEST(siocgskns_listns_and_file_handle) +{ + int sock_fd, netns_fd, userns_fd, reopened_fd; + int ipc_sockets[2]; + pid_t pid; + int status; + struct stat st; + ino_t netns_ino; + __u64 netns_id, userns_id; + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET | CLONE_NEWUSER, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[256]; + int ret, i; + bool found_netns =3D false, found_userns =3D false; + struct file_handle *handle; + struct nsfs_file_handle *nsfs_fh; + + /* Allocate file_handle structure for nsfs */ + handle =3D malloc(sizeof(struct file_handle) + sizeof(struct nsfs_file_ha= ndle)); + ASSERT_NE(handle, NULL); + handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + handle->handle_type =3D FILEID_NSFS; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create new userns and netns with socket */ + close(ipc_sockets[0]); + + if (setup_userns() < 0) { + close(ipc_sockets[1]); + exit(1); + } + + if (unshare(CLONE_NEWNET) < 0) { + close(ipc_sockets[1]); + exit(1); + } + + sock_fd =3D socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + close(ipc_sockets[1]); + exit(1); + } + + /* Send socket FD to parent via SCM_RIGHTS */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_sockets[1]); + exit(1); + } + + close(sock_fd); + close(ipc_sockets[1]); + exit(0); + } + + /* Parent: receive socket FD */ + close(ipc_sockets[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + ASSERT_EQ(n, 1); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + ASSERT_NE(cmsg, NULL); + memcpy(&sock_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for child to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + free(handle); + SKIP(close(sock_fd); return, "Child failed to create namespace"); + } + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + ASSERT_EQ(fstat(netns_fd, &st), 0); + netns_ino =3D st.st_ino; + + /* Get namespace ID */ + ret =3D ioctl(netns_fd, NS_GET_ID, &netns_id); + if (ret < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_ID not supported"); + ASSERT_EQ(ret, 0); + } + + /* Get owner user namespace */ + userns_fd =3D ioctl(netns_fd, NS_GET_USERNS); + if (userns_fd < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_USERNS not supported"); + ASSERT_GE(userns_fd, 0); + } + + /* Get owner namespace ID */ + ret =3D ioctl(userns_fd, NS_GET_ID, &userns_id); + if (ret < 0) { + close(userns_fd); + free(handle); + close(sock_fd); + close(netns_fd); + ASSERT_EQ(ret, 0); + } + close(userns_fd); + + TH_LOG("Testing netns %lu (id=3D%llu) owned by userns id=3D%llu", netns_i= no, netns_id, userns_id); + + /* Verify namespace appears in listns() */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s", strerror(errno)); + ASSERT_GE(ret, 0); + } + + found_netns =3D false; + found_userns =3D false; + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) + found_netns =3D true; + if (ns_ids[i] =3D=3D userns_id) + found_userns =3D true; + } + ASSERT_TRUE(found_netns); + ASSERT_TRUE(found_userns); + TH_LOG("Found netns %llu in listns() output", netns_id); + + /* Construct file handle from namespace ID */ + nsfs_fh =3D (struct nsfs_file_handle *)handle->f_handle; + nsfs_fh->ns_id =3D netns_id; + nsfs_fh->ns_type =3D 0; + nsfs_fh->ns_inum =3D 0; + + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D EOPNOTSUPP || errno =3D=3D ENOSYS || errno =3D=3D EBADF) + SKIP(return, "open_by_handle_at with FD_NSFS_ROOT not supported"); + TH_LOG("open_by_handle_at failed: %s", strerror(errno)); + ASSERT_GE(reopened_fd, 0); + } + + struct stat reopened_st; + ASSERT_EQ(fstat(reopened_fd, &reopened_st), 0); + ASSERT_EQ(reopened_st.st_ino, netns_ino); + + TH_LOG("Successfully reopened netns %lu via file handle (socket-kept)", n= etns_ino); + + close(reopened_fd); + close(netns_fd); + + /* Try to reopen via file handle - should fail since namespace is now ina= ctive */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd >=3D 0) { + /* This might succeed if there's still a reference somewhere */ + TH_LOG("Warning: reopened netns after socket closed (fd=3D%d)", reopened= _fd); + close(reopened_fd); + } else { + TH_LOG("Correctly failed to reopen inactive netns: %s", strerror(errno)); + } + + /* Get network namespace from socket */ + netns_fd =3D ioctl(sock_fd, SIOCGSKNS); + if (netns_fd < 0) { + free(handle); + close(sock_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_fd, 0); + } + + /* Verify namespace appears in listns() */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s", strerror(errno)); + ASSERT_GE(ret, 0); + } + + found_netns =3D false; + found_userns =3D false; + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) + found_netns =3D true; + if (ns_ids[i] =3D=3D userns_id) + found_userns =3D true; + } + ASSERT_TRUE(found_netns); + ASSERT_TRUE(found_userns); + TH_LOG("Found netns %llu in listns() output", netns_id); + + close(netns_fd); + + /* Verify namespace appears in listns() */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + free(handle); + close(sock_fd); + close(netns_fd); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + TH_LOG("listns failed: %s", strerror(errno)); + ASSERT_GE(ret, 0); + } + + found_netns =3D false; + found_userns =3D false; + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_id) + found_netns =3D true; + if (ns_ids[i] =3D=3D userns_id) + found_userns =3D true; + } + ASSERT_FALSE(found_netns); + ASSERT_FALSE(found_userns); + TH_LOG("Netns %llu correctly disappeared from listns() after socket close= d", netns_id); + + close(sock_fd); + free(handle); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sat Feb 7 06:20:32 2026 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 7C563385593; Wed, 22 Oct 2025 16:11: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=1761149501; cv=none; b=LOdAWUn5+uQ7/kwfTvpnQoFtVWuaf8yTjGH7RxnoAIF2Obt3KmaSHrRLRK0/OPmtflaeQW9sefphWPlW99ZZNtF9M4WyAgWzl7O6duj+Q2QipIXvuxsGeHVOgBudDpwRroak/gxKmcwl0CW3h1fuPTya3iKqKRTKTS7ucXKRoHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149501; c=relaxed/simple; bh=hCsvfSo30jvB5RwCOJL1MYMpSNtYBU0UYAUtNvQDowU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Z22cASH9spxIW+xMyHAIzmETaM5MZlWzJ9SBi9RvedKJiXP20NZ9IP9vhnEFIkz9Y/bPIceQkabYpHztpPZBDc1fRfJBZZkgP9L8ezcLaNIEjOmhLG5DKwmXIgqY9ymCYdhdLn2N0/orZdhl4YlAy+1y2gaO7FDnjkKNdEYK6W4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=j9weLslz; 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="j9weLslz" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 308D5C4CEF7; Wed, 22 Oct 2025 16:11:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761149501; bh=hCsvfSo30jvB5RwCOJL1MYMpSNtYBU0UYAUtNvQDowU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=j9weLslzwz8F6T8Y0qJtOKkaXQvpuBn+FrHJsbK5gKoOOY0q5ylVSU8THr2molHGg VqEJFq0VZznX50AWltvGG63XWmMpFNcTgoxrT0NQF5YfPjr6RyZ0xCYe7m1yNbwvBy Ej+C/bIvKQTPrYIjoXUscsaTZOmVKCDPKILm4nhza89gQv7vAnXoulja2AfzKawROm 5sZ6ADSoxGcV6bw2eBlVtut9+yto2eQ/JChQhBYcAXj/Uyzp6tnhU1CCwGFNhdWYQR 2ZMTQBToUuoRA7m4kwV/vjgygvkEzdm+jrO4jXC06n8OMpJ/EYtn9V7/V+fele9YX4 2NyqS7e/uv9sw== From: Christian Brauner Date: Wed, 22 Oct 2025 18:06:41 +0200 Subject: [PATCH v2 63/63] selftests/namespaces: twelth inactive namespace resurrection test Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251022-work-namespace-nstree-listns-v2-63-71a588572371@kernel.org> References: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> In-Reply-To: <20251022-work-namespace-nstree-listns-v2-0-71a588572371@kernel.org> To: linux-fsdevel@vger.kernel.org, Josef Bacik , Jeff Layton Cc: Jann Horn , Mike Yuan , =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= , Lennart Poettering , Daan De Meyer , Aleksa Sarai , Amir Goldstein , Tejun Heo , Johannes Weiner , Thomas Gleixner , Alexander Viro , Jan Kara , linux-kernel@vger.kernel.org, cgroups@vger.kernel.org, bpf@vger.kernel.org, Eric Dumazet , Jakub Kicinski , netdev@vger.kernel.org, Arnd Bergmann , Christian Brauner X-Mailer: b4 0.15-dev-96507 X-Developer-Signature: v=1; a=openpgp-sha256; l=18202; i=brauner@kernel.org; h=from:subject:message-id; bh=hCsvfSo30jvB5RwCOJL1MYMpSNtYBU0UYAUtNvQDowU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8ZHghq+O/xf5D9q0r8buFt3y7+V3A5/mRWIsVpy0Vk 1OZG+v5OkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACby7STD/xiWWypR5VJHRWxr ou11vm2r3Ht7A2fGTGH57hye8JxIf0aGwxoLmRqMxH48tdNX/yFUknw7j7Hsld17ffHEBX1/3+7 lAQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test multi-level namespace resurrection across three user namespace levels. This test creates a complex namespace hierarchy with three levels of user namespaces and a network namespace at the deepest level. It verifies that the resurrection semantics work correctly when SIOCGSKNS is called on a socket from an inactive namespace tree, and that listns() and open_by_handle_at() correctly respect visibility rules. Hierarchy after child processes exit (all with 0 active refcount): net_L3A (0) <- Level 3 network namespace | + userns_L3 (0) <- Level 3 user namespace | + userns_L2 (0) <- Level 2 user namespace | + userns_L1 (0) <- Level 1 user namespace | x init_user_ns The test verifies: 1. SIOCGSKNS on a socket from inactive net_L3A resurrects the entire chain 2. After resurrection, all namespaces are visible in listns() 3. Resurrected namespaces can be reopened via file handles 4. Closing the netns FD cascades down: the entire ownership chain (userns_L3 -> userns_L2 -> userns_L1) becomes inactive again 5. Inactive namespaces disappear from listns() and cannot be reopened 6. Calling SIOCGSKNS again on the same socket resurrects the tree again 7. After second resurrection, namespaces are visible and can be reopened Signed-off-by: Christian Brauner --- .../testing/selftests/namespaces/siocgskns_test.c | 569 +++++++++++++++++= ++++ 1 file changed, 569 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index a5a96509661e..90af54062ab8 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -1275,4 +1275,573 @@ TEST(siocgskns_listns_and_file_handle) free(handle); } =20 +/* + * Test multi-level namespace resurrection across three user namespace lev= els. + * + * This test creates a complex namespace hierarchy with three levels of us= er + * namespaces and a network namespace at the deepest level. It verifies th= at + * the resurrection semantics work correctly when SIOCGSKNS is called on a + * socket from an inactive namespace tree, and that listns() and + * open_by_handle_at() correctly respect visibility rules. + * + * Hierarchy after child processes exit (all with 0 active refcount): + * + * net_L3A (0) <- Level 3 network namespace + * | + * + + * userns_L3 (0) <- Level 3 user namespace + * | + * + + * userns_L2 (0) <- Level 2 user namespace + * | + * + + * userns_L1 (0) <- Level 1 user namespace + * | + * x + * init_user_ns + * + * The test verifies: + * 1. SIOCGSKNS on a socket from inactive net_L3A resurrects the entire ch= ain + * 2. After resurrection, all namespaces are visible in listns() + * 3. Resurrected namespaces can be reopened via file handles + * 4. Closing the netns FD cascades down: the entire ownership chain + * (userns_L3 -> userns_L2 -> userns_L1) becomes inactive again + * 5. Inactive namespaces disappear from listns() and cannot be reopened + * 6. Calling SIOCGSKNS again on the same socket resurrects the tree again + * 7. After second resurrection, namespaces are visible and can be reopened + */ +TEST(siocgskns_multilevel_resurrection) +{ + int ipc_sockets[2]; + pid_t pid_l1, pid_l2, pid_l3; + int status; + + /* Namespace file descriptors to be received from child */ + int sock_L3A_fd =3D -1; + int netns_L3A_fd =3D -1; + __u64 netns_L3A_id; + __u64 userns_L1_id, userns_L2_id, userns_L3_id; + + /* For listns() and file handle testing */ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWNET | CLONE_NEWUSER, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[256]; + int ret, i; + struct file_handle *handle; + struct nsfs_file_handle *nsfs_fh; + int reopened_fd; + + /* Allocate file handle for testing */ + handle =3D malloc(sizeof(struct file_handle) + sizeof(struct nsfs_file_ha= ndle)); + ASSERT_NE(handle, NULL); + handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + handle->handle_type =3D FILEID_NSFS; + + EXPECT_EQ(socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets= ), 0); + + /* + * Fork level 1 child that creates userns_L1 + */ + pid_l1 =3D fork(); + ASSERT_GE(pid_l1, 0); + + if (pid_l1 =3D=3D 0) { + /* Level 1 child */ + int ipc_L2[2]; + close(ipc_sockets[0]); + + /* Create userns_L1 */ + if (setup_userns() < 0) { + close(ipc_sockets[1]); + exit(1); + } + + /* Create socketpair for communicating with L2 child */ + if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_L2) < 0) { + close(ipc_sockets[1]); + exit(1); + } + + /* + * Fork level 2 child that creates userns_L2 + */ + pid_l2 =3D fork(); + if (pid_l2 < 0) { + close(ipc_sockets[1]); + close(ipc_L2[0]); + close(ipc_L2[1]); + exit(1); + } + + if (pid_l2 =3D=3D 0) { + /* Level 2 child */ + int ipc_L3[2]; + close(ipc_L2[0]); + + /* Create userns_L2 (nested inside userns_L1) */ + if (setup_userns() < 0) { + close(ipc_L2[1]); + exit(1); + } + + /* Create socketpair for communicating with L3 child */ + if (socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_L3) < 0) { + close(ipc_L2[1]); + exit(1); + } + + /* + * Fork level 3 child that creates userns_L3 and network namespaces + */ + pid_l3 =3D fork(); + if (pid_l3 < 0) { + close(ipc_L2[1]); + close(ipc_L3[0]); + close(ipc_L3[1]); + exit(1); + } + + if (pid_l3 =3D=3D 0) { + /* Level 3 child - the deepest level */ + int sock_fd; + close(ipc_L3[0]); + + /* Create userns_L3 (nested inside userns_L2) */ + if (setup_userns() < 0) { + close(ipc_L3[1]); + exit(1); + } + + /* Create network namespace at level 3 */ + if (unshare(CLONE_NEWNET) < 0) { + close(ipc_L3[1]); + exit(1); + } + + /* Create socket in net_L3A */ + sock_fd =3D socket(AF_INET, SOCK_DGRAM, 0); + if (sock_fd < 0) { + close(ipc_L3[1]); + exit(1); + } + + /* Send socket FD to L2 parent */ + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1] =3D {'X'}; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &sock_fd, sizeof(int)); + + if (sendmsg(ipc_L3[1], &msg, 0) < 0) { + close(sock_fd); + close(ipc_L3[1]); + exit(1); + } + + close(sock_fd); + close(ipc_L3[1]); + exit(0); + } + + /* Level 2 child - receive from L3 and forward to L1 */ + close(ipc_L3[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + int received_fd; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_L3[0], &msg, 0); + close(ipc_L3[0]); + + if (n !=3D 1) { + close(ipc_L2[1]); + waitpid(pid_l3, NULL, 0); + exit(1); + } + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + if (!cmsg) { + close(ipc_L2[1]); + waitpid(pid_l3, NULL, 0); + exit(1); + } + memcpy(&received_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for L3 child */ + waitpid(pid_l3, NULL, 0); + + /* Forward the socket FD to L1 parent */ + memset(&msg, 0, sizeof(msg)); + buf[0] =3D 'Y'; + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &received_fd, sizeof(int)); + + if (sendmsg(ipc_L2[1], &msg, 0) < 0) { + close(received_fd); + close(ipc_L2[1]); + exit(1); + } + + close(received_fd); + close(ipc_L2[1]); + exit(0); + } + + /* Level 1 child - receive from L2 and forward to parent */ + close(ipc_L2[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + int received_fd; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_L2[0], &msg, 0); + close(ipc_L2[0]); + + if (n !=3D 1) { + close(ipc_sockets[1]); + waitpid(pid_l2, NULL, 0); + exit(1); + } + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + if (!cmsg) { + close(ipc_sockets[1]); + waitpid(pid_l2, NULL, 0); + exit(1); + } + memcpy(&received_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for L2 child */ + waitpid(pid_l2, NULL, 0); + + /* Forward the socket FD to parent */ + memset(&msg, 0, sizeof(msg)); + buf[0] =3D 'Z'; + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(int)); + memcpy(CMSG_DATA(cmsg), &received_fd, sizeof(int)); + + if (sendmsg(ipc_sockets[1], &msg, 0) < 0) { + close(received_fd); + close(ipc_sockets[1]); + exit(1); + } + + close(received_fd); + close(ipc_sockets[1]); + exit(0); + } + + /* Parent - receive the socket from the deepest level */ + close(ipc_sockets[1]); + + struct msghdr msg =3D {0}; + struct iovec iov =3D {0}; + char buf[1]; + char cmsg_buf[CMSG_SPACE(sizeof(int))]; + + iov.iov_base =3D buf; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_control =3D cmsg_buf; + msg.msg_controllen =3D sizeof(cmsg_buf); + + ssize_t n =3D recvmsg(ipc_sockets[0], &msg, 0); + close(ipc_sockets[0]); + + if (n !=3D 1) { + free(handle); + waitpid(pid_l1, NULL, 0); + SKIP(return, "Failed to receive socket from child"); + } + + struct cmsghdr *cmsg =3D CMSG_FIRSTHDR(&msg); + if (!cmsg) { + free(handle); + waitpid(pid_l1, NULL, 0); + SKIP(return, "Failed to receive socket from child"); + } + memcpy(&sock_L3A_fd, CMSG_DATA(cmsg), sizeof(int)); + + /* Wait for L1 child */ + waitpid(pid_l1, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + free(handle); + if (sock_L3A_fd >=3D 0) + close(sock_L3A_fd); + SKIP(return, "Child process failed to create namespace hierarchy"); + } + + /* + * At this point, all child processes have exited. The socket itself + * doesn't keep the namespace active - we need to call SIOCGSKNS which + * will resurrect the entire namespace tree by taking active references. + */ + + /* Get network namespace from socket - this resurrects the tree */ + netns_L3A_fd =3D ioctl(sock_L3A_fd, SIOCGSKNS); + if (netns_L3A_fd < 0) { + free(handle); + close(sock_L3A_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "SIOCGSKNS not supported"); + ASSERT_GE(netns_L3A_fd, 0); + } + + /* Get namespace ID for net_L3A */ + ret =3D ioctl(netns_L3A_fd, NS_GET_ID, &netns_L3A_id); + if (ret < 0) { + free(handle); + close(sock_L3A_fd); + close(netns_L3A_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_ID not supported"); + ASSERT_EQ(ret, 0); + } + + /* Get owner user namespace chain: userns_L3 -> userns_L2 -> userns_L1 */ + int userns_L3_fd =3D ioctl(netns_L3A_fd, NS_GET_USERNS); + if (userns_L3_fd < 0) { + free(handle); + close(sock_L3A_fd); + close(netns_L3A_fd); + if (errno =3D=3D ENOTTY || errno =3D=3D EINVAL) + SKIP(return, "NS_GET_USERNS not supported"); + ASSERT_GE(userns_L3_fd, 0); + } + + ret =3D ioctl(userns_L3_fd, NS_GET_ID, &userns_L3_id); + ASSERT_EQ(ret, 0); + + int userns_L2_fd =3D ioctl(userns_L3_fd, NS_GET_USERNS); + ASSERT_GE(userns_L2_fd, 0); + ret =3D ioctl(userns_L2_fd, NS_GET_ID, &userns_L2_id); + ASSERT_EQ(ret, 0); + + int userns_L1_fd =3D ioctl(userns_L2_fd, NS_GET_USERNS); + ASSERT_GE(userns_L1_fd, 0); + ret =3D ioctl(userns_L1_fd, NS_GET_ID, &userns_L1_id); + ASSERT_EQ(ret, 0); + + close(userns_L1_fd); + close(userns_L2_fd); + close(userns_L3_fd); + + TH_LOG("Multi-level hierarchy: net_L3A (id=3D%llu) -> userns_L3 (id=3D%ll= u) -> userns_L2 (id=3D%llu) -> userns_L1 (id=3D%llu)", + netns_L3A_id, userns_L3_id, userns_L2_id, userns_L1_id); + + /* + * Test 1: Verify net_L3A is visible in listns() after resurrection. + * The entire ownership chain should be resurrected and visible. + */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + free(handle); + close(sock_L3A_fd); + close(netns_L3A_fd); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + ASSERT_GE(ret, 0); + } + + bool found_netns_L3A =3D false; + bool found_userns_L1 =3D false; + bool found_userns_L2 =3D false; + bool found_userns_L3 =3D false; + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_L3A_id) + found_netns_L3A =3D true; + if (ns_ids[i] =3D=3D userns_L1_id) + found_userns_L1 =3D true; + if (ns_ids[i] =3D=3D userns_L2_id) + found_userns_L2 =3D true; + if (ns_ids[i] =3D=3D userns_L3_id) + found_userns_L3 =3D true; + } + + ASSERT_TRUE(found_netns_L3A); + ASSERT_TRUE(found_userns_L1); + ASSERT_TRUE(found_userns_L2); + ASSERT_TRUE(found_userns_L3); + TH_LOG("Resurrection verified: all namespaces in hierarchy visible in lis= tns()"); + + /* + * Test 2: Verify net_L3A can be reopened via file handle. + */ + nsfs_fh =3D (struct nsfs_file_handle *)handle->f_handle; + nsfs_fh->ns_id =3D netns_L3A_id; + nsfs_fh->ns_type =3D 0; + nsfs_fh->ns_inum =3D 0; + + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd < 0) { + free(handle); + close(sock_L3A_fd); + close(netns_L3A_fd); + if (errno =3D=3D EOPNOTSUPP || errno =3D=3D ENOSYS || errno =3D=3D EBADF) + SKIP(return, "open_by_handle_at with FD_NSFS_ROOT not supported"); + TH_LOG("open_by_handle_at failed: %s", strerror(errno)); + ASSERT_GE(reopened_fd, 0); + } + + close(reopened_fd); + TH_LOG("File handle test passed: net_L3A can be reopened"); + + /* + * Test 3: Verify that when we close the netns FD (dropping the last + * active reference), the entire tree becomes inactive and disappears + * from listns(). The cascade goes: net_L3A drops -> userns_L3 drops -> + * userns_L2 drops -> userns_L1 drops. + */ + close(netns_L3A_fd); + + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + found_netns_L3A =3D false; + found_userns_L1 =3D false; + found_userns_L2 =3D false; + found_userns_L3 =3D false; + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_L3A_id) + found_netns_L3A =3D true; + if (ns_ids[i] =3D=3D userns_L1_id) + found_userns_L1 =3D true; + if (ns_ids[i] =3D=3D userns_L2_id) + found_userns_L2 =3D true; + if (ns_ids[i] =3D=3D userns_L3_id) + found_userns_L3 =3D true; + } + + ASSERT_FALSE(found_netns_L3A); + ASSERT_FALSE(found_userns_L1); + ASSERT_FALSE(found_userns_L2); + ASSERT_FALSE(found_userns_L3); + TH_LOG("Cascade test passed: all namespaces disappeared after netns FD cl= osed"); + + /* + * Test 4: Verify file handle no longer works for inactive namespace. + */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd >=3D 0) { + close(reopened_fd); + free(handle); + ASSERT_TRUE(false); /* Should have failed */ + } + TH_LOG("Inactive namespace correctly cannot be reopened via file handle"); + + /* + * Test 5: Verify that calling SIOCGSKNS again resurrects the tree again. + * The socket is still valid, so we can call SIOCGSKNS on it to resurrect + * the namespace tree once more. + */ + netns_L3A_fd =3D ioctl(sock_L3A_fd, SIOCGSKNS); + ASSERT_GE(netns_L3A_fd, 0); + + TH_LOG("Called SIOCGSKNS again to resurrect the namespace tree"); + + /* Verify the namespace tree is resurrected and visible in listns() */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + found_netns_L3A =3D false; + found_userns_L1 =3D false; + found_userns_L2 =3D false; + found_userns_L3 =3D false; + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D netns_L3A_id) + found_netns_L3A =3D true; + if (ns_ids[i] =3D=3D userns_L1_id) + found_userns_L1 =3D true; + if (ns_ids[i] =3D=3D userns_L2_id) + found_userns_L2 =3D true; + if (ns_ids[i] =3D=3D userns_L3_id) + found_userns_L3 =3D true; + } + + ASSERT_TRUE(found_netns_L3A); + ASSERT_TRUE(found_userns_L1); + ASSERT_TRUE(found_userns_L2); + ASSERT_TRUE(found_userns_L3); + TH_LOG("Second resurrection verified: all namespaces in hierarchy visible= in listns() again"); + + /* Verify we can reopen via file handle again */ + reopened_fd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + if (reopened_fd < 0) { + free(handle); + close(sock_L3A_fd); + close(netns_L3A_fd); + TH_LOG("open_by_handle_at failed after second resurrection: %s", strerro= r(errno)); + ASSERT_GE(reopened_fd, 0); + } + + close(reopened_fd); + TH_LOG("File handle test passed: net_L3A can be reopened after second res= urrection"); + + /* Final cleanup */ + close(sock_L3A_fd); + close(netns_L3A_fd); + free(handle); +} + TEST_HARNESS_MAIN --=20 2.47.3