From nobody Sun Feb 8 07:58:47 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 11B7930E0E7; Fri, 24 Oct 2025 10:53:06 +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=1761303187; cv=none; b=T9XcYQ9gHvU/2RcE2yM7c8Y/xV+1pigDjBt/oqoFRLDeOGjBTnXwQKMKoA141aHdK+P8zwRd1YYAxlPZ4Wqmi9K7IXGTW0LQycrgZmzTEUA9wIc2oxO7vxu3wesIEobOlLN2KTjnCj/qDAaDRcaUlXZ6JFec+bSbdrfrrxBiIY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303187; c=relaxed/simple; bh=wpu8fA7qXxdZSYnV2Wt9hfd/qe1FdRoJcNk3AI3VvA4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=u/JDPmQpntaK8qI0y+il9xyJhoQIsbdC2Id+KDm1cFt53jSfAdzoh0q2no6XuQZjy/LP4CO32fizgQn5s85D/QMv/8CKnibtJjSf0QgWecF6MbxvISPmqEFxUHxRusQfK6ZTanVFPJCqPAD2Pg6vdLDU+soCJ2Vfyd8jBI4lriQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=kDMSPBmt; 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="kDMSPBmt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0D049C116B1; Fri, 24 Oct 2025 10:53:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303186; bh=wpu8fA7qXxdZSYnV2Wt9hfd/qe1FdRoJcNk3AI3VvA4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=kDMSPBmtRj26rFr7amHZs5Me8zv5KQtORio0ATW0/AFODAt5alD3IEK7bsLKalrft J1cxy7Z3v/ol+zt03ogwZo04go708SQhx4OYyFJJwULhnejlUcS/eDrQnjCbbyG4hD FhLlpywHhBXgRx1gkv0Mp3ZkRPMV6nx7X3NmH0joDVPxXz5lbjzMfT9/7ddZo6D+Yf T5D32b/SM9GoH0KkF+FCbKIzA2UQtFVnQBDhhYpNeWticNUXXWEkzWqa80jOVR/mE9 FxZD56xfSSdSnAlAXjPt7C4N6HO3W0kwOPa0qoZEKVPCd1CqTdU1+XHykf160eCuWD Fi/h2exnYRAGg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:30 +0200 Subject: [PATCH v3 01/70] 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: <20251024-work-namespace-nstree-listns-v3-1-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrp8UqpYDYQ/PZsj+1N+7VnLt/5lFgWMZvnwfGte 94xOvhHdZSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzk0xZGhi7nL2mXfQ4d9TgS Pm+J8qejLOK50644C/SlHuI/l2F+npmRYc3d/Le2q/tkjpyJcffj1lrz5aJZ+ARV472TW+tcKpo XsgEA 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 E1AE231076A; Fri, 24 Oct 2025 10:53:11 +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=1761303192; cv=none; b=RmeZ/uEq7P8WbdGM4NrIlm4VaF1r/No9Op++OeYCDVlfV93aC4Yg/NA9u5rfvsM63/X9gPgc0Q1DtWo8oIMy/WnZIDfoHdeg2cMRyi0OFLlDRbNaF8o7+jB0jr9cNPROFJ+R/SGVKczleyNeVeOZ75zDQQINFbktA+b7fX52WMY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303192; c=relaxed/simple; bh=jSqJBpD/6utq5kB6r0uVAxUcKbpMKsXXqLyZPGG0ICk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lKcI9LvIxRfK7DhtXF/mR68g8WE/Cw62aMuSFLHX7fTpd8lE8XqBXTAn1S/t0zBDq711UETZvl7Kffihm17BsTLpacRfamgPCawHQIOStdN5tFxsJmwzKlsl/lBp21mZ46jMJCL0b1y3eGMfyX+hFguVerJ1cBP03PEQ18V0eBA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G31kf5m/; 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="G31kf5m/" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 05E4EC4CEF1; Fri, 24 Oct 2025 10:53:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303191; bh=jSqJBpD/6utq5kB6r0uVAxUcKbpMKsXXqLyZPGG0ICk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=G31kf5m/LSFYhjq1IOaX4YAEqQY/W/N9UOg3enrdmQcBW5xHVaBfNbQUKr+53eCBz 19uE03qcFrUPj0IkcjEQSFWpax8Mh/0H5AfJ9X3aYys5o1Tm3deZFdy3PoqNVbNHE/ l/nN6v9zTRj1xjZUrciwAzLKNIb1zg95avHq2ZuoXqS0sUwMYsAgxXeEvb2tsHNTyH HWChmysoioyTE1ZlPceSxmg3wWe9vpKLdt+HJPykapA7f14eRmvAR66NXL72lYrvLq FenxHKGA0w/VF2Fj2PTly7DxecjpWNJwO+b1PYxcUCpc1W3XFpmcrdYIxWBVqHigr6 b7Hp8oCpU5POw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:31 +0200 Subject: [PATCH v3 02/70] 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: <20251024-work-namespace-nstree-listns-v3-2-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmppq/uX1KRX+qo9LCBeQf1WftD0Ff35oRHt7z4nz vmiwsXZUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMJFtPxn+cG+LfP5CeX7Y6dqA 1TNLuSZaPov4e5ihnpHBo+f+64ux/xn++1mdconXnFj3VDfg8qvq4gsFO2TvJt5Yktbukvw955A cDwA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 19077313536; Fri, 24 Oct 2025 10:53:16 +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=1761303197; cv=none; b=XRNhUGcLleX8ZaLyt19X8NO6IcAcP2Fr45EeaF4TQ0tnVNszqPxBR+NqaZkNz4bTg5YwaIjJa1J03yDHPPmJckrvijI90xeHbA9h/zShA0PQYuobaDdRTZaQKKanmbdihUGhMb4p26igWBvWh40ptx26t5YDkMrJYbZJCu0MTP4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303197; c=relaxed/simple; bh=VMCLQ5Neu+JsCPfFhnjTC4pvJzkr6RMBoSrPUgoYfJM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GWuiaxSL2c3HCLpry2A6/y5vRYZNifGcZ3LcWMu4CWpV2W5wpLS+oV7u/a75lfOcVqJpKb+0X/HMVscQiTSOiZdOO+B7dsMaNH9URFvAeYNVTMjDv8M4av5U54XpZYvWBp4Ip5Ec3Yo885/gZKKns+ZwSUvuWUWQyAYtvYhe7SI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NJXVDo6i; 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="NJXVDo6i" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 00F45C4CEF5; Fri, 24 Oct 2025 10:53:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303196; bh=VMCLQ5Neu+JsCPfFhnjTC4pvJzkr6RMBoSrPUgoYfJM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NJXVDo6ifCMqXV3ZT+yOB+nXERgroeLT3Q3pckKV6NCQ05eOFRL1rzzpTN7p2m2IS 18r2xTd61k57/SLZMfjkg7NCHRCcUeXwJCpkaYbj0ksg7PV8sgTJp+smcL4iaC0VO6 772335U69i3d3QgSQqopoSJTvwPAEX31GDDd9/sKcf/FgNEc/cVdUf52TYcf44nAcR yngvJTBWx92wRVG0U+uc4D2MjIFIhXWJlFPIXGUZ6K7YcymK9WOe6yqW0TtIW/HB4X M2sQrzHq1KkzSZha3eKi0/ygCidCvzqWK1Zmpp/gARckXo57LCBT/PgCS+YvS/ZBc/ 216bj1wcRlkRg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:32 +0200 Subject: [PATCH v3 03/70] 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: <20251024-work-namespace-nstree-listns-v3-3-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqpvd1x0tv61LQQXnXO+/yfTr8IDk8tZZt+Uo5zT tsjwxdeHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABNh+8fIsOLsDNY1AfmbT/cL C8Wwa12a8+zF5DyPXpUDbmu/1jFtzGf475Ln7T77kuwUu2fbc3Yob/iQyrxg9q3MnvD63uXiLv3 u3AA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 201D0311C15; Fri, 24 Oct 2025 10:53: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=1761303202; cv=none; b=a5J3y+70B32RCmRskDGtt8kXo6f/rNuN49p9o5s6s0MuOXfKEwTyjREcpM8dJsXsbrqLBRKcu7X4zDpTnanhTDdAJwv2/WBzLAfrf5HCCHm7kRa9oigDduxhqJPfwi4cXfKZb4Q4har2JLhq8hvFqKGZMTZu09kc6o7g+n5LJTY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303202; c=relaxed/simple; bh=LCe8V3QgmxQPWsHxmkO/HYNSTPj5l9bqGO1onywb9Xk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tEdJoBXhH4XklmNZpWAMtmzrsyTQ8+aQXPsDGDZEdrOyDO5SoZuLcZOGD/KyHP3KNQTuWxa1O9qg/g6IfVr1A6Q+gvZw0XyWPJYxMB6QNecvYz59KmmMNypfmAwWFGyrIix7uT+foPX/3phr8pj9qDKjiVthS2JS9vqPFYbjQbg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ZoYqnB9K; 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="ZoYqnB9K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1184AC4CEF1; Fri, 24 Oct 2025 10:53:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303201; bh=LCe8V3QgmxQPWsHxmkO/HYNSTPj5l9bqGO1onywb9Xk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ZoYqnB9KL4SLwPaLgd/xoT9eRT5rR7P8yMRIpW4Fhd1E2paUg41wvhKY0kKRHEq4l XbMNEYSJnU2XslSBWSq1ul3zxUecZGylZfo3/kTXyzQcFfO/E1wmmNTubfI90vr6tI AuwG/d+6Vy/uS/eEIt7A7lRv4MrusY2OgcEOr/A8BOnbvk1VhTrBLu/Z1F4CEAoaRn XUSCEXfghBAzmCaBgePDvFFjS4Mlcauw5srpSG2XtFy+zaa4mhCzpe6NNP6flKHIaE HF58q4H+NSG2Qb1Y3XivLqE7YE0EYUVFJ9BVZeDFYt4s6s8hYBSS48tP+GM8QPujAA O0OTCwouDgW8Q== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:33 +0200 Subject: [PATCH v3 04/70] 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: <20251024-work-namespace-nstree-listns-v3-4-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqZHX2c71C5nN/fdwzZxZUpjxw5FN+bTFgjZ2y9O yeo/PaujlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlMiGD4ZyWe80kkSev6p3NF Sa4qojb5pUys2iol6cuuWj1JUt/QxMiwOeNG/44k+8RT59X8uD3FayfN9V0+8fo9e+YHsiqfjnn xAwA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 297BC3126B0; Fri, 24 Oct 2025 10:53: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=1761303207; cv=none; b=P3h/tWYaAVLYEJohiagi9Dqc201Gb6tmT63JEhfWW99juw8mqUnPb6LGuqrj1uaOGMSGu2eUZ3wOOETLWXWIRVmeZbOEYGvTJ3V0TTzzsjeiiQosrjksyBWwYYIx0CCVpKEcTWI1GDr+vUu8uMV1M0B4JJicFd1L3IaxlHdK3g0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303207; c=relaxed/simple; bh=KoKI9phRTGMhjpn+9D8BgtjcoxSIgpJa0JnjxzKpEbY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RHJtsyqbZUcaFKRjuIioXPNuikuN0EX1Vm3g/Ic1fG8e4RFcHMG+aqI69bZdP5F5HLxPl4ujIN1vngpqp5oYdNTMnJYfuCKjDeIzr8rrhVc/0h9a5EVtKcFdbGQ0b9aHktwjvXW7jOuDj5Oo+T9JboYxw8OwVBwNbm/lr+Z/fEg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LQtZcKCU; 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="LQtZcKCU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2CA43C4CEF5; Fri, 24 Oct 2025 10:53:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303206; bh=KoKI9phRTGMhjpn+9D8BgtjcoxSIgpJa0JnjxzKpEbY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LQtZcKCUECJ4AiyPF2OogZQsWCHtGi6dLz4z5WiF+jcJKEU1YPkl+IE0BszPeq80w 2X/RQm89VASsp7NYMx0NydKahTT/39rek7p6HtJ8gUtpsfegaE4nfpjNd3IAlvVWF2 bqFSX9E1l+54aEP4WR8e/0zn/c4TWikaA2GzhRLkGm2WfkVHVwaQdVie9kjRBfbvVw u/PWo1i/aTPPoved4Jft5yUttujrHHlB/ufkNTEbksDOfR/9+IE9vLIg1Qcn/hm/TN hPeoRKzIqdAOoPUuv5pv97Zeon/s0VqnEBB2zMePx5MAgfybKWpVXb9xNlkuuQCDcw VyR4ZoNMUUvUQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:34 +0200 Subject: [PATCH v3 05/70] 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: <20251024-work-namespace-nstree-listns-v3-5-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp5KrkxSMG6zOj1lnJ36biiyFv7myOS7UtNHeX6d vXfWszRUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMJECL4Z/ej+/Ke0Q7OAurDrA 0uD37EfOOrkw3Wux31XOlF3hDV7znZHhoKroxDQWCYH5k98yGO1TNhO9GnN9M/c9FWaeuJVTNU4 wAAA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 C726C3126C7; Fri, 24 Oct 2025 10:53: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=1761303211; cv=none; b=fg4+H2N5+FnQuJiqBz8VYa4sMVL49NuUhI6OyJ9htceWN1Z8eD7KLNqVPwYR2IfaVilba9k9m3tAkeTnJhRhBPytgOO5qw7H1UDmqRWz6MyU3s7fZwIm0sjs3YjlTKzSSfgQw1iGzwzGttaRhWNkGDy2fUqilzHbmhDlwwJ35Yk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303211; c=relaxed/simple; bh=74AZcYyOqxtykIDy/RGdL2vrgfuHMaAEm8WcGrCjYG4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mzaPIEZGcOi8mLkH6KtfoC95yJCJSnhmZ06Og7WZ+DOf5eQeuEu/OvKZyWq/uKBYIhTMyW8UdWUkcJ1ndhcp17aAYvSdtFOnfRLIHk1BaqnNb3gE2kJYQFFwD9BpAn2rxHl28fJmeajv0AxmzXv157bJtvWBdJHvThmZ7f7gpYQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=rwBPmxQu; 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="rwBPmxQu" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 271EDC4CEF1; Fri, 24 Oct 2025 10:53:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303211; bh=74AZcYyOqxtykIDy/RGdL2vrgfuHMaAEm8WcGrCjYG4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rwBPmxQuvvRwSb5irTHJqsFp02PfOUotVvq7YyND6SwL1mkek2U+SPuhRD3gaWHKx XPPweYijvHDEan0SBgsIEAiMS4sbdjsKhOAp+SpSBkwXPOajW86v+jQAcSxBh16ED3 C90JBNmvvJtS0HHktVbWPyaRSOCBokdn5LryB3BDTADGbIbLhME4wXW97An7xdRsPP OR+DsIqfxGdtdwYjp404UQsW5hmTFfkz0dpZM6FD0z2MtOPRLDvjold4Nr5koYtgec rrgMmfN9B7E3kOUaOpbtM0yoVtx8UbsNc6Sa7CbQIAn7j4nS2WkUyJcM77UB8kgAl/ lO0LX0Cv+288A== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:35 +0200 Subject: [PATCH v3 06/70] 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: <20251024-work-namespace-nstree-listns-v3-6-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrRPFHBncNbLVXQk3DwT5jV+/VTmsS/nxEPn3bC2 kGrisO2o5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCKObQz/qyNifzXYzPQwWmvx qenFj+1udgc3fW/fnW0545G3nrDVE0aG31N2OQVF7F99u+zJj78Lc4qP9slX2Kw79HOnoH/EgoJ qbgA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 2793A3126C7; Fri, 24 Oct 2025 10:53: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=1761303217; cv=none; b=njjRpqmLfwwU1aiMjKdzjOC9LFfehojtn2xCePJYWqz78KuXjqfYW1ad5583pHSvZ14WtFqnDQiD7YF5rM3uTKlpjStN7jCNX3GfXRoLTJ/Oad7K92EY1ZIuZi01d8Nh7Ts56rHUP7RIyjOmwczs8FWwah3nhoK21PtXgt8EQiY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303217; c=relaxed/simple; bh=7aAHCcaecm2VZuosAD5WF6qVRIAZipjG6VYIR7g9o5A=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=D0aB8V0HGADbmpG9NZiCbC1CQofxh4+mj62Jt+59+DD5nMl4XQls37GsqyDOlyeTWAjKNm0uIytMNnXgrsKRJ9PajrtNDkN5yTXvfczyK7TWpc8gKi6jSBvEmdP7F3tCCW2DzGLyXcjeYvHEYBWi4LcrVQHcEupCMIKsApKXf6g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gIj+Tkmo; 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="gIj+Tkmo" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 24BBDC4CEF1; Fri, 24 Oct 2025 10:53:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303216; bh=7aAHCcaecm2VZuosAD5WF6qVRIAZipjG6VYIR7g9o5A=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gIj+TkmoGJOiasOs8X1moJXVepkYY2XYsCjSLQivwBOx8EdmXXdVCS9c8kEB2vfKQ unVmGvBiQkqBVHL9srqDcCjuW8Z+WbHwOE986epDXcoKCV1Tt0ScAT16CitnU31LOc EJbYxgNokKHGRFo6aD7Tc2urcoNzBXxvgjT6C1hBB7rNvUhU2mEIBegjZjcQuF3n0g RLDC/shbxTJ9moRENz78H9H3A3saiLzqlz4Hp3/TkHW9S/DAB2dcBQXMQPaz3wu14v FS2QeNGGHeDQqKePMBRcdO+H6G6VDqstp5taiuTc9fxzcwHP/OTubjOooIppJQzv4z 5w1hegZ9gk9tg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:36 +0200 Subject: [PATCH v3 07/70] 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: <20251024-work-namespace-nstree-listns-v3-7-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmoxZO2o8/z8INOhRSduc/qa6/sua2m/+L3oSf6pm 8cEPbkDO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACby/ggjwwGLdQ7HijJf+rPd iN1et2231LqGCYcKg5JY1cV4n8zOfcLIcGNZv/EnqT79+yobF7GWz97ucWrFd5fn98MWmz1gUVv CzwgA 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 C6AC431619E; Fri, 24 Oct 2025 10:53: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=1761303221; cv=none; b=sQbYnNx/xw2qL/u4aPf6jDIfz1GSdnRuE773kzjguooPKAKpsxEHoMDub9vDAH8GtBN7B1b7xtqDUcED+Fj53YyOxnyTPT1B71WFDg1Ieam/8rxi0ToHKS9/Q+do1yZc4q2OYm7iIyT43jYto7jflgXWdzkiSOEVjvanOCcwTZE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303221; c=relaxed/simple; bh=GmTU8Q/fclIPwxUSGwafLrmOAHz2L+FN5rNlGUSGB9Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kxS5miuONH7Zjx4dGHZLGteBjGUjS/z6EqKy83FLMcju0tf+Bu0egkAV2OELAuNTNcw1j6PdZ1dlc2mUrAa0VH16PCTJZ0sjKN+ncRE8BkmIH/YQMtEMTuOZ2SEp+n1eHnhaQoNkp27BM1RINA/fxgc11Jn8RIg21TYC69xKT40= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=f93KrMgV; 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="f93KrMgV" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 26E9CC4CEF5; Fri, 24 Oct 2025 10:53:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303221; bh=GmTU8Q/fclIPwxUSGwafLrmOAHz2L+FN5rNlGUSGB9Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=f93KrMgVkyYNzRB7jRt7suQJihSpcCkM1QJZmx0Xomj5JfuaF0njy/mDsdUfTXOaa BLFZfZMr42gDFMDBttlVseWEGXadZXhuyGxaLV/9ZSiPFYq1rSWBlp9d8OrELzXKxO 13rgQ8nhJTqOrz/KZSiuBN/YeWMMRnS83/+tbHK51UAkmEZY3AmfImDrMtAMNvIDfS jCGVhFUyll3/UMi2nLlvfIK+8QeBn+9aTaetxe2YJIoGf5Kzy7HccsMVwpGm3NZl9+ 2qct/HMS2X9TL5G0+noAfzPPv3JXAVTqik5JFMAzZfs+i9wITzDNMhNnacLoXztqy0 fEnPogA5cctPw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:37 +0200 Subject: [PATCH v3 08/70] 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: <20251024-work-namespace-nstree-listns-v3-8-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpJb2W94LPpdt3xAuknvlP8t3yyX7tzJ+dJ8RDNc Am/WU9SO0pYGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACayto6R4YfnPxm3SVkVnt8N 5t958qZsi5Ny9cSUN8+Xyd0vlo1gVGX4wjlp3fuXxy5tf5rpFN4nsN3zu1beKoYVP+MXbi93nby LEwA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 3BC2D3128A1; Fri, 24 Oct 2025 10:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303229; cv=none; b=fJsJ2ctB5lEDZexrsc7mAsvbbpd1bfp54E+LoWTWGfM8+pME8Ixhw/gr6OckzZbhrsgrLVIJh9PS62CN2581kT5ZnflCkm+j1wdO6Qfeda1DqgK/KRlUyI6J/ni9w8BWHugUzA+QfAOPmvBVXG5I5VKJz6fL0mxQrZugWuMfki0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303229; c=relaxed/simple; bh=QM8oyzyJ0QczVJ0uxGx22MIzfw44XMMyED0mCYHZDF8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VGEyXW8P6U+im6AssNYXCtD7qH+9lqh7XFeG/SSmP9kaoAysQLroCSUEPvZ3rKhjy+gVjteRt567zDozy4JHHWj9wyQSmS8+j2O4lYi+ApYTfRs22jlbb2SbSipSkD0qa4hxJXzAqod93AoLYqdQjCy3z5JiHIuB3FdFkjHZbdI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IDOkSc8Z; 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="IDOkSc8Z" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1CCE2C4CEF1; Fri, 24 Oct 2025 10:53:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303226; bh=QM8oyzyJ0QczVJ0uxGx22MIzfw44XMMyED0mCYHZDF8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IDOkSc8Z209ZjnA3ZzOfATDSVohe/B5WDpBEcAQXBEWWBiJNB0GB8ek38w60ZLQWA C2zwPQFa6CjCrNFuv3On8PIkx5gp5QlhjH9NZwYyn9ON1lJtpFRRYG1kUQwwaYy2iS o7xwCmFGtDNGYwe5Kd8ZY9q9cDJYLRQL6C9hINiwwbNbv03SsLeVm1gBiBGk+/yCXh 1mrsydfapfGMIT9UWe/vC//bGMptRYN5IBcoAB5cQS4on9KRMG/PLV9yZIV8gsNV0K Cl0556lter5/J+DugI9VhzRqG5HVeC8Typ8byDRxZ/Rtr3+rlpYGupVQm0U5jCrCHR sRtJ4bVYR3tOw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:38 +0200 Subject: [PATCH v3 09/70] 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: <20251024-work-namespace-nstree-listns-v3-9-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrJn7rpE1NWkeD+wul/XhdzPdctOmZx3nZPZf7Oe ZNm7ttQ2FHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRzKWMDP/bdtlHfzBsVy+5 F6O9uFFywtrMyCPfbup/fulhWNgnacvI8NVmZcp2LZV28xsBuXnt7Rs/zH9WVPdNupvp5CKRq41 8zAA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 332423191A6; Fri, 24 Oct 2025 10:53: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=1761303232; cv=none; b=CnnCJUMaAQHJNhgqoAXu5RVo9MAF3D3tlfbdLFe3LWtuOln82Gogs+QN1cV2Lmekm4abBBcMMzFLd2Wwde/PhO7WubqS9HuM8/gR+UNhlEfxaUBnZ9QpAdhn4XZzR+bFDtfo4Rv8RUrvrPWfHlqtRPbyQZU5uyx/XVsDxOqoUW0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303232; c=relaxed/simple; bh=PRr5aGNWRTH+10xraw3D5wgKQID6oDCbNnUrUcndNYk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qwRKHMOaKaKfTSGC7pIJNCKHo1nFYgc2MGY16lw4r2LzUvgMcTqkltGJtPgvzOakT70S7WIdLDmnVv/yTKKdzxNAuQXQ29rDW8puSq6q1D7j5K1BSmBp+CHvczpbfA4JF/vuHQYE1VgvflYRustu2MFiP2vzgiyNPJPMKTyZXac= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pdVd5CE8; 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="pdVd5CE8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 36CEFC4CEFF; Fri, 24 Oct 2025 10:53:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303231; bh=PRr5aGNWRTH+10xraw3D5wgKQID6oDCbNnUrUcndNYk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pdVd5CE8uimYDoI+VrFVlXV6mfgy9Tvj1wSo+mAau2n2hfeMbeOZ6aLVDBQZOUFlQ 2MJFROvAkdySiorkvyK08MFOzeCU6RYomj4BWKdgWd1eGfJN6iSwyBAbi3ab/eW9zM Wa9nVGmOPTObVCVIAplf6K8AAUJePs8rOgGS8KE6TuqMV/5/9X+kN7Pyj21kYYAeQ8 Jclg4vj+kEV9uCCPG6JGhytVhBrFvbeBUzxSHgkZm8OP1qeTZC32oCkV6lHB2zm0Gb tpujhQzdYsISn3qQKQRYvUQuHe7dZeevf6QhsndthtAYKKBYGPH9u4GuDeVnsmHJY+ gqPGXbCDU5T5w== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:39 +0200 Subject: [PATCH v3 10/70] ns: rename to exit_nsproxy_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: <20251024-work-namespace-nstree-listns-v3-10-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2954; i=brauner@kernel.org; h=from:subject:message-id; bh=PRr5aGNWRTH+10xraw3D5wgKQID6oDCbNnUrUcndNYk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr5GHXYkftkrsfRY1JL9txuTzqb8iru/aJVs69HM G76yyzxvaOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiAfoM/7Qa7jmt0wq+taw1 +c+NF3tv/l97zM4z+cPpUyu+vI9OfOLC8L/m2rMZFbcKD3N08G6XDEl0eSjkOP/q3EK+4qM7lh2 w8GAAAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 The current naming is very misleading as this really isn't exiting all of the task's namespaces. It is only exiting the namespaces that hang of off nsproxy. Reflect that in the name. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- include/linux/nsproxy.h | 2 +- kernel/cgroup/cgroup.c | 6 +++--- kernel/exit.c | 2 +- kernel/fork.c | 2 +- kernel/nsproxy.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/include/linux/nsproxy.h b/include/linux/nsproxy.h index bd118a187dec..538ba8dba184 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h @@ -93,7 +93,7 @@ static inline struct cred *nsset_cred(struct nsset *set) */ =20 int copy_namespaces(u64 flags, struct task_struct *tsk); -void exit_task_namespaces(struct task_struct *tsk); +void exit_nsproxy_namespaces(struct task_struct *tsk); void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new); int exec_task_namespaces(void); void free_nsproxy(struct nsproxy *ns); diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index a82918da8bae..ce4d227a9ca2 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -1523,9 +1523,9 @@ static struct cgroup *current_cgns_cgroup_dfl(void) } else { /* * NOTE: This function may be called from bpf_cgroup_from_id() - * on a task which has already passed exit_task_namespaces() and - * nsproxy =3D=3D NULL. Fall back to cgrp_dfl_root which will make all - * cgroups visible for lookups. + * on a task which has already passed exit_nsproxy_namespaces() + * and nsproxy =3D=3D NULL. Fall back to cgrp_dfl_root which will + * make all cgroups visible for lookups. */ return &cgrp_dfl_root.cgrp; } diff --git a/kernel/exit.c b/kernel/exit.c index 9f74e8f1c431..825998103520 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -962,7 +962,7 @@ void __noreturn do_exit(long code) exit_fs(tsk); if (group_dead) disassociate_ctty(1); - exit_task_namespaces(tsk); + exit_nsproxy_namespaces(tsk); exit_task_work(tsk); exit_thread(tsk); =20 diff --git a/kernel/fork.c b/kernel/fork.c index 3da0f08615a9..0926bfe4b8df 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2453,7 +2453,7 @@ __latent_entropy struct task_struct *copy_process( if (p->io_context) exit_io_context(p); bad_fork_cleanup_namespaces: - exit_task_namespaces(p); + exit_nsproxy_namespaces(p); bad_fork_cleanup_mm: if (p->mm) { mm_clear_owner(p->mm, p); diff --git a/kernel/nsproxy.c b/kernel/nsproxy.c index 19aa64ab08c8..6ce76a0278ab 100644 --- a/kernel/nsproxy.c +++ b/kernel/nsproxy.c @@ -241,7 +241,7 @@ void switch_task_namespaces(struct task_struct *p, stru= ct nsproxy *new) put_nsproxy(ns); } =20 -void exit_task_namespaces(struct task_struct *p) +void exit_nsproxy_namespaces(struct task_struct *p) { switch_task_namespaces(p, NULL); } --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 55269319614; Fri, 24 Oct 2025 10:53:57 +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=1761303237; cv=none; b=QHMtwU44fI7vRXcFJCyPT1B4mo3bJZf0AEH4GTJHowD8pxGLcADnb2oj/qQNdpyxvgelhYmPQ0LBZSrDVxKHfhfLvivsMwaFI74fXjNWsy+8CkdTzAgnp1Awr9Cq1KkXASIduj6vaZdJSnEPUvV1cFdEwKS/yWQwqBvefSIvBYU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303237; c=relaxed/simple; bh=LB6UPDVoEEEprxOMk9yjO6wkEFULlDbRdRPVgZljH4o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fytttB5xeSeq3GNDL9CAkZxqRFMTCVMaEH2Qelv+zDqZ5cwkwsquaWooSbwAGHVT+gMcQYm1FIySIlvPG77BmF8RpTYXnvYktqVcfzi99PA3zF+p6RW2ekP0i0I1qHj8G2c2GxlQ7oMtZyK1jFrA+y0yl+U/zvura9o+0kaQhtU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ReMgCL7r; 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="ReMgCL7r" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32DF0C4CEF1; Fri, 24 Oct 2025 10:53:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303237; bh=LB6UPDVoEEEprxOMk9yjO6wkEFULlDbRdRPVgZljH4o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ReMgCL7rLh8kObcsXeNMluHCDPkjRInUnmE31kpDi7ty+8JgvzQANp9SqRyBfz7yB 2A3Z5bxnnskN8VJz5sjB+HPDQvZ4nnL12vm/WuQV/QwWh1TGTkky3AsENoxtSYXtAp u9YLAv0E2PnK8ryqds5fe8u7oxRXoKTvjLo5HGWmj50MxeFf9xouNA1/gJQOsULVXi /iTF/EkZb0nXV+c1DM4LIbgwAZ1mIFKHK2p486cqCcjhfjCfdJMkm2uMNXRWSnwIQY rJ3F5HVZxUSxtN2Ytim9VxM/tHXRaSOb//7NwUnlEhMWWPOykpq/Gy6TsR+7yP6tM0 JrXsMKM78Kzrg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:40 +0200 Subject: [PATCH v3 11/70] 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: <20251024-work-namespace-nstree-listns-v3-11-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=35883; i=brauner@kernel.org; h=from:subject:message-id; bh=LB6UPDVoEEEprxOMk9yjO6wkEFULlDbRdRPVgZljH4o=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqR2NP4YyfP/dcWki3+mwP2mxYy/ldjSzy+UyrHk 9tWvrqno5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCJWJowM097kFVYcWhstPqHO uGlP2M4I7edZ01jyzf3eXju2qmBWOiPDql3z7SPdnX9MMun1nB3bxdFa9Vo1qmnGWfcz1dz900K ZAQ== 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 Reviewed-by: Jeff Layton --- fs/namespace.c | 2 + fs/nsfs.c | 48 +++++++++- include/linux/ns_common.h | 142 ++++++++++++++++++++++++++++- include/linux/nsfs.h | 3 + include/linux/nsproxy.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 | 6 ++ kernel/exit.c | 1 + kernel/fork.c | 1 + kernel/nscommon.c | 221 ++++++++++++++++++++++++++++++++++++++++++= +++- kernel/nsproxy.c | 23 +++++ kernel/pid.c | 6 ++ 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 + 22 files changed, 464 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..8b9bebd11c49 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,17 @@ 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 allow it's resurrection. + * We could try to take an active reference here and + * then drop it again. But really, why bother. + */ + if (!ns_get_unless_inactive(ns)) return NULL; } =20 @@ -614,3 +636,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/include/linux/nsproxy.h b/include/linux/nsproxy.h index 538ba8dba184..ac825eddec59 100644 --- a/include/linux/nsproxy.h +++ b/include/linux/nsproxy.h @@ -93,7 +93,10 @@ static inline struct cred *nsset_cred(struct nsset *set) */ =20 int copy_namespaces(u64 flags, struct task_struct *tsk); +void switch_cred_namespaces(const struct cred *old, const struct cred *new= ); void exit_nsproxy_namespaces(struct task_struct *tsk); +void get_cred_namespaces(struct task_struct *tsk); +void exit_cred_namespaces(struct task_struct *tsk); void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new); int exec_task_namespaces(void); void free_nsproxy(struct nsproxy *ns); 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 ce4d227a9ca2..45e470011c77 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..a6e7f580df14 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -306,6 +306,7 @@ 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); + get_cred_namespaces(p); return 0; } =20 @@ -343,6 +344,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); + get_cred_namespaces(p); + return 0; =20 error_put: @@ -435,10 +438,13 @@ 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); + 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) dec_rlimit_ucounts(old->ucounts, UCOUNT_RLIMIT_NPROC, 1); + if (new->user_ns !=3D old->user_ns) + switch_cred_namespaces(old, new); =20 /* send notifications */ if (!uid_eq(new->uid, old->uid) || diff --git a/kernel/exit.c b/kernel/exit.c index 825998103520..988e16efd66b 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); + exit_cred_namespaces(p); add_device_randomness(&p->se.sum_exec_runtime, sizeof(p->se.sum_exec_runtime)); free_pids(post.pids); diff --git a/kernel/fork.c b/kernel/fork.c index 0926bfe4b8df..f1857672426e 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2487,6 +2487,7 @@ __latent_entropy struct task_struct *copy_process( delayacct_tsk_free(p); bad_fork_cleanup_count: dec_rlimit_ucounts(task_ucounts(p), UCOUNT_RLIMIT_NPROC, 1); + exit_cred_namespaces(p); exit_creds(p); bad_fork_free: WRITE_ONCE(p->__state, TASK_DEAD); 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 6ce76a0278ab..94c2cfe0afa1 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; @@ -246,6 +253,22 @@ void exit_nsproxy_namespaces(struct task_struct *p) switch_task_namespaces(p, NULL); } =20 +void switch_cred_namespaces(const struct cred *old, const struct cred *new) +{ + ns_ref_active_get(new->user_ns); + ns_ref_active_put(old->user_ns); +} + +void get_cred_namespaces(struct task_struct *tsk) +{ + ns_ref_active_get(tsk->real_cred->user_ns); +} + +void exit_cred_namespaces(struct task_struct *tsk) +{ + ns_ref_active_put(tsk->real_cred->user_ns); +} + int exec_task_namespaces(void) { struct task_struct *tsk =3D current; diff --git a/kernel/pid.c b/kernel/pid.c index cb7574ca00f7..ec9051d387ee 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; @@ -284,6 +289,7 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *= set_tid, } spin_unlock(&pidmap_lock); idr_preload_end(); + ns_ref_active_get(ns); =20 return pid; =20 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 Sun Feb 8 07:58:47 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 7179B31327F; Fri, 24 Oct 2025 10:54:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303242; cv=none; b=PXPySRwAkuxyu0NCtHMaUi9hwcLiRr5VskOjQPBAKr7AKOkDd+DmqWeFTp1Mb8CX46GZsKovOxYaRZtkdxIknD1Yvv+BO7et5sOLaBaYTtzNiQUkXMhKazQNYDGMyWK5e/yLQ0KlP8T6sTpqvoYjZK2k/Rt0SAnkvR+CDEBWjy8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303242; c=relaxed/simple; bh=BQTckd1lwN42TzFjtcvMTDlqbwW0nSU43xXjRiLpTAc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OOlW9/dytsyJ/CMB3MiNjv62Kz23P7OxIQlmaqZfrNxHOd4DI9EvxssCJKPiMn4oJnFXoe7bwvwNttwzXOd8WTTkY993Tfgj/wS2jP6hMO3ICr55G4/fTiCMQkIRkHfOaAfurSm2KmpH7Y0wNC6rESJx+1t3UVuPwDx/WeZR88M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Edc5+huj; 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="Edc5+huj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C144C116B1; Fri, 24 Oct 2025 10:53:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303242; bh=BQTckd1lwN42TzFjtcvMTDlqbwW0nSU43xXjRiLpTAc=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Edc5+hujHVCoky31ynt1k3LfhpLH1kcuxKpz0PQthsT0xHYZb4bd/bu3ybScqhqvu g0R4xucGLLIyajM3wqLnhEsVTYabcaGSxkK+NFQ1HHRY4YZXkd5VFNW1Bmg3idIH5D voVIJje/uL/IhCFR/+uTF0L0TF7/ZhQ3lUSVXVvEAOTLfBlYax7IWd3aj59CTEksrA Z7WbEB3qjPN84zerXpYivqJ0iiKgsuu0i9Wkc1Sf8hP0dnJhcRNLOznHoumvY0rHan UU6SeiJBTCtZb3xS5SgBMWKU6dN1SO+7V6xz8ezMv+ZnxXBqCSEPYHo69F6IxaF2+w cMhCeCkBlrogw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:41 +0200 Subject: [PATCH v3 12/70] 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: <20251024-work-namespace-nstree-listns-v3-12-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmoRE+Xk2Pszc2bcs6N7bzeurfjAMkWvyPvwdTt9p q0hbd/NOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACZispzhr+Dt42Xz63cs3hgx NUv5n3vzjmbLF9LtCgZ9ax3ZJCLyPzD897ivvn6dxfbwNSvuzFy6xK2qw/xdxZnFXJdTHrv/s31 4hwsA 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 6DC5C313287; Fri, 24 Oct 2025 10:54: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=1761303247; cv=none; b=ueI6Uo/oDHpEJthYBUKsv9mR2wZRm60n7XNgNwxPDM7RNxHYOFV7uDeizGUqI08TOLATSHCnwHdG0NlqOliidjeTCxi1t1/XvJ7pnW408RdfXR761yWgcaaFlOW7dX3eHG6t7Cg4HCSzrgrPiZSsAtkVH2N0pujWbcVFekKGaVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303247; c=relaxed/simple; bh=I9Gr6zapSqyfvp5VjlbXhfKK8aPWlTON9tgSCFZUh0w=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=uJrRw+JdKj9GvSxcxMo2jGzFJ+5xKk3DSSsFhPsSQi6n5N5B++hfA8804XvKv0aot5FRku2X5EaP+ybK7G86KgFxP/4Z9yqi1UeQFWTZIjOO2nlGM0t8DNRFLaxDkK+101nhyOE7k9qJZKgVyWiE8sBw5+l7xbElXp3Aq5QpqhI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DhPIpmO2; 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="DhPIpmO2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C501DC4CEFF; Fri, 24 Oct 2025 10:54:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303247; bh=I9Gr6zapSqyfvp5VjlbXhfKK8aPWlTON9tgSCFZUh0w=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=DhPIpmO2v9pkzDZ9lSp9pTjzXFrYTMiLUmwnR3dAsHS7ND6sLWL6KiaYBPQDPoyR/ hjVCEtWYXuUYZITY3hPRl0lI8zhgHUPRn1iFGgpFiAgVwNCq6HhyMZ0IA4H9JHwI5r HT253FTtnTEUesvYNz90cijTHQASXi2EBPd75DnsHDTFOhktu48jVb9iDZm4VZW72k hwzgpzIvELflKeoil/SpKCwubi2Y5wL3Mx28zoKg/ccJfm+xc/4wRO7Z/RtEVHulzJ oMH8SLWSwFsq7GDuTURKpHdkx+f/uU9n77yLgO8c2YEHPgUFTzj8RriUN6gpANs1bp L59NMFWOau3jA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:42 +0200 Subject: [PATCH v3 13/70] 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: <20251024-work-namespace-nstree-listns-v3-13-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmo5c5w7fNfHN5MvvSrK/K9Q/fN4YN3MxRu6o8QNb NjChYq+dJSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEwkYQfD/4zNckcqZi5rbpie un1Wz9pSMe0M66rlCyMNfSZ9/niNq4OR4SLP1qrnBy9tOnS/bPKBJJunhmcDPWfLNrw/W9CZt2b ScW4A 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 D102F313287; Fri, 24 Oct 2025 10:54: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=1761303253; cv=none; b=CJjSXK6XNXFa8WVUnvPiGv3jdUCJboLlLnzKk2BryTfX68T5afBivSyQsIJ/55WCdBzEgnHFwfWYzQUivZOeVFhXZw3EfZ8PUPizkznL/eW5jzb9sa4qh/pJBrc9c9zigna6jYCca9PRHdzklvjHn1jVx+yz6hc3ZxPjR7QYmds= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303253; c=relaxed/simple; bh=XlNTVHPsWhpdc2SiiHtveAAcuq9JAFNLIFuraBp1Wjs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=SfuS++DAcT7e30H++v+h7Olgsvq9HRzD7k541mzMY0SrjgdcrdIzVlOFsasuLhIvRSsterNPgwm98JVa0SFDIT7e5j8Xs0Ah854E8Crzxh3fiedLaj3fyEWf3tpyL/2T1jbQOM45MptQY6yQMRzdAUghbH9ZzzTjU7qWRC80NuI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bi8ShVAS; 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="bi8ShVAS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C29F7C4CEF1; Fri, 24 Oct 2025 10:54:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303252; bh=XlNTVHPsWhpdc2SiiHtveAAcuq9JAFNLIFuraBp1Wjs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bi8ShVASZDe7TFMCaU15nPVFSxk7q3Z1YEguj/UUVxtY/FDkqd3rGSPldICKJJERm x+YQ4gehppau2apFmcRP8MqJ0qlsgTDNYQx7kO71bL8A1ugSolFW+yO3c8gUjC5pFs /lbyCFdbG45iDL1J9b3/2vbLKFd7r8a6AdDsATvD39kZulKrsQHjd0negZp4IeURT+ zEcFbbKlHQ+KYzQ/2u61yp7sCX7cu2M7Y8MnJQ/xx5m2qL5A1mOvn3eyAMyCvZuKOF CHiN+q8Ak/k1khg24RzqZbczAlrUwZt7czhoIDTpgwhuBGJoLz6kL4gh1zUu4MiwfL Eks8huUxV7oiA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:43 +0200 Subject: [PATCH v3 14/70] 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: <20251024-work-namespace-nstree-listns-v3-14-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=XlNTVHPsWhpdc2SiiHtveAAcuq9JAFNLIFuraBp1Wjs=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrRNko7ktX7LuTwp5NMaQePubOsmbpwoYeamJn6R HGpMpXAjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIk8lGX4zfKv8EE6Z5uNZNJR Xo+q+PLNM0LM1huVH72iW/Gb/4fzcUaGOWd/8YXZLvFP2FH39PThdraoyZw2ejFc3no8zFv2/Pj CAQA= 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 Reviewed-by: Jeff Layton --- fs/nsfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nsfs.c b/fs/nsfs.c index 8b9bebd11c49..19dc28742a42 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 Sun Feb 8 07:58:47 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 B65A1313525; Fri, 24 Oct 2025 10:54: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=1761303257; cv=none; b=bi7L7DNr/zOb353i2+OEJtYfayM7AChqx++/G7qz41pOEYvXgLmkVfO+miAFkTfWg1X+3J8woNek+6VRHLiqzyCs5LncIZWJEjuCqMBqkpm6FKdmqvbnLaYAmd0M9mWPZw1h3Cjgh3gLHdcHNu+V07Pkia8GOTbpd/9EU3j/s30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303257; c=relaxed/simple; bh=0Z06FS7PHlmbbOXNaiYAotrcXY1wE2OxBYSA5XT3a6Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=us7o+BXCy2LfDQ6r8dMjIbJdRRuKIZw0DCRDytdfCYaU9dqazeP2Y8rc+8p6lbdg6R+eXIC5VZ4fX79dQgx1bpGMIGoyVvU8ujrRUrmsjfhiGAdnmgMu1UQsnOtRgJRnckrjrtOAyBft1EbcZCVV3e44c0ri5l2t+G0YC0ouhf8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r7Q0wKcF; 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="r7Q0wKcF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C3EA7C4CEF5; Fri, 24 Oct 2025 10:54:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303257; bh=0Z06FS7PHlmbbOXNaiYAotrcXY1wE2OxBYSA5XT3a6Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=r7Q0wKcFANKsg8lPWpO4RvoNtJp9nUHz8/UTT1Wkod79L3vRvfV10fdOYN0gLAxB6 qhXjLSUmvrxnv8XgzLVFu3MzAV5ng1rG6hoCRDaAnJZ4s/sxpT2Txczxbgs+Ec5vsU cAk96CyMyabP6Qo6dtLrZgO/pqBrxbeUfHMLCwDNZdS2HanGYbYWxGiUPqomduwZMa +8ihpAssqcMA7qsmI8blNwCIRio7kcOd+WOx9QBkGwjPFZ9BJvoi1v4eN+xvVgpneo vkhTNuvS1reQzQpApog5qz9zEikX4MLKao0bRoYMmYi0laW7OTh8wWuiWitPBaDklx OpkjfhyDN4s9A== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:44 +0200 Subject: [PATCH v3 15/70] 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: <20251024-work-namespace-nstree-listns-v3-15-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmo57hAX8mvP5k3reXcFqO287OM3awFPk9GBo49uK IXt9BL42VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRVU2MDD2ZjN3bQs9qLzhb +lGj1dn6Wvf29OvVu+O4t2meYhH3WMDwT022pm7ZF/WoYumCbXxrGAR+Bai+F2tImtUlc/W1z/7 z3AA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 7AF79313525; Fri, 24 Oct 2025 10:54: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=1761303262; cv=none; b=EY9eWIusm9zEEkCoGf7D9Crdn6/tDgiDOc0hwdHuzFeUzyZJArOe2m5vnPp0GaYFxWflDCPrkR8kV/CehthpvZzs/y5wumW0Nzpjm+fIr8M37GevBMs/xlq0wAMbB9tQ47QI8P6pjXejJgjfeDRT62AWiEa2ke8vj/vLHDYHFMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303262; c=relaxed/simple; bh=Co5S70aHxdL+O+qEH6Oe29bl2YvObKQAs7B24LZSp/E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=aF6TzlMgAPAMABWZVpABMztn2Qk6wfTZI0jr7txoQPINGONj9jDWnfmLB4dkP8nmpJBy+BZSuXVDSkhrcPSGYJdp3J0zhBkcLk/B+6XkXVS0h+eNj4VtRjNBAFLilbubiK5LyxNbbQ5UR1QJqqzqCXtfGj943IKkvINca+Qi0r4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CF7ChK+5; 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="CF7ChK+5" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C4508C4CEF1; Fri, 24 Oct 2025 10:54:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303262; bh=Co5S70aHxdL+O+qEH6Oe29bl2YvObKQAs7B24LZSp/E=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CF7ChK+5EeZw2xl26uy3v25pfjPfJLl/tYGdcU9mb1zGPBpfqD3lz5G0pN1uKjQaZ Occg3rPU3aaljeO2k9u61Nz9ox0tmTWwgFsi0KYElP7UDt20DOuC4VjWDQ34wPcb6f 5RwQ11IsR/narT3Iwu96ar5BZgRhDCd0sAU0yqdNgL/I1dSIPfVoal9ThNd1O1tAg1 LBbesYe5wtSz37WPgQVoR7EbwA5XQx/indPsmQfu1F9pasNhEyTBI4N3EPocZcsU8R TXbOTx5dZ1Dx5OC9fMPQrqAUnjXY/GTAcpk46azXhBcYOG2MDkdInKwsOfcGtHAMmo P2Amc8VDrY8tw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:45 +0200 Subject: [PATCH v3 16/70] 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: <20251024-work-namespace-nstree-listns-v3-16-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=Co5S70aHxdL+O+qEH6Oe29bl2YvObKQAs7B24LZSp/E=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmply5yl5eh+sfvOSa+Zgu2t8atNbv0Xs9K+5JHkU nWos86yo5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCKnyxh+s3c+yF2YlnCj803b crmdKV1GzP4dezQUld3nTjq571t6JCPDMlUJt1OxM3fkpMwWyztSH/x3o2PQdcmHPg9/JCqY/lf lBQA= 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 Reviewed-by: Jeff Layton --- 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 45e470011c77..9fa082e2eb1a 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 ec9051d387ee..8134c40b2584 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 Sun Feb 8 07:58:47 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 D303531353B; Fri, 24 Oct 2025 10:54:27 +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=1761303268; cv=none; b=ie3qXeVSZd9WP6OsII5iLGe2uTeV0nxWhOStezWK56P4p3eP+9k+th9fqkIEGeoyrrtaJpKIS2sBl4JftNhUpdkHLJV5q7kuSxIA8d1gx+pFQh/gsp+My9T45Pf8C8YfPHsLU4C4YzArQA4MFScx7l0YJ5g2TCqcSS4VTsQS7NE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303268; c=relaxed/simple; bh=TTErASs+2e4SYLwWGXf0I9OmpgOOFOWHZXi7WdpPuow=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZBxkdR8XVwPwHex4lV+Oy51P2CsF7HVa9wiMXslUvSLa8ZgSnoPjd7dDINd2IcExt8qI+V88q/G74ZLFLKD2TMCD87obWKWC1exYg+tGmxAOYUY7hS8GRhqrTG+kZL43f6PKJN8F6KTdts1SX4q5Yec9/xtFFZPNxoKwTkY6Dxc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=naeROZ1T; 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="naeROZ1T" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D01E2C4CEF1; Fri, 24 Oct 2025 10:54:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303267; bh=TTErASs+2e4SYLwWGXf0I9OmpgOOFOWHZXi7WdpPuow=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=naeROZ1TTyDNODK7mVmoI2svK+g066vcK1I3SyprwvzsYdBb6kzYAeDkKwchoQQP7 JCUkOfIpR6yUUUnJCSIuO6J3xQm1+SIGi+ll2fHk4nqPTa7/4AajvYRNFzvSqc8eFm O4MtWup+W0+iCL+xm/KzWCsVPOtMhjsJnB2mfqfCB2oRhQYO0/6TuBfvI8aJ7fY/He 5ls/s3raTz3ebuk4TNbhvBoDl/X4/qNjkzbz5+474CYhgPVkeEqjY6RticoyqQTcIg Ip5FqZEr+16EVWMTjRIeCIn0EDJbpm3uphzo8qAf/yXuIK2fFLIixHL98iBUFJ4fxs aOiDwdeaNxOOQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:46 +0200 Subject: [PATCH v3 17/70] 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: <20251024-work-namespace-nstree-listns-v3-17-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=31082; i=brauner@kernel.org; h=from:subject:message-id; bh=TTErASs+2e4SYLwWGXf0I9OmpgOOFOWHZXi7WdpPuow=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqNWSd/81PhmsKYbw8XiHNuzNQQjnB7n7dj97EHm s26Dz0nd5SyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEwkxI7hf85Vx6Pztzvdeseo +JO/ZO/T2TMs1Dev/LTigdlN3qSt1+MZ/te3/FilwMqzQXGjTGH71oOqP+Ywng3MCoqPfpR6d1f iNlYA 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 Reviewed-by: Jeff Layton --- 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 | 417 +++++++++++++++++++++++++++++++++++++= +++- kernel/pid.c | 1 + kernel/time/namespace.c | 1 + kernel/user.c | 1 + 14 files changed, 516 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 19dc28742a42..5c21fdc79796 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 9fa082e2eb1a..a0eee0785080 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..5fd50d73f0ae 100644 --- a/kernel/nstree.c +++ b/kernel/nstree.c @@ -2,11 +2,15 @@ =20 #include #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 +87,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 +122,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 +159,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 +175,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 +197,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 +372,352 @@ 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_get_unless_inactive(ns)) + continue; + if (userns_capable || is_current_namespace(ns) || + ((ns->ns_type =3D=3D CLONE_NEWUSER) && ns_capable_noaudit(to_user_ns= (ns), CAP_SYS_ADMIN))) { + *ns_ids =3D ns->ns_id; + ns_ids++; + nr_ns_ids--; + ret++; + } + if (need_resched()) + cond_resched_rcu(); + /* doesn't sleep */ + ns->ops->put(ns); + } + + 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; + u32 ns_type; + ssize_t ret; + + if (hweight32(kls->ns_type) =3D=3D 1) + ns_type =3D kls->ns_type; + else + ns_type =3D 0; + + if (ns_type) { + ns_tree =3D ns_tree_from_type(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, ns_type); + 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_get_unless_inactive(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=3D CLONE_NEWUSER) && ns_capable_noaudit(to_user_ns= (ns), CAP_SYS_ADMIN))) { + *ns_ids++ =3D ns->ns_id; + nr_ns_ids--; + ret++; + } + if (need_resched()) + cond_resched_rcu(); + /* doesn't sleep */ + ns->ops->put(ns); + } + + 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 8134c40b2584..22a0440a62fa 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 Sun Feb 8 07:58:47 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 EF87A31354F; Fri, 24 Oct 2025 10:54: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=1761303273; cv=none; b=UJV5KzlshoEC2pAROTHZ2UDSxsDHwZICRZsYq1wKY96oXzJqO9Q8reFBc4tD4VPP3PlAm1kfOyK+8sztUt5a2Lv2GsLrcMnHHGPFPECQIfDi7+wUtMAX5GY1s8RU7lRHvAdakwo9FalgeSbq8k9eK8R6m9/Pu+Nlfy8KK28evPM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303273; c=relaxed/simple; bh=tRwqy5SwFVniPr5V+qBsta76Evy4Uws4vCbVqOZukQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kv4IVqvol1MaIuKj6tn3+47XuFoqzH486f2uFIfqk/PLpOH7N7OrGqn+zYrOSxbVWsnYYKlwN6nkPSHZ+fy0NJXnT4qYGiIRzDVdMEhHsGgiKs/r2zAGVsB7mysC1YJiaP86HkvZPgsMgiaBNydYFIF4AIHeHTLnbkqJ1NX8enk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=AdzFdWkq; 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="AdzFdWkq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id DE190C4CEFF; Fri, 24 Oct 2025 10:54:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303272; bh=tRwqy5SwFVniPr5V+qBsta76Evy4Uws4vCbVqOZukQo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=AdzFdWkq4KA20SWQb2Hf8Gz4qIVvV/RPNAL0gZ/OjAWF8yEdSBi5MYYPFJTI9C/EI axfb8obGUZvcO9RLjYw53hnjrMxiQ7a2xIYi90KvAqNYbLtbktQzjZPmprPd6mWfsK D2v40PzMUZufSvitLIaJ998lFwLN+1KcOVK8PgpVgYBl1uzgLxBEc9Ddhb9Kz1gI0R K3LonFIXtk1MJ3XgbEIZhlu5kQ3oUCSlh8youjeVMnHwaUpBgwpR6wQgU882nFdqwY qWbNldMucOtqyT4mIwbAhZlKr/5/gPlhnvNghp5+NYglbzhyvmj5EmeGGzxTpsrUWu OYHfyI6A2evPw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:47 +0200 Subject: [PATCH v3 18/70] 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: <20251024-work-namespace-nstree-listns-v3-18-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr9Mb/SYdpUjpplCypPWcyNaooJdvvimHOna/G1f Nf+x343O0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACbCb8zwP3y66DTWiSoTizy3 +P1oaV4TrOrpu7k0edoEC6fliXxewQx/ZYP2hTenblWZ48TFZ/Nx+8YDnAovlqY0zJH7U+q/ro+ BGQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add the listns() system call to all architectures. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 9C568322774; Fri, 24 Oct 2025 10:54: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=1761303277; cv=none; b=L+UhP/smkD+hU6W9KecEXslnkBB8siTOq38hKXSC38Ggwxiu74G0YPodTUsMKwd5BFp57WQPltG5IuA8bcgIhw9J+rZ9KdfBYlMCpouUbdDdHygOQhA2YsUlKYea9oDGMt+OyvoBYtKb2ozZWvgPSXDmYUq1R5t05Xp4fWfWY4M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303277; c=relaxed/simple; bh=1Vbdfejrzu8I2m1UigJuDF0ynX7SsD3EwMJY3zP1DiU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nJF1M7mTL3uPJK7CTijbIbfL82hM8r6FEnSNPzXa2u9gZUUACHFlX8miIJzCvvTXqKKFY8cjgeeVvfkQ1WxsdGNsZ5oHVLElLz4eQx2bdoRF+Zg2zlogAgIq0QyApfw/KQ7tE4U3en5GgzI78bnh07Pxk7Ff49LfZQ05IaSdxWI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=hrgSkc5q; 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="hrgSkc5q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E419CC4CEF5; Fri, 24 Oct 2025 10:54:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303277; bh=1Vbdfejrzu8I2m1UigJuDF0ynX7SsD3EwMJY3zP1DiU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=hrgSkc5qn1RmTQYzfThGTsn1OXkfDxC07Vk49pFJU6Tu4WT1O7Wu+aYWVJkjOOgcM 6muVsPQjUP6deZiEp371DA5+wJfahTih6FoPlRZbN2+ZnB35JotNEceSrtGH2kqKOZ NREviSmYS7aNqjsxmESiW1YbVq39xnaTCe/6+2nIqLr5B9BstpCTtpuMePtlriXdR3 beHukWc3Lw31lHFHikwSUFvaSrfDulSc7wtG4QhrisJIO4mLRC5thWql6L3D70as6F 4/ZOUOXfUENqt5wMxptwOVFq69GqpVoEDoXd5a/rtli4mxYStxJYWS9dU/V7r6v4QR yGIur+Ho+HO3w== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:48 +0200 Subject: [PATCH v3 19/70] 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: <20251024-work-namespace-nstree-listns-v3-19-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmo9flVWZ8ka013vntVai7x1jSwOKS28zrvs2NELa UExu7hiO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACay4iLDf7ej8tsFLZM/awte SXqtuLm9zDllQ8nrq59uxxx+c22p5yxGhomP/sir75umt4tJx19LuuY/r1zhd5fJxxRnigu3clg tZQYA 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 27B5531353B; Fri, 24 Oct 2025 10:54: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=1761303283; cv=none; b=D6hsms8fC9N2Dj8OcErzcJxql8vIJagJdWUnmEqL/KrigDb6HqhKQQ2XAuysvJsxNphA05sareqXI/wYVX/IVCwYo1fji5uneqxm+jaY9kF7GQGWn08C5e+Y4coDj5UJ973UTYBrY4Mndfxk69ZYniXSS2vmWmYcrPoGI8M3Oes= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303283; c=relaxed/simple; bh=5c8S8VpHc/7sZMeT1/SbhEW34RvFd3Tre08SPwP5pEQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=IgA6MFAbNhLTgcP3Djje6X9UtGaJJiAl8BQu04eM1NTsoitlqaGdKMigBZSxTNtZ5gcEMf9ZkmlxZtyrQAGpxmVURB+1mdVIOUo9lccpnju9bgKkM86yEFkb65C9Q4TTT8IJkwZRcbZMv9r8j9D8NFofgK8vmL/Ie668EfOYPL8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=i1sk//S7; 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="i1sk//S7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id F033BC4CEF1; Fri, 24 Oct 2025 10:54:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303282; bh=5c8S8VpHc/7sZMeT1/SbhEW34RvFd3Tre08SPwP5pEQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=i1sk//S70I/6Nu/q8PmUjcvgzu1LbLrmSzHtJPaC2pxZY8A6bkDtoaAL9Zhvr5LaY d4l4PoV1rGfX2R3xxjYjmpjTkipxQsjz4GsD+IsKM5ZbnwFv1Ra3361tIeyX4BJcHw xOJbIJI8AQZqNUQHhM38Cus/KgeRDA188wPCj/ib4WYw6eoh2XO9XFxZqGbUPiSxqv vTec67waeTGYa3kuoqhghU5QTNL+w7bA3TXbNRxKeNxQHww6swR0XZXmIGtH0fTYNw wECGKnYKO8clViUXMGmMLS0uv0JJ8KkJPJW+EQfOklc3hFTJy+8RNlXceyEjgZpVJT 1WR4JxpWhV4Aw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:49 +0200 Subject: [PATCH v3 20/70] 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: <20251024-work-namespace-nstree-listns-v3-20-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr1XcH4OqRO2eb0Vaf6H9LRFYrn0h4yL9ZzL9n/W aa7hnddRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwETO72L4p5dnZ7/0H5fgFLEs zv7lbBKdzUrKpS5yfI65J7vt7KesY2T4vru89s0R677GeFVGmfmWJyW/Fq7lZHVOlBAO73Px1eM GAA== 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 157BE325484; Fri, 24 Oct 2025 10:54: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=1761303289; cv=none; b=g1N637+BrqpMffpoLx8tOx+qgeR50K2/qIat34qeDkJA+3ZOEkAdceNIoN4VaHJW64Uq4yY0nK8ayD6m5wnucqFdtj8mMoIv9Pi1JE7kj7isr0whvbK+S7M7G+bfPBCkrMwDUzFPdg5NB5ddBvgxzFFpRjUmp+PoFrLlET2bHWA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303289; c=relaxed/simple; bh=zTxekEdjlVJZprVoI/00FXYGRRSOiQasmJAHzIPasqQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OJU+t67hyPed3DHU9O1ONLTj31JQbFa4dozoat6rzTr9nyxypumFvnJKU+mXR4YO1zlMp/IXZfZV8a2kb1rTthNKQ6n192TaNSLbIWzuVEpLUU1jLDizDVnZmmR66ji4g/j+F+ApaQMSHZKxuuh5HjW6bOvCAygeUa9bNfJR9Rs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NL8T81k6; 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="NL8T81k6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 251ABC4CEF5; Fri, 24 Oct 2025 10:54:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303287; bh=zTxekEdjlVJZprVoI/00FXYGRRSOiQasmJAHzIPasqQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NL8T81k6ruIE0BffChAF5qn47PPeGcsAzLCXOGXfje3uLxdINc8YNrGm4QVgB5k0v DwUAlwUkgLCjTHpi1a6trZmL2FJQ0LQ8/uTe7DHGy0Ed6mKBTYt0PjhVou+4YQmSSZ RMDuU7O3ucX330C/RkiJWEQX03nVx/ToUE172ePLMqhMhSxX0OglMVdqMPDmAJrV2z a6draJ2gOIDgjQrSIXgQxlUBe8F8YuTHx0nfZDFCoo3Gestpn/OH6iOXbEKcmNa1vN lu5TtAF5bSb0x/jT3LXum3Um5tvVF3HssJ6gT/P25edbqQjCNZy5dajVmn3UfmjqVi xzHZNFiVFpalw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:50 +0200 Subject: [PATCH v3 21/70] 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: <20251024-work-namespace-nstree-listns-v3-21-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmq98vhNYEHJNq6VPRmhMbNM4696rZ7izHhcq+RE2 FSpP65JHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPR3MPwv2LSryeh3QK/Vtz5 9nPCty8Sy6fFe/Re2/j3m9zNhguNeSaMDEtXfd75w6VQQ0DH4lRcQf5Vxx1zd8/YPV9n1uLAk2+ FNvEBAA== 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 230E7313E37; Fri, 24 Oct 2025 10:54: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=1761303294; cv=none; b=c+Oo2w4YlY75mY9amOjRyDFvKv7Y9TMSgOcrAwhOKh+XKIzEjPwjLuNtkYho6/jgGXA14X1TVKZn61JxHeknfFgpEkOKbHfHWL796jIM491rdhckyFKtdCkpIAH9SU0fcw+fBPgJtWdt9r6XvLt+0fD2rR1LTL9SQqLcy01E4l8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303294; c=relaxed/simple; bh=VPZa5Pr6JMy6E6vudTcQn3gJk3UQIlVxfxrLDEyUgG4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mwLUmF39ONI+t+ZqvkgrDPiu5Jn3dQVfvTUYQgWOkPGNf1W2ZqqgLF4tYKTmcchSjQQroWMj5oSQKzedeGsVAR0n1pakbEt9PWVzsaoZE0e32rK5fr6CdlaKq69v1SiWjkH4TlP8kZ+234a2fujAFiQebpadkMS8MA/AAG6tZSQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LgFDUWg+; 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="LgFDUWg+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1FAC8C4CEF1; Fri, 24 Oct 2025 10:54:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303292; bh=VPZa5Pr6JMy6E6vudTcQn3gJk3UQIlVxfxrLDEyUgG4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=LgFDUWg+W4XI1v3/3NCYmbLipq4BUGd3rFG/ZgLtGrDp4gBSy5EcY3RdIxIIzKLY/ 7Au+2Bx3aP57Mt2bbXoxfA7Rbkje4+HXE+Vqjm8cNTHGGlS9i76V2xyVUy+/oyJxkA FsDJ6TR13JL4YT5lj78v9lRO3/N/LeB8O3+vbHvJrr83O3XxGqlzm1YxXgfAzLhBmv Zq16R46T+a9j96Tb3RyvZdGl1wKwCiH/8alLKUp2Gkj6WAOrn16wiNI99jIR8k5bDa DZXgToZ673ZuX4smuKxmcmywrzjxNTFJAjFcvZBhHeU3xpRk4fRRcZVUS9fDfa+Uh/ E2HtDanAsvFUg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:51 +0200 Subject: [PATCH v3 22/70] 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: <20251024-work-namespace-nstree-listns-v3-22-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2754; i=brauner@kernel.org; h=from:subject:message-id; bh=VPZa5Pr6JMy6E6vudTcQn3gJk3UQIlVxfxrLDEyUgG4=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmptzvQT8X3qGlwT9Ub4t9lnMe7LvFUCH/dtZns/b TuveNfpjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIkk3GFkOJs6V/L1zvzYFlHt DTGbFOW/u+9c+2l70deNv/mXb5YMn8jwP5gl5ZDrTOfSHWvTLO+KWLXIy1zdImlysEdtxuv59Ss 2sgEA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 81 ++++++++++++++++++= ++++ 1 file changed, 81 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..7cade298c754 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -71,4 +71,85 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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); + ASSERT_LT(fd, 0); + /* 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 Sun Feb 8 07:58:47 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 427383148A6; Fri, 24 Oct 2025 10:54:57 +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=1761303299; cv=none; b=ZyH1eA6xLHDy9VUOgR5EUwtOYUsi/CtaVt2CRG+JApjjaShhDTRlSQGO1t522GUmw8y6E7Ry7OYdvmbLRM0+6OFa49dmtZ9QaZifnc0nCrDi4OFqUSXFL8/ERSDtzHE+9lPodGPv/bGLXY0szliXgFpuGci44wLItiabfipZ220= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303299; c=relaxed/simple; bh=aUj6NRVDEfXAvY88G+wOpYmY1IAUvRXs+4FwCz1W+QY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lZPaN0brtEMBfonWz9L/wYB+Dtp9/Fm4JQFvxdtJFgzEQY1Ce7fsJQ080S+nnNwFw52T/Xm3wc3fq0JNDHXetYQgVR0Xj3kyl1f4nl62qRs8JbQsOZtexfhOyA+FREBgLelZSr2dkyPKGf3E5mG1An9pUDcv0mYv+CgL7Un3RQw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=qez5EiCU; 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="qez5EiCU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 34F2CC4CEF5; Fri, 24 Oct 2025 10:54:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303297; bh=aUj6NRVDEfXAvY88G+wOpYmY1IAUvRXs+4FwCz1W+QY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qez5EiCUWkoRmLtGfJCc1hhoQu6p/kggIz7DbRZ7B1skDkxjXJ2GnJajucNG5kLHu m/ZWGPInBW4PqnhbctuZr/rStVgbjmQGC/g6yo4Lax3EhEbXmaAk6UeO5QlNrlcQUZ DZEh8DqF7r5wPdbuB+c99+tkBv3eedeHSx6TgZYlvZFmBjRdDjpWyevhYZDFwcVr/X cXp5aZ67WVQbOFknoVsPrpiVqbSoAdNo3x2lTeIi4dHdBJGML59JIgo/S3RMT+1DAI b5NrJOlin1MC1E87Qjsi9KMt/6QLFnn0MKdnzSyq1n3T97qkLhi0xqql2q4fvLO0NR ZtaeTYVQHkcCA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:52 +0200 Subject: [PATCH v3 23/70] 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: <20251024-work-namespace-nstree-listns-v3-23-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3551; i=brauner@kernel.org; h=from:subject:message-id; bh=aUj6NRVDEfXAvY88G+wOpYmY1IAUvRXs+4FwCz1W+QY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmo1Djq61+b6tt3c33knTAtvfbClfdWBP+KJludiL uy88z8nqaOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiD/cz/GR0nL1mr7qLpC27 fPCM0FvhK+6Euq9zv9u3799fZ4GmZnlGhtayWTE5Z6++nruB8dXFtL7PUzh+XC9YkDKvWXCRxzf XLnYA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 124 +++++++++++++++++= ++++ 1 file changed, 124 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 7cade298c754..c2e34de7a3a9 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -152,4 +152,128 @@ TEST(ns_inactive_after_exit) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =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); + ASSERT_GE(fd, 0); + close(fd); + + /* Wait for second child */ + waitpid(pid2, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 42E2D32E754; Fri, 24 Oct 2025 10:55:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303305; cv=none; b=iu1gTZD//UUJ1Vke2v7wg5yMpmKgt6c2byar0Ipz9mLbUwzoMoii2blFu94no7QyxdqIgTD3eff+8vx2sSnByb9fpGQPvW+Yw3147BvC+etVan7WLjfCrZSdjaulMulPSzOdIwF/t6MFKjpZjmBy/rDiKUflhfTZ+56C5fsS4ZI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303305; c=relaxed/simple; bh=e8EI0iOiQx8fHK9+00tBtoOgGlNpcvVChJMa2f3XulI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bDWg/56xG1qJmkReZHQVZgFySeuMyt1ig7h8Yr33+35Yszf3RjovvTY3D5Lo/okYNC0nCtK+fWyXhKusyfp7VfWT1NeW1IFm1+sI35YhfjJtewUTdI3v+8xjy/GTHVSABlkKq9GYgI1krWIzZBNqptGrkUPEl5Ar3S7r1qykFXo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GuNYvFMM; 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="GuNYvFMM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2BDEAC4CEF1; Fri, 24 Oct 2025 10:54:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303302; bh=e8EI0iOiQx8fHK9+00tBtoOgGlNpcvVChJMa2f3XulI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=GuNYvFMMrJM8GbW/at+LnYDJ7urdsLsMZO7sPszrT6Bxquoh0A/ncnRHOuZhgYQRh 70pmzizJDAR9PFzWvhPgKfDTUuLs5J8zL0p5RF1axQeOfh6DZypX5Vki0GnsYhnvuY yxCz9xyfNAyL47VwzOoUcQYbMRZFhRUIpYw082Mz9H992r/ST+9WhJDJpRRVFlnWuX i+Mhq5um5r9R/6dN77RNfiqozBsTBUk9GdEe7kpvBNHnAdr4N1tFD4F9RNSJPlxrY6 u+SEOC6j9TNxWScleJaHtPWHrBUL6MUrNGv+XTogsZl25n2u8iTj2dcu0fA7Xt2FrZ VZJMTdl/hXjhw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:53 +0200 Subject: [PATCH v3 24/70] 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: <20251024-work-namespace-nstree-listns-v3-24-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2891; i=brauner@kernel.org; h=from:subject:message-id; bh=e8EI0iOiQx8fHK9+00tBtoOgGlNpcvVChJMa2f3XulI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpV+1v3a07+otvqu9YG9z53bpXmPqN86yP34ePdC yKkwy7O7ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIph0M/yyN4/5MiODp2Lnn 96I09bYnH3UvLV5UP+ugRcbHAt5VjlsZGZZZdjk5CX0/danxcP/f2RlH5//MO7j5XLHouuuWxf+ 6trICAA== 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 90 ++++++++++++++++++= ++++ 1 file changed, 90 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 c2e34de7a3a9..396066e641da 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -276,4 +276,94 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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); + ASSERT_LT(fd, 0); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 3212C332EC8; Fri, 24 Oct 2025 10:55: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=1761303308; cv=none; b=LelOAjx9FQmMDKOMPUakgRG+nXXtBt2zcsSm1J55y56PqHn9NDE1giqJSUAxrrpdnDSvHwtoKE79VHpuDi0G6kGH/4ZlWsaOiFtlNR1N+dieHxZ8oK9UW+IgSVBCJuEB3XZ3bPr9EJWrwgEYZOdQdRxsWCrL2zCD+t6OGLm6Ctg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303308; c=relaxed/simple; bh=9GvGWgJa/IpvNzb6FhYrFg2g1xbeoNS/+Dh15oRdkuU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Iu7t0veP01K3530L6ecBLVggN8d6GPMgAsSnmTgp15+Jc7O3kUyO/ZXwWGpXK7m+4mHNZOdSanM3FBfMv4vrpHp9loKUtk0uz6nhiwzB8XNToCrj1iZYuoICQTlEDJgdLSWtOwptt2xaYfd4i/Nns+ChxNqGhjlWYaWNyLwHUD8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ayxzcpm7; 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="ayxzcpm7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 528E8C4CEF5; Fri, 24 Oct 2025 10:55:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303307; bh=9GvGWgJa/IpvNzb6FhYrFg2g1xbeoNS/+Dh15oRdkuU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ayxzcpm7Wc6z+pnimAVbPi0ui32yxRSOK9cv0nkCK78kwX9ZC4GhuVQDag/1aaBk5 KY/aaLW3JxUqxyUP+2rtloEuRp/8PZiXjf5M5qMJK4x1R2pKddh7lxbo+OpR7yfHGq 0JbWuMdM+Zwlht7+ldWjbFcTsc1BDM8CAly92iUMD1P/REg+WYFhhCM+CC72nGr+0v pIftxMPElRJM4f7C8wr52GZmHnjRHmfLcJJPPiiMNXNc1+zV9qJKIvfFG2mT+OJO7I 8vC4u9NMlJdpXe0/a3yaO9erKQZNEQmCDjBslyuN3S5lyJGIzIaFdbbCM/mTuCi8dT hnxnww1OA3ylA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:54 +0200 Subject: [PATCH v3 25/70] 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: <20251024-work-namespace-nstree-listns-v3-25-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2433; i=brauner@kernel.org; h=from:subject:message-id; bh=9GvGWgJa/IpvNzb6FhYrFg2g1xbeoNS/+Dh15oRdkuU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqt331aVyFv/7PzW1qarq4I7DH0TjdP2fjOzzF6M /PFhcJcHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABNZvZmR4cOss3MdxQ70TnC/ 5uxsed5sVnK+UI/u+fSYnQx16+fVljMyzPL38QkrKduntmobQ8fS1rsp1fmCzb9aj1hHSnwLuXW KFQA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test PID namespace active ref tracking Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 82 ++++++++++++++++++= ++++ 1 file changed, 82 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 396066e641da..f4e92b772f70 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -366,4 +366,86 @@ TEST(userns_active_ref_lifecycle) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + ASSERT_GT(ret, 0); + 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); + ASSERT_LT(fd, 0); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 EB5043148C7; Fri, 24 Oct 2025 10:55: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=1761303313; cv=none; b=GKNnJOUQZ7610FbGTdT7K+V3mh+zaTTkPQdLcaruA/7jvzBNOwxXOhZxYWjhrn02HZoI/TzouLIMPYDEdyOqJUYv9u02YaYTM8FO5wJEdHs5AxNLfrzXJVUSIUtfluzKdacFjNrOgAH+kHjdGAAgzB/uUR5Z257RXot+uLInJV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303313; c=relaxed/simple; bh=zOSZXXVQ1jVkT7WHK+88OLa6Cp/PXPPixfxVAVT9vUI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=oVwvlMONteejZztv1Z2LQ7I4unW5vzldciq1o1FWoBBojBpqgkakdbn71JndEDLzGwOJQk3GY+SBycjixZar5ubl8GEkAclYGtgVuJnYx0CT2tdJbuPV2pY24wbTREtb4wwtfZmk3MJVqvpJ5ZzB2+UkkzHyw0No8WqM8L7vExg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cw/cdEEj; 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="cw/cdEEj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4AD60C4CEF1; Fri, 24 Oct 2025 10:55:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303312; bh=zOSZXXVQ1jVkT7WHK+88OLa6Cp/PXPPixfxVAVT9vUI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cw/cdEEjDh58J6Sul51gTUSUvgWy/59P0JOLuC3aRnDLSa+TWrPj3YJE53ROQYCpn V4EmSvGLhuwIvd5Dwta+IBcwWOkqmTGsKoI8NSwdF6OrG0dHWt8sSC5Fxb9bxIf+P6 uJc/agGba2W5Jcv/F0iNmr9NYV8jaKd6yzNmcH376oXkHyr/hKbo+v7oykTgC1sca+ y3Qi2NZEJ33iPtumeh7Ot7drGcjAFVZMhOUyS0QU33JdHWy3W1ZyEFz0Wqw/3KIWMR N/9GTmyjK24hqovFsa2AwbocML/5PbgzqfQ96q4qwmgeAzDSbSVCW5iheg1zYAglIy mqIZh1bLXKbxg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:55 +0200 Subject: [PATCH v3 26/70] 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: <20251024-work-namespace-nstree-listns-v3-26-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5791; i=brauner@kernel.org; h=from:subject:message-id; bh=zOSZXXVQ1jVkT7WHK+88OLa6Cp/PXPPixfxVAVT9vUI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp9ue6CQqehXY53xb9XX/xS5+ous1ieFnv/3Ezdq 8xrUmrlOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyqZGRYfX800f+vWXK/lDi 8yCdc/IW/nt6n0R80h+efv3w/WurZGVGhtv6Wic2ztx/btHysL0Ll93drVX4d+LFp4sUfE+Ge15 4wswFAA== 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 155 +++++++++++++++++= ++++ 1 file changed, 155 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 f4e92b772f70..50653096fcb6 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -448,4 +448,159 @@ TEST(pidns_active_ref_lifecycle) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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); + ASSERT_GE(fd2, 0); + + 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); + ASSERT_LT(fd2, 0); + /* Should fail with ENOENT (inactive) or ESTALE (gone) */ + TH_LOG("Reopen failed as expected: %s (errno=3D%d)", strerror(errno), err= no); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 E75183148C7; Fri, 24 Oct 2025 10:55: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=1761303318; cv=none; b=uUu4H+zK0K1XTRgEi4MlVKM6qBx0DuI4EuOA0Ldv05JKQgubiAthHa5P/Fo0rZ+FsRiW/kH4yndCtxDa47sacu5Sbq0gMNA5JOF6BdVt2w065Nx0Oa4YFBQ40tHOSncj4nupPuY6CBH9xNwi+e01N0E9/lQvthziX5YMperch7A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303318; c=relaxed/simple; bh=uKR7z2WD/2U9Ks1GPvzLGsI7e1WaqtgCdzzqT45jKts=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NAXK8C7f61NFR/qCNNDHwpyKEBp468NhpaFjOrwaAscXHX72ZLMoDc/S9wz4wW3D+YSYqRRRSMGco3UwzgadNSx+qRuZr01CgwHA7cYHosbXlvdBRQKGnvx4b8zT332wV4WQnPMvsI3KEf726nTktOUt8xp/KZAV5qidVYoJYFI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ihUfgd08; 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="ihUfgd08" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 4B325C4CEF5; Fri, 24 Oct 2025 10:55:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303317; bh=uKR7z2WD/2U9Ks1GPvzLGsI7e1WaqtgCdzzqT45jKts=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ihUfgd08up0BkmRVKBcPgoF0oA/h8zWOxPALrK5HlqpoTmKs68cyVwBuo6QnzCbpT FBXWfoPK48rkaGIT2byNJYP5f2UEmhFSFkc5uP9cO8w/tgI4ufapw4b8xB6bcTxFd9 5gR/f1wR34As8W6ClNEprDhstJ9p0IQSCl++20Vs3aRl0pf8C+pMjadEt1/KuHOVjR xgTKsIOhaXqgGI8p7oC5wBBwLdmzz0trXfcOaJCQlmklSqJOYDRJM1As0ieUo1ZJ3V tTBVTu8ATZDcCxHm+ArBlaxQKrE/tJZ7u1srz3XcGzDBi/KqpfgUGE7OdwPFE3e3qe bnEinto3APUAA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:56 +0200 Subject: [PATCH v3 27/70] 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: <20251024-work-namespace-nstree-listns-v3-27-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=8847; i=brauner@kernel.org; h=from:subject:message-id; bh=uKR7z2WD/2U9Ks1GPvzLGsI7e1WaqtgCdzzqT45jKts=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrd89Rh8b6DxY9/bNT6tHjZn0QbL/8JrTdDtjQ2c S5889Agu6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAizk2MDHdWis8TF8wNmHTm UN9epwCbFa8PNtrWf2mILVXWDrv1bxMjw9/Dh/RX6NcWJM90jIo7tmDfnoR1LWdit/TlxCpM5Jg txAEA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 222 +++++++++++++++++= ++++ 1 file changed, 222 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 50653096fcb6..60876965dd71 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. @@ -603,4 +607,222 @@ TEST(ns_fd_keeps_active) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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= ); + ASSERT_GE(parent_fd, 0); + + 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); + ASSERT_GE(parent_fd3, 0); + 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); + ASSERT_LT(parent_fd, 0); + TH_LOG("Parent inactive as expected: %s (errno=3D%d)", strerror(errno), e= rrno); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 6442233B958; Fri, 24 Oct 2025 10:55:23 +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=1761303323; cv=none; b=u2WIKv5LknjO2zJwD6uxEzScjgF7JWudadqf4tCl6ZKJfQkM0FU3uSGDSjdrWOt9pp1FATdDzK3vqbUrI3x4aG/QObsYcV3cH6cTR01HF+GICa9tLIhbWAT8EJRzADZcHl9xHO46yx412MFPppvfy4iUz2Q6Ju/wR/gReuwGqsI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303323; c=relaxed/simple; bh=45ZVAOSQ14PBDoxcUZ9fr0EyfYF6v23SFzJ2GrRGZ3Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GHtWy1JL4iNJrZwyvsgMazDEbeUtNvyQJUq8l8pTGPkKoMBLXGpUrCoGOeigempUHff9JSLmuhCHlVuMWI1LkWsVvoOtP3LNkBHCIPoEsSy0YmBfgCF+U+KEDoLkCTWXaNwM8HQnVLA9Rcnw8DIZmZroEOJD3IJ6e7InI3cT0p4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t0kdq1PT; 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="t0kdq1PT" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 47280C4CEF1; Fri, 24 Oct 2025 10:55:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303322; bh=45ZVAOSQ14PBDoxcUZ9fr0EyfYF6v23SFzJ2GrRGZ3Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=t0kdq1PTU/3GA8UjOfYOduY9T/jA1Gz3i6knpoDad5oajgEUzyil9vgGAh3I7vy1T Ek0ZVCFLNNel9qafhZ46TpPtVicbRzQMvQjm1e6YZgLtBihWjxAsvYOPrkyaiOh+o3 sRiQfEhBhwFrrjlbC5HZ3u1CFHjTyJswZCVVDjW9Zlw90lNTdMUqYTuuqSwy8pmZCV yodZFLrIE7Lm1BDgyVEsTmFNEalGSzf6+4bCYVmYOtHQ+685TFJoMLn9qDbOb/elDy t26Cp8aOsRMhZIQWpyK3V3NCOtFKwbqVtTz7bQNam//7FpZcB3B3FwyFbDRbb0z4we u5moWOn9j2eyQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:57 +0200 Subject: [PATCH v3 28/70] 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: <20251024-work-namespace-nstree-listns-v3-28-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3400; i=brauner@kernel.org; h=from:subject:message-id; bh=45ZVAOSQ14PBDoxcUZ9fr0EyfYF6v23SFzJ2GrRGZ3Q=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmq1frv1UVJO9nq174UrNpzLmXBi2pOZ9ka/jCe6J p6abzGPq6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiL/YzMsxWz3nGo1xvVf+o 4sLSuCcTi4u6E365c6v4M3t7vl7wYSrDf0cGZeP/r3K2qpobLp9+r0syO1JSR+KwmoR8nnWNdGo 0BwA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 117 +++++++++++++++++= ++++ 1 file changed, 117 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 60876965dd71..55a741d32b08 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -825,4 +825,121 @@ TEST(ns_parent_always_reachable) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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); + ASSERT_LT(fd, 0); + /* 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 Sun Feb 8 07:58:47 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 02CAB314A6E; Fri, 24 Oct 2025 10:55: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=1761303328; cv=none; b=O+G9dYXiH57nIv47xv6TpSZWbk3c1MJf9HWccNo7NE6oa/IsSwSVieWjzxURN6gJbK95sAl5UaEHwyqoZKU1IxUo5Cdb8tM++VLycFg3VGgAWY3i8uAXhDvcMEZucSsAgsHRrlm837BryK1hj14SLaldyE80qqLNEOL7H8tLapU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303328; c=relaxed/simple; bh=15Kss0/E0G/yMSjq65yfXbMGd9pstwgOgfvTnyiPCqg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Zg/Bnz/zIHsIqXNbByPh4tq2HKFyul8dp7E7iVompbqCuDU6gqswjd0SVvjPDBOBG1KtCZvwCRBC2V0J8eY8PHnF6yz39enDvZUhTF3MZHlC/3va8DsCUC4y1HUooDjzG5Sq/fIs5BVmAD1Vyu3FIdJqI0OGQB4JMqJralz8i/M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=krPp2Fw2; 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="krPp2Fw2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6359AC4CEF5; Fri, 24 Oct 2025 10:55:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303327; bh=15Kss0/E0G/yMSjq65yfXbMGd9pstwgOgfvTnyiPCqg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=krPp2Fw2+7necAESB9wQ7NWxQvpJWRbLFN1WL3lxslakHFsLSYNdTmCA8YqAllH5u 7Hh4HhBfxr7M6EGuOhtnv7PlJSgJHgpypCU15xLUYGoUdgxkNBjHMQlAxGMyYBBq0N MqUQOdClgaTNRqo5LagEUeSu23pibyuikGRBU529Cgt4Wb6AdVHNbJiciJYniLBTkt lDxkCLONpqxdqPIT7P4JMzdAalI9rr3EBov7sQDGggCa0NHiZxlFUn56vuQs5imqhf 3Qc4371NiMBmVfaHIH86gMrwvqDS6TBrcCJscYY9qt2TrZ749CrOEfi+mhNdnivk2v jkCwTmWfdEXhQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:58 +0200 Subject: [PATCH v3 29/70] 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: <20251024-work-namespace-nstree-listns-v3-29-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5204; i=brauner@kernel.org; h=from:subject:message-id; bh=15Kss0/E0G/yMSjq65yfXbMGd9pstwgOgfvTnyiPCqg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrdnfvJq3JioNP9SR9yr7TxfkzgCq54ekqxscj/t +SZA3Z7O0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACbSJMPIsPc2Q/b8i2vUr9Vs ZrsTzZQ/N9SZ6Vj7zl0WhzrfSMS9FmNkuHa/+ebMC88yur+s/+2YIlmtNcNN9JQj6+4fObsdj81 gZQAA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 164 +++++++++++++++++= ++++ 1 file changed, 164 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 55a741d32b08..88189398aa35 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -942,4 +942,168 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* + * 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 Sun Feb 8 07:58:47 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 2DEB7311C37; Fri, 24 Oct 2025 10:55: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=1761303333; cv=none; b=qZOI8XnreZ49ZhyxlIDcciMriaLR4TyqvHOzQARKju0/w5y88CMijxzpl+kC8vH1oJUTqUPTlvZaucQ/VnJY0wFa/QiPryblDsTyn7tXtXzGFWMK/gXdMpHOSuDdzqJe3DtVxUjMbUuY88sTJqFkxy1gxob/fESdL/7s9jHZgfI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303333; c=relaxed/simple; bh=y2A92uW0sV7FWrn4QLm1MH/vZbCpxMWKE7RtucXI55k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WqA9QV/MTl5d8HRQne3hns/5GLXmp0ZGu3tZJDR1qRXW50et+HKFXnAqgj5H3IA4vlXYqiUzNEOsrLfdYUxKGKRq+njPJFgcC5fhipA2FqLWDVI7cKjUMliBs3VUcX1zbB9JzK/rhooQEFi4cdLPYD6BEjPf627ku1LvLNqjWe0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dKkIF3kC; 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="dKkIF3kC" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 571DFC4CEF1; Fri, 24 Oct 2025 10:55:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303333; bh=y2A92uW0sV7FWrn4QLm1MH/vZbCpxMWKE7RtucXI55k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dKkIF3kCWwO7bai+/DNC+OleoU5hfDZHVGa7yZNuC356+qVsqopPMiI9qh+BFmRDl dql0WxtFg/vV8OJYoLLoGk0cMRsIIjzLFTj3bTvOYsNm895q7CjvZqDvGOpsTFStJM FT0+oT0JSCl9r6SLaU7o0QL9NdmfRKpuYBIe4XEYiRWSmj9VGKFX/eXjsfuBGF12Rr CHiUZ769iHuwqX0B4m41TuSy6W9yNazdVvvDmDaUajH/1C3gDuZ/DduPefTmTxmqNr 7MH6MU+i30vW4dLbNvFoHAnh6zyEUvm1mtNxtU57y7YqqbG8gu85NYJc4S5ZTcTB9j Iq4zpAMjgXS7w== From: Christian Brauner Date: Fri, 24 Oct 2025 12:52:59 +0200 Subject: [PATCH v3 30/70] 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: <20251024-work-namespace-nstree-listns-v3-30-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5568; i=brauner@kernel.org; h=from:subject:message-id; bh=y2A92uW0sV7FWrn4QLm1MH/vZbCpxMWKE7RtucXI55k=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp17FhXttxaQP/t71Vafx99kBCS/zjreNIsAdG2o 7LhjdxCHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABN5+oSRYVEPz7boit1OZVk7 PhrlWKTv2GbDzWL6j892q/xj1WOGVxkZLtgW+RbtKv3Rtitla3iZoUdgy1etAxtUFm/rWj1Tmke eEwA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 170 +++++++++++++++++= ++++ 1 file changed, 170 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 88189398aa35..a334792da982 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1106,4 +1106,174 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(p_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 2792D311C2F; Fri, 24 Oct 2025 10:55: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=1761303338; cv=none; b=lXapunHqEsU9LINlqr+zjYBAZJVJcJKIfTIyWgKmBC/6BIAvAp/sgNDtvnymNxlCmi68ijp3ICz4QMhs/PtkiWh3LuJJYWg9YN0sSRJlRykyJcxXSegr7fVHnCXm+EPXS3jNVIzNk/iyuw5/F+rDQShEfF3kwKzG8sHJbh2SbqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303338; c=relaxed/simple; bh=/yKwCa2j86hXlE7nkbxfrj9fgrYMvJohWcIM8ykZ1NE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AO089cYmbRM8qP1SBBf38JBKArZhuV6jZ22tNeQGBxctetT4EJ7fx+2UA1cAxJgzpu8lcISqrv2jMNa6DoGtt35HNa8q4PM23JRVDlFl6EXK8/e6JnY9H3KgFf32jfdq1GxX1g7zrFtI9geKZWleBwwP0nBZ34kJtf/FmpINM1s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Nyt2JbEq; 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="Nyt2JbEq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8116CC4CEF1; Fri, 24 Oct 2025 10:55:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303338; bh=/yKwCa2j86hXlE7nkbxfrj9fgrYMvJohWcIM8ykZ1NE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Nyt2JbEqgKCcRftbj3qwvtoG6j8ykzDlll2W1EOaFu0Iz38JwkiIDbGGD+CZ/c8Jm ozwMkWbQSeE7B5yfYQ3lPJViUs83OW3x9GLu+uJMKn6E4SLHGV1ypaHtLwlzSNPKL7 wUiQxu0r8mSROvIsBTOhZMqGyUj0DHY+l8Y9T38+Uw+cWE8reVPZc6TWhORGdETV8N 5Ajk4RsmKvYZzQpiYX/4UBTVEYX3ztnfb2fbwHskJUf8N1CRA32fYa7Mhq0t2bfB0b l58XIh9EIZni947+A8dKmqEkbFbL1VZ6gAnfLQodppEGCnZ2h1IzC9vxj8a9M9qGSH 9hJlbGRsSOLcw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:00 +0200 Subject: [PATCH v3 31/70] 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: <20251024-work-namespace-nstree-listns-v3-31-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5561; i=brauner@kernel.org; h=from:subject:message-id; bh=/yKwCa2j86hXlE7nkbxfrj9fgrYMvJohWcIM8ykZ1NE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmoLyvTjXWCQYtpe1G9wwlbtY5dJk/ujCdM27+VZJ XvwtfSbjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlkPWdkOPc368KHe5INZTcm XW3259/0v4p/36Ofs3n3zym/uTNQ/iPD/8Db7Tz67O8s7UOcbeP23LVUubcs8scXvjKfA8f81/9 m5QAA 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 Reviewed-by: Jeff Layton --- .../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 a334792da982..885f58c81247 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1276,4 +1276,175 @@ TEST(ns_multiple_children_same_parent) ASSERT_LT(p_fd, 0); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* + * 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); + ASSERT_LT(u_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 7A269314A97; Fri, 24 Oct 2025 10:55:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303343; cv=none; b=C8Y7QZkSkYv35WFxH2GHQsCqE9ldP/4DoilO15sWy11qAyS3rM/rcc9m8cHX4J1ybUhv1E2aU18LlmFXJ/p2/0S4HozMMqxQ6mMa8nfLxrWdu5vczVTlHTmuugF0bfrMhcbkoeJ8fIQrDiTwxBvlK1kcDrqHiJgOq9Zpvswf4c0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303343; c=relaxed/simple; bh=XQPZMUVWj0I1xZ/psAbg6Xt/HD13reOfi09gp9j+WG0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Bx99K+LtN3YejtPqGPDR/cv3Kl2dwATSHgT+7HnnmPBJnApygR9KLxb0MmIhgFHD92ljLCblw3xjHskSrp+nWhEOj3bCURDUWcQoJpiHcVgQzK07DZus/Cg+NOQF7GG1am9IJ6uW3tO+wQjvTVj6WGjiI3RR/drjvcaU5XvN4fk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QI/CycgL; 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="QI/CycgL" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7BA3EC4CEF1; Fri, 24 Oct 2025 10:55:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303343; bh=XQPZMUVWj0I1xZ/psAbg6Xt/HD13reOfi09gp9j+WG0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=QI/CycgLlT29t5rgQ61Mrjs+t8nZqRCiWLFVizBL5gcTrBkhKEcBtY9VoXkP/Lawo kyT1sMUMjcrFrGsoluu8gOERz6AHdGoHMBnOmLxXR6AKvfiWIi1Mue/Sn8tbD+aykA XmZHHBQ2eF05ez4qaODRbufrEjj8N0bu+opcCMj2ZMO8sH7/VotsaluRJMhBw8f6qa H1fLKMq4pEdW9wXWRnOWZz3/6XMm5AL3eBcNNur4KGrYYz/T4l/iox9djpnaGyIICR ZNWIYYAfgkFPv1NHSrzgutq5AXjjlX5cXc5vOcpqx7MyWoDRSpp38zmzTZXtw6Feui LmaNz6Jkhkr8Q== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:01 +0200 Subject: [PATCH v3 32/70] 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: <20251024-work-namespace-nstree-listns-v3-32-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=6072; i=brauner@kernel.org; h=from:subject:message-id; bh=XQPZMUVWj0I1xZ/psAbg6Xt/HD13reOfi09gp9j+WG0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmprdz1Y3x+UE5esXm/aYV3SoC+xY0/vrMOWeaaq0 3dIVtR0lLIwiHExyIopsji0m4TLLeep2GyUqQEzh5UJZAgDF6cATOQ/CyPD9+OCuhqdFsYa33dt zbj+/+HtenOVTwLLHkzlNLf3bC15z8iwP/u7/bSG77PPb/Nbpz1rjc8uncPbln9+MuuysZZH3lZ vNgA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 176 +++++++++++++++++= ++++ 1 file changed, 176 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 885f58c81247..b1a454dac9d0 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1447,4 +1447,180 @@ TEST(ns_different_types_same_owner) ASSERT_LT(u_fd, 0); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(ua_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 333AB314B69; Fri, 24 Oct 2025 10:55: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=1761303348; cv=none; b=pD1tQJH4QSBMmKNannealBzbmyRn8q04PxUPqDGsBYzSVskwSNmtGUmvIPadaxzXt6D7aUMADggePqc+RyQf1+wjh7oiZu22Wu9qEl1NT+VFjMoxu3SP269W+vn2uYp6b3MQ1m7PZsfHKZUDJ1dk/ldr4dIzfsIxP5DapIIcOXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303348; c=relaxed/simple; bh=DmFqcW+ecoV6629hjGEqua36G7/JisMrs0MfTVBDcAA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FqtMY5twgob4hSbfPwXGnoMe61fMpGN0I6tFUr/tlVJgVXfKwtyiT1w5U8qS3z/MHjPhPXggskp3TMP7V+Uy+ItXjdhbSVFFopocKfUJm4n/VxNk2HfEQ7xqn5P1zTvw2n61cCslcjmZd5b3i+asT3ujtmrsQqbt+ouQjq5ixRQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WHK3b75H; 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="WHK3b75H" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 8620FC4CEF5; Fri, 24 Oct 2025 10:55:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303348; bh=DmFqcW+ecoV6629hjGEqua36G7/JisMrs0MfTVBDcAA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WHK3b75HBsro3CBofl+jgLzWk+pDaEBH+on40OrU0xFV6Neet+WvdIMHtKj6/ePN0 Uq3CRygawLAo0+cSMe5DyE3UoL9kxUPtlkacV2foo+omqHEst1b3e16PmMyvp+1rYO hO7VkJeAZVqCBxqkUpRSn7lI7bSIP+nP52Ap5AIGsDQIEvk3CwKZrAGskG9DIm35pp wTEAIin27x77Dt9Ow2TWDcn4LRZPJXLl9Lyu6UtLoVTdhbP7bJVATkwHevEqyK++Pn HLLthJZ6byjB2VEHEosjUny2nyy6HmcZqJh3Yd6h6oo5pURI5qlcqHgOb8vK1uxmL/ 2NpqzcZjoUwSQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:02 +0200 Subject: [PATCH v3 33/70] 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: <20251024-work-namespace-nstree-listns-v3-33-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=6467; i=brauner@kernel.org; h=from:subject:message-id; bh=DmFqcW+ecoV6629hjGEqua36G7/JisMrs0MfTVBDcAA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpTn6VtJRP0pOdvLVPopfWr/3Fe5p6hm5TwqKSDr cFwgUVpRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwER2iDMy/E/4d9qgJnLa7OXX t2wKvdvV+yD/lb+IqYDWzDsxzx5kNDP84TraFbTye2aey5keizvBkYJzCs/LHNzQX5n0MMehfZo hGwA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 194 +++++++++++++++++= ++++ 1 file changed, 194 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 b1a454dac9d0..25f06e623064 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1623,4 +1623,198 @@ TEST(ns_deep_hierarchy_propagation) ASSERT_LT(ua_fd, 0); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(p_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 2DFC2314B69; Fri, 24 Oct 2025 10:55: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=1761303353; cv=none; b=V4HO5DZ+n23cNx53CKK14CvwkseNtpdBUkKkzFNAD7Pbojlc8Td1ceChmNunlx9N385SSU/HeKH8hZKH695jtCum2IQpzuOqPqq5+OedDerz//0ALmJGqAmoNtBHJ9uCV2AB8WqlAibsotYpEUbtW1+/t3dhbf2wg11cExW11+A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303353; c=relaxed/simple; bh=d+4+UcmFmPg23QL+eCNaKFnhnQg3HsdsjL7eCoiFS0k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=tDav80fsLjrztPncKyGgtJSdpEyg+9sdal8nwaaUxi/Z6SPvBzqzATAeIJC/bDrFAFlJODQqb+cifMHRJ4JldcacfZ37gncMDEJ3Y7BiZ+F1rwx/AxltM9aTee3BjP7o7sdeGA5AA56rT0aKiTQs3p2VUH0zzZEpzwPheIOyqEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tYeVc1t8; 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="tYeVc1t8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 868C6C113D0; Fri, 24 Oct 2025 10:55:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303353; bh=d+4+UcmFmPg23QL+eCNaKFnhnQg3HsdsjL7eCoiFS0k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tYeVc1t8XciAXWQSkpEGfscl2mNHN6Z7RBC//4cbLhMmOJxzUjY5RBkFuQ5ea6boE 5tdFSgUsmvBSwfv7UaNS/CkyKHPJ6mGQ9lJUZ3KoMXV8tNjrbLB0UcGZy9Jm1Mbm11 oG2pkDOwYYqAocJHrHeDw0PINBf78WxhyoJQ5NW9OjkcaLzPCpkIyfPJM849TgDnR4 y6hpzVtI9jIktcy9v3AUuG5ipA2gZ/PPJRHQCz1BUeDS2o5ZbEwt6zZBwMPY2z8JDR E0bJuOkrfrCUif8gnNNJN/x9DKUVE+Akggcv3dE5poXWFRASFxs51H6Z4cHR47aERZ A+S5Fg747hUHg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:03 +0200 Subject: [PATCH v3 34/70] 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: <20251024-work-namespace-nstree-listns-v3-34-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=4427; i=brauner@kernel.org; h=from:subject:message-id; bh=d+4+UcmFmPg23QL+eCNaKFnhnQg3HsdsjL7eCoiFS0k=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpL7V/kILbP6bnHhEkbxDnz+fdZ92btv6nqd05vV +s/kXPvOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACayQY+RYYN55PKoa6bxsyuu nbTt/Z1r/jzodYyzxepkm6MOikfsHRj+h5cJXWh2Wr5Tm/3wTply9TSuWQ8eLO4ue31meeAW21d 2PAA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 132 +++++++++++++++++= ++++ 1 file changed, 132 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 25f06e623064..430702c041a9 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1817,4 +1817,136 @@ TEST(ns_parent_multiple_children_refcount) ASSERT_LT(p_fd, 0); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(ua_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 948A6314B69; Fri, 24 Oct 2025 10:55: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=1761303358; cv=none; b=m+MEwt/cSW+jyOar60n2Hjw4IYjAkiYqYOKZDmz4T+t92Itqi7HSZPBQvOo0HZjUAfcp3/07JX/WHM1dHex02fSjdbEWfN8567yraWqvglq8D+NCiDg8q/7e9H0/dwBrlGFcKMp5Ys5XGIxsiFL+n9MGnW5UiCYDFIDkFC2gM3I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303358; c=relaxed/simple; bh=ZSob+cuR8TNM3RYLLd2l60NqKAeHuoXtXyT5AeRNtxA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=jictdIeTuADV98w4CcME91kp9C+0TU8SHbaJgWxaav4Hj4XoC0QBu1sfXLiVQDmQaiV3CNBOELm2J/PCVDhivjVjusQmdfPHnMo3zviGr8RLc2K0YxHUAaKps1dZiQ7cjnnHthOwmGnvizl3H+ACu1n8upvEThDrwBPKNmX2cqA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=asmhMTxt; 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="asmhMTxt" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83876C4CEF1; Fri, 24 Oct 2025 10:55:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303358; bh=ZSob+cuR8TNM3RYLLd2l60NqKAeHuoXtXyT5AeRNtxA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=asmhMTxtpNV1SR5Gj5Q0uIhI7BwzsDQwfRC+gbBFV7SWE4CY66o0mC2vwc4P5os6g lSkLBc2Kcx7dbLXGquR/CxivWh4Hu6g+Yt66Dl6AG25EpKgfoVrxFp3ExNLWNmUnBq Gjc1Rv7KuIG2y3lgeTEJ8vcw2UMzJaa+juJAez+Fnf+SdgMmGBpN1ku/iwvswXO12E VcDw1Lut9+9SY0FiR0e9TimWvoLMjeJHRKrsYZYnyuQTgvqX/GGkYKimeiW0Xktp8C ijM+2B9KHmozKft/UN5fD35h4zN0BXWVTM6My4SGNzywr6hNKR1UJgZwTsDz1VqNwz 7y/OMBL6FxrkA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:04 +0200 Subject: [PATCH v3 35/70] 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: <20251024-work-namespace-nstree-listns-v3-35-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5309; i=brauner@kernel.org; h=from:subject:message-id; bh=ZSob+cuR8TNM3RYLLd2l60NqKAeHuoXtXyT5AeRNtxA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrLzS+YeuDlD33Wb9E7Pl8VO88/ddWGiXNEsli+q 09ZOPOPREcpC4MYF4OsmCKLQ7tJuNxynorNRpkaMHNYmUCGMHBxCsBEtv9l+CthfqW2YKpo+Sbf gzZiWlIrWL85f5y7J+9w5ryJBSddmVMZ/icYGAlkRd1b5XD0zIdlIuv3e6+VCSpOkQ+M/hwkXfe zgQcA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 164 +++++++++++++++++= ++++ 1 file changed, 164 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 430702c041a9..b7fa973a2572 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -1949,4 +1949,168 @@ TEST(ns_userns_child_propagation) ASSERT_LT(ua_fd, 0); } =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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(u_fd, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 91F5E314B69; Fri, 24 Oct 2025 10:56: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=1761303363; cv=none; b=phI5SV07GISmJmkk2ihZGcXcimEIJYZwaFI5DLutXglIOEychK5Bwj2MmG/GOPqYwua/Jd4L5iUTQJiqPTM7l/BQN5PdrVz2A53POHsSQnhJ4pu7r6H+8LoTrELch/98WXJL+SAUuX1q6mD8S/Tc0IYVOCWA7SYZBlfeaywOQMI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303363; c=relaxed/simple; bh=WU3OpDiHSBOB5eonlPoaP8MJGbmszqupW5dQlbeASiQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LaCrhDKAnZck+iA1XS3FTVBvU9M3Q3czFBnCBR8QFU5LgFAiTwLuKmP7KBM8MN7F/4/fwsUe7VxZYSGn7DVETuI5jog5HCGXmaHB/OnNjiN8NS3kiQdMDlL9fZSCU3HmLJpmILf/D8EdXLNp34c6ojYTcR+LaUwf/sviTQJ+RLQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pzI/e047; 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="pzI/e047" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 926F0C4CEFF; Fri, 24 Oct 2025 10:55:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303363; bh=WU3OpDiHSBOB5eonlPoaP8MJGbmszqupW5dQlbeASiQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=pzI/e047vSvjARP4MMY8D3oYuvNqG+le1yU5USl711GJm/fNl4JaJTmlFc73uVb/d G2mXBxPht0eLP/xByaZG75YpuPkjQ/kxxgnZ6lChwIpC6StAPb6uRzSBCUI8YE80Zc HSOfxsrAFvfO3Np2NunE7+PYBG75QIZvt4Cd4Dd1VxrevxXtHZpCEvzGfk0tYiMXSZ ttrzVWONCvIRZtqAOsprTBQU0ES3j4pYRcgEWfqvCEiKnQcMqXEtGgHwKn6QYhMOXq Gw6m8PeDLYhY3tIMCBK5oo4ZxFseRy/OIdfHil0hAZboWjczHuYTHkPssAJTU8SDzU tIXbRFjGZ3dYQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:05 +0200 Subject: [PATCH v3 36/70] 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: <20251024-work-namespace-nstree-listns-v3-36-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpLO3jOWn7jyTUpjOn+OY/+raji73KZ+o/brf7dn XW/3tYFdpSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAFzkHMM/01XzJp7bZFIovneG rdk21u1NyR3+Ij1i+zS9r+udiAntYGT4oTFD9nBXrl0bt0rO7V9rktJfbN0U7cjxZLtJQHvZxkQ OAA== X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Add a wrapper for the listns() system call. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 BC4AB3126B3; Fri, 24 Oct 2025 10:56: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=1761303369; cv=none; b=luoJyedG/LZIE2UynvmbtJJZpigt3R+WKenVlXWziuK5M7FPTCh6lhMVdXqS9Agz+TbIo9zh4wrsyLuqrmlTYqxIbcD+WGED9epk7FaD0UOY52ipbH1VI5/ZDmWc2S2rQ9hKMbEGnnzlIxsnM3C+dAFgt6ud8Qmo34TyXInW/n4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303369; c=relaxed/simple; bh=NAhtGlBVfCqrlTfWbGN1zDMklE1n7EKY3e8ekT2vQ0Y=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mjSN+yp14LlmzmkWx30OVClIbBwyO57BPB54AsnoEVO3/d3z35AK4qqQ3mYvRO5YCRq0hSXNgLU0WLI77rWfNbTabRXsNjOpgyO1EXNsUBFh03myKE6obAq/1X3ofiZNezJG5IRcjEx4MSOsqCxM8yuwBp5ZWaQTDBCpkqNx3T4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WTMaRsaF; 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="WTMaRsaF" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 92706C4CEF1; Fri, 24 Oct 2025 10:56:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303368; bh=NAhtGlBVfCqrlTfWbGN1zDMklE1n7EKY3e8ekT2vQ0Y=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=WTMaRsaFeygFiHMdtqKHeMoK/sbRe+5g8kbMDgYh1ZZpLUptUfgZFnaI0fv+A8b29 EFBMbqKWfYYziNi6BpUemVikIo2RSH1H7U0ZXfjCAwHmjLpa5zs133kke+l+4Xgppa 7ti2+9aeVqM3rosghmeyodonnd1uAFZUQi283LzMw3s1l5o/hG7j17pIUHSwlEnGj8 rWf/jCDBY2IyH+Z/HyOQhwBN+KoryahPWCpP6b+ctXr6AvyL1gWZXhyFKpFkCpcxMJ ouKIclPd8V3J4Auw9nlnGbDYRMCXTdTFw2Ai8HE6LzOHAuzYZYVHvDWhLsuqU0+wDA PKuyhGeHuXLzQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:06 +0200 Subject: [PATCH v3 37/70] 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: <20251024-work-namespace-nstree-listns-v3-37-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr7sqo60CXAPlx4g8cLkYVzZPkvLeTgiXLQOLzyv vTjlGVdHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABN55s3wh/sSH88N1tTPuc12 eSeCuaROcS4TqbLc8ye47cf6/s/eBxj+F7dsi8uxLpW7XzJ9n1XrKx0b1oDHcYqvc6YwbWIwziv hAQA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 606BD3491E6; Fri, 24 Oct 2025 10:56:13 +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=1761303373; cv=none; b=OXdxmFZru7kEsnAeFx+8tLhjBQCAhQMKwOAJKvGei1Msf2aSYg8iBuNToPx5/QsD14kGi1rCh7SP/qsNJVgtcaafeR+/8R+4ST/WmE4JCsm79Xs2CyjS0tdtYGbycLzfhWKJUL8jSXIaLYapohnlgZ/qm5IFbrQcLAX6nPuClus= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303373; c=relaxed/simple; bh=gPBGu8BceJ6oHRtyp7iwBf16DUj5zY+HNikOeiNBVYw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=OI+mwLGSgt1z7eZQywYy3WNa3FKmCEm3DyUl2conqu3xdQ0Yss5x5jhPh7iWVq8lzX64VpOVeRQvHUjh1EaNKRkjYvr7PncOm/kr8Puh2uc+99HB/imw933GJOaPfflFoB84mMRL20Dh6KcLX1SgHFZlaLiyrfX19vzhICN/sn0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UCnlDw6K; 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="UCnlDw6K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id B1496C4CEF5; Fri, 24 Oct 2025 10:56:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303373; bh=gPBGu8BceJ6oHRtyp7iwBf16DUj5zY+HNikOeiNBVYw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UCnlDw6KAaZztWiADUu/lzZgT82C+VoPzLNu/rxzxgE+8sC4gks36mnpt+RtA+DrQ wnPe4kKCOVXki99KmnPTy8kfoFQjxDmir+9NzcBzQtbg7D7+bPrBV6COWJYSGpTFS1 myaepogQbJ31SjY0c9RxVd/tnDrsl9pyWB4p6J3K4IwLQbZZU1yKyjs/bt2e2zh7eE kev2BrNrW5STF20wpwnGhNU5VlgJFBJRYDd4T0UnomER8FgjcSdgYFjtGQrv6PZdzV 5T2G2fR8V51LOrlIJjbEr5HIyJY+ufsLRYR1yEkDNsCqhvNSpMp7J955uIxYCwqW6h qHOLu1c+uROjw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:07 +0200 Subject: [PATCH v3 38/70] 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: <20251024-work-namespace-nstree-listns-v3-38-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqzPvgq8cvfhkiBpjKezofOLismZLzb43Jm4Tv19 IaIqkyWjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgImIBTH8D/4xK/nfm8CNXAKz Pyyr+F+if+zD/72Gn0v6j0kw2nQcvM3wP4gvMPFMlOcHH2vZm/LTDC/kpufF35i6/oFl2E5JDbN nDAA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 83908314D15; Fri, 24 Oct 2025 10:56:18 +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=1761303378; cv=none; b=QoZGaUiGSCppLvVWQ1FsvJqacziKKwvS29zrxMOwSpIYOqcKKImeo0jMI9BIm0XkfMwyarZgnMsDpkjFdbAM/Z5ZJ613aXfTMQPnyAdHUctgm+2zeAwPehnZZk8GzQOuJiO7cljsojaj/oy0SLCQ5fbIBTmwykwt2/n1So7z0dE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303378; c=relaxed/simple; bh=16wgRCEaRGE6KnaGWYUsE3X1jinLIZr1ZBK0aXw4RfM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QYG4P4tn+ff5OejqF1jR+pzmgnIHJjKAy+7FAEzxeb8cqSp4jVkIpmUIUFlrcdOrZLttfLn9pQhMWfD+KFpx6zRnIAvwwe/99qAPDm/NfCX8CtNYtEpyg4qaluFkCNiP10EuCJKgsrBlSrrErdE8kSkebKn3f8XyNIIdEuJfTTU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IhoNDm7M; 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="IhoNDm7M" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BBC70C4CEF1; Fri, 24 Oct 2025 10:56:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303378; bh=16wgRCEaRGE6KnaGWYUsE3X1jinLIZr1ZBK0aXw4RfM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IhoNDm7MYHudlbkhVsfUx/mu4yPv3B7LpWedIbsFqk5feOJR2CRLTtpPfGU913rts BnXsbhrrBG61BAiBz8SQXkZzz7CuVgVCCTVF338/JjHpWwS/EisV9aolFITdl8uOiV NSPcpT3BSWvZci1xaqhHxKBZidz3LoPbdEAG4ILj+fNDqCeN9M0gfspQU3CRZE9whS GhJDDxpOOdf9k4/VuTE+x2XBOam1W3CpgebRf2yw+btHZbTEbQajWit1RZzWe1YFkC xJC9kpNKo6CZR+ucuRxGJ+6hR2XNPkcmTFPFiLoxPw3jPI1HNaMIpfpSFCdzIgORxh 6l1D+YC4t/kJQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:08 +0200 Subject: [PATCH v3 39/70] 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: <20251024-work-namespace-nstree-listns-v3-39-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqTFlukG3Fq7pS9f+ubJ933MD15XSttObNk0c+Vk 7ZO05eI7ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIeh+G/77Ns2ff05A9yVel /6T/xenyO87L9py7bcszsfjdmoieVTcZGRbntt+c4mIXu+6T60drrmXBx1sPHolevehw58v55uJ r29gA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() pagination. List namespaces in batches. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 9DFCA314D24; Fri, 24 Oct 2025 10:56:23 +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=1761303383; cv=none; b=cCzzxnvIIup0iwIb+stE5QBhA4OazGB2MgnEYPT38ir/2O7zc6nIM/AP3U44Ugpj54NCXOnaJvv5yoZvw2Cwk1HqPe+04y9fPuOk1sIcJPNJVFA9y9gOYretu162gxaQ0wGoT4WrZ+HZJMp251ROCuW7unBvxHRxFjV17Jh52RM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303383; c=relaxed/simple; bh=UxNNzwwfXU08oQlPAvQ0Gj3cx0fWVzo9FwN6OUP3IWE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=r2HuiAMNT87t6iH4kaiWXHHmFL1xody/L+Fe50EEVCj3qe957CmBf5lRWZEAD0IT70BfxO4I0deXdmsMwYmMBNa6+AWOZTPOcR7DisqaYtn4F6r2YSWvupxQtzQSqOgrjbQ8gbmtccqNUxrbgmYMja31XnnLPKF/kpVIZBobZks= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=o0+PQ7VR; 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="o0+PQ7VR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CD267C4CEF5; Fri, 24 Oct 2025 10:56:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303383; bh=UxNNzwwfXU08oQlPAvQ0Gj3cx0fWVzo9FwN6OUP3IWE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=o0+PQ7VRpTPf1RoflNfIYBzi4NN2upfzZd4YOiX9pG9/MW1Cg5W2+DbhfDwbWMVUo ysiuojmhoCXqCa5YIJihEy/23arASAhoc/EKl+ke30/RvpM9FBQydhpg+qUft9KK/y GspxwRaoLGQVa9Fas1FSOQW73AUAOivTp7tMuBmjARqMvPBhmERuyYca5uvL8OLYWw xsdR6r7ZO1u4rj07za7aYxM4hkyEUBjE9bz8/gwXzXEzeDq2W7C0c1bKXppcH9J9r0 Z3gLygpAqNY7S2bV0VYB0uw+R5iGxf6VQohncdB/eFNZY0ESyx5yPLKAmvVkVR1gLC XUlzS3xU1CAiA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:09 +0200 Subject: [PATCH v3 40/70] 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: <20251024-work-namespace-nstree-listns-v3-40-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpzvhzw8pziInXpH87zF2xWP6op23jjoJ2HH+v1x UITNnGu6yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiI1gVGhi636ReOlyz6F3+b daevx2dLOxGFtC9pZosac8U21nCG72H4pxao1b5H73vDI/GSryzndDc/WzzBcG3etKAMjZ/pzKu eMwEA 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 0EC96314D24; Fri, 24 Oct 2025 10:56: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=1761303389; cv=none; b=r74ZALllefBWN0wF9NE4+kX29nxnolC1PmARec88do0qc8ccUE7nHBLWAEvleNGOu4ECtnFHMOS3MAj99qajo9FLHTdyiGA05UDo2gE1zFLRryJ4Mf8XIHq9aLLvSGg9jsDLqqQ607sb/wC0DCcJTLNNdAqAYTH5bohtOo37KXo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303389; c=relaxed/simple; bh=6a8oUuByWnFcgaLPQi4hm9sjsEH0DS834LqCnnYNmeo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=U6SIaSeDg6ZCnj57lVQk6HeMkQeO4Elcx+DHvrajolqjtq004QLxzcDCY6vTmAfhzFBg5ngHwzHSv84VcIpwJra09UsZtdvoG84LNgLq4q6Vja/FyYxpXP9AzeRe/TuZiDmdkXnztjkuE2fPtA8Ujhe4h0XnCq+Ilqr0Ocmc7SU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tgQq9IHU; 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="tgQq9IHU" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 14E3FC4CEF1; Fri, 24 Oct 2025 10:56:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303388; bh=6a8oUuByWnFcgaLPQi4hm9sjsEH0DS834LqCnnYNmeo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tgQq9IHUKUF9ujC9sgy5JAimr/doRtBYakq0UYtJ/Y8M1aOiQ7pDtYgQm4JEYFtsM yFb/ZctkBLSdTVcVmjwsPOhF1GCrcjBflu8RuLLxK/8rXJG4a7vawWH2SVwCZO0oh3 wTbuBLh47W6y4av4fdkRHQw4kVV9ZwmqUNwO0+HwaL5QB5yFQnAecMorXxj7viQbjX C+HsbZde3kx1miMUPbmjrX2Y5dtvhx8JIewzzuc8U5OVCvrlYeYxXdlxool01W8OBY R+7/hhdEJVs8+YOeTfqOiOGQCXnu7gxaDGv1yAo1VDx4OmJPdmv7LpobSwMi3l0YOm hesTVPBSS6aQA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:10 +0200 Subject: [PATCH v3 41/70] 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: <20251024-work-namespace-nstree-listns-v3-41-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3753; i=brauner@kernel.org; h=from:subject:message-id; bh=6a8oUuByWnFcgaLPQi4hm9sjsEH0DS834LqCnnYNmeo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr7OYsl5+5yrlrhtQfsnORcJ15xuHE/yvZh3iF1p pSu8G//OkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACby8iYjw8OILyXsSqUsW7Z9 mDw5RvpUSJhxesz9l8uSbIMtz83iXs3wv/Jml1HRFYviy/rMs7b7d5UyFPVtdepIa994fNZLm6B WPgA= 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 Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/listns_test.c | 123 +++++++++++++++++++= ++++ 1 file changed, 123 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index 457298cb4c64..a04ebe11ce2c 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -201,4 +201,127 @@ 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; + } + } + ASSERT_FALSE(found); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 242AE315767; Fri, 24 Oct 2025 10:56: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=1761303394; cv=none; b=cRFiizSw2kI7xug5tjfJRi/0r4PYVwEY6BKmJeFBBGeTFCufKUH9BBz13zSvHQSO5SQQuKw8BQhaEfto5pezqM2a1nHU2PiZ7id+GsveCrLIMlPHlsI10eCtCJ+MPFpFWhdtWOSKF0RyaZ52JdfobPbjJIQdTEu+bgRcOmi6db0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303394; c=relaxed/simple; bh=KSlU7UvLSHSGPJJgTeCWtnFjFzuANwkcv8D+4cZnjGE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FqsF5CklcR+EhMlZHCPcp56iJ+xPiQvJslnXKm1uuo6wqOgQPIs9GVb+JcKToVqdUfvqfzBCW1+YyJF5qE8d1tbwxm44m/yHK4hI+TUjJipj++yZbaOYTJjiCnUPp667zY+YeCEBTwFyZH/cLEeOAeqGhO3/fZrw1VcI/akEv4k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YB11ZvRM; 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="YB11ZvRM" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0CC03C4CEF5; Fri, 24 Oct 2025 10:56:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303393; bh=KSlU7UvLSHSGPJJgTeCWtnFjFzuANwkcv8D+4cZnjGE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YB11ZvRMvYVJwEuw+oWADvI56G09uqmppB8eLypjYvCoPmhg16fTH+eFODMGlHkix 95uf4LQEuzG0fGkEV4tFl3joRZpqyRyr1UfeZXgh34+xXieBkkjoKEcEzDmmrKS4TZ cgTBK6kbyTGK6uyJRSw7g5RKSLicD62wSg0ePuYQmJxb+mxrvWtgq8n9JnE9QnIz3T rBwVbjdW8xrCpfV7h4Jb8YO/TOQ524yxhgLXHXgFA33IJ4d1kSc7f7NOHAR6G9OnqE mommNkgTUeSYPiG2auT70/58PYfY5SpAs0DLmOdTlGMkKaUZkFdokWMAVZCt2evA6P sEV3rYbzHM4QQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:11 +0200 Subject: [PATCH v3 42/70] 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: <20251024-work-namespace-nstree-listns-v3-42-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3583; i=brauner@kernel.org; h=from:subject:message-id; bh=KSlU7UvLSHSGPJJgTeCWtnFjFzuANwkcv8D+4cZnjGE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpzEgtufH8nN2LrDL9Px6U2BU1PnnTscLzP5RsHX /isNtlo21HKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjARx0hGhntxnKt0ONiO+v19 OuvPHlvRF1XXmfc9Mqs7/Y7jfvOzbBuG/64VHQ3vim75nZxzoeicxuEGmSfdadwugXO/fK1sOV/ ryQMA 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 Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/listns_test.c | 122 +++++++++++++++++++= ++++ 1 file changed, 122 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index a04ebe11ce2c..f5b8bc5d111f 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -324,4 +325,125 @@ 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 sv[2]; + pid_t pid; + int status; + __u64 user_ns_id =3D 0; + int bytes; + ssize_t ret; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + __u64 ns_id; + char buf; + + close(sv[0]); + + /* Create new user namespace */ + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + /* Get user namespace ID */ + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(sv[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &ns_id) < 0) { + close(fd); + close(sv[1]); + exit(1); + } + close(fd); + + /* Send ID to parent */ + if (write(sv[1], &ns_id, sizeof(ns_id)) !=3D sizeof(ns_id)) { + close(sv[1]); + exit(1); + } + + /* Create some namespaces owned by this user namespace */ + unshare(CLONE_NEWNET); + unshare(CLONE_NEWUTS); + + /* Wait for parent signal */ + if (read(sv[1], &buf, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + close(sv[1]); + exit(0); + } + + /* Parent */ + close(sv[1]); + bytes =3D read(sv[0], &user_ns_id, sizeof(user_ns_id)); + + if (bytes !=3D sizeof(user_ns_id)) { + close(sv[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(sv[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 */ + if (write(sv[0], "X", 1) !=3D 1) { + close(sv[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + ASSERT_TRUE(false); + } + close(sv[0]); + waitpid(pid, &status, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 20DD53126A8; Fri, 24 Oct 2025 10:56: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=1761303399; cv=none; b=QzR6sCfXdtjkIGzJN2EQt6V1DOSLLjjbLIvmR117xXOyiGZiuolI//qZ/k9ZcDKPzmZIqDEFA2hQS2kI38ZuUi07qD5x0g5mP9AqE9UOzyADTQrUII74EZNNnFBTECjBMvviETEMmqp4qs94smuahfpca51byypPdeR6UnmtzLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303399; c=relaxed/simple; bh=QzUkya/eQ/QDDIuBeLk9Y5q5aIl9eBXy2tswIGkyHaQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KxKQp6HOoP2cw8hOt1smYmNsEnYc5WfjrGzhLnW6116h0NRVcK1zcNSwHmxWb7Y/gCDCnJL6kPGET3VjA7i3lf64hPj/Fld/mfiTZIu3EwDCH2Xn23rNSlP6rlz78tpIvUxUftTo3etdb4jqsn+UdbSL+szT7ze/5zzlzbW6FWY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=jvpIkok8; 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="jvpIkok8" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1E11AC4CEF1; Fri, 24 Oct 2025 10:56:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303398; bh=QzUkya/eQ/QDDIuBeLk9Y5q5aIl9eBXy2tswIGkyHaQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=jvpIkok8dAE/P7o2XKUnM32XFAmVvIu0rCu65fgvuQjX6YE68qqqDyK3+ci+wOdUy BvU4Z/EaFb/4fa7jjCrmFwmctAAgbgUdzXxVighJlY27m8Qh5kClB4LjWNn0HTro+Y SRVqJNLPChCTLQnd8roNnrN8f+oYVfzytEtnLzFwvtqY+w7NPbTRjV19Xa4snWlImY amfGuIAMAk7Iy1jaaHboSDWK5/KJXLZm6oRuoE6U53c9DDWX9g1qcnDDyZ/fIVSJt0 tDOl2py0adtzQ+k/FAjuD7JR4pGaXb5+8zrKAbQaF19tPzxH1IiqekcsC23PrgtpyD wg+JhBSstSyXw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:12 +0200 Subject: [PATCH v3 43/70] 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: <20251024-work-namespace-nstree-listns-v3-43-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=QzUkya/eQ/QDDIuBeLk9Y5q5aIl9eBXy2tswIGkyHaQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpbtniNGtfE5zvPzv+3aPWCiilHReu/+W0q13636 apoS+LcjR2lLAxiXAyyYoosDu0m4XLLeSo2G2VqwMxhZQIZwsDFKQAT+XKZkeEhZ+pJI9ljwlc/ BXy1Z+RdfshA+Zd10ZQjsdfFbd9XzFVh+O8SwvZ3xdqnxgtfbok405Oxs0ZA5NbWVfpJeRx+dh1 MWSwA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test listns() with multiple namespace types filter. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- 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 f5b8bc5d111f..d73c2a2898cf 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -446,4 +446,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 Sun Feb 8 07:58:47 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 228EB315790; Fri, 24 Oct 2025 10:56:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303404; cv=none; b=l137DUEFH+JH018R8LbuEOD0Noerd/NgOaEVJ8X+oiW9oy6xgkzOvm0nqt8zPy/0y9myiqW9mHBXjFbEniGK7Rx3YqCjwAAxp6KLj1uvCjZ5LYKt5aVMLG+8bxw59LoJhrN3IXHxFBAJXAyOlT6UfavLjKhevG07jyvltAVwweY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303404; c=relaxed/simple; bh=vycCLgs/SEoxdQIQ6EcoGlOuO/CNJYVzQfqAbKcG6n0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JxT0z/Eb/v9djg2JnLpV8yaOuNZfdmMR4/L21WzaFjHga11j+6eDafyAB0m3hsnyXx6yMaoNWF+R4LiF4DkFhigpgywpHs5hnAEjgrlxtaNipaC9nsQza6g+TSzKRleqWUHVgZ7QdhETCUwTI0K8m+HtyowO3pCRS09+kVGQZAc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Tb5fxbOR; 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="Tb5fxbOR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 19754C4CEF5; Fri, 24 Oct 2025 10:56:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303403; bh=vycCLgs/SEoxdQIQ6EcoGlOuO/CNJYVzQfqAbKcG6n0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Tb5fxbOREhXkPUhu0L4hZCuE2FKuyN2YU77awTMDEq4iGRsdQCnvfIF80JwcekrSA fkjervaqKGjQDW6o3IyhY/ijBC7kOd6yn1Tf6borqXuRgqgNJHPab/cE5TdLsM7eho z51UWpTw7187ENAPj14RXZCakt0wWqSKRHRN2IGDS0OuLou7R+7SIQdtS6OJZ3c5LG elaulD9L7INrKshNc1zBLp5GIbxKbswNh9RTT6tapO5teAuazQ/hh6yB/haHnXJ1ZT 7aY5wwkw3PZwWvo7CLhb2Eh8aVN4fYdk65AZnamxE87UrJasHqZlt9jk36bBmbH5l6 I130OXpO+f00g== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:13 +0200 Subject: [PATCH v3 44/70] selftests/namespaces: eigth 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: <20251024-work-namespace-nstree-listns-v3-44-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=4158; i=brauner@kernel.org; h=from:subject:message-id; bh=vycCLgs/SEoxdQIQ6EcoGlOuO/CNJYVzQfqAbKcG6n0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmoT+Ldtg/j7yRxdD/x0FLkOTNY4Ib0mKcfp+saKQ 49+Pj7j3lHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCR18GMDGvPWxvcEZ8+JfHm 1zoT9+/RjDyRRhc6FizccF1fOWj/IQGG/6WLfvy7ZFV2W0JR713tmsjd+cabpn5f6uyUWOaz7nl eEicA 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 Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/listns_test.c | 150 +++++++++++++++++++= ++++ 1 file changed, 150 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index d73c2a2898cf..d3be6f97d34e 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -477,4 +477,154 @@ 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 sv[2]; + pid_t pid; + int status; + int bytes; + __u64 ns_ids[100]; + ssize_t ret; + bool found_parent, found_child; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int fd; + char buf; + + close(sv[0]); + + /* Create parent user namespace */ + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(sv[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &parent_ns_id) < 0) { + close(fd); + close(sv[1]); + exit(1); + } + close(fd); + + /* Create child user namespace */ + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + fd =3D open("/proc/self/ns/user", O_RDONLY); + if (fd < 0) { + close(sv[1]); + exit(1); + } + + if (ioctl(fd, NS_GET_ID, &child_ns_id) < 0) { + close(fd); + close(sv[1]); + exit(1); + } + close(fd); + + /* Send both IDs to parent */ + if (write(sv[1], &parent_ns_id, sizeof(parent_ns_id)) !=3D sizeof(parent= _ns_id)) { + close(sv[1]); + exit(1); + } + if (write(sv[1], &child_ns_id, sizeof(child_ns_id)) !=3D sizeof(child_ns= _id)) { + close(sv[1]); + exit(1); + } + + /* Wait for parent signal */ + if (read(sv[1], &buf, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + close(sv[1]); + exit(0); + } + + /* Parent */ + close(sv[1]); + + /* Read both namespace IDs */ + bytes =3D read(sv[0], &parent_ns_id, sizeof(parent_ns_id)); + bytes +=3D read(sv[0], &child_ns_id, sizeof(child_ns_id)); + + if (bytes !=3D (int)(2 * sizeof(__u64))) { + close(sv[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(sv[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 */ + if (write(sv[0], "X", 1) !=3D 1) { + close(sv[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + ASSERT_TRUE(false); + } + close(sv[0]); + waitpid(pid, &status, 0); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 E60B231579F; Fri, 24 Oct 2025 10:56: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=1761303409; cv=none; b=OBFK6oTvcDlISfqx1JDup/XnGr+m2WlmNsb8k8gPCyZG0PCu7DEnqUh7H7riM5nippi2zcI3VvnTqa8QCRE7yx4xWTMkuOaMFNWEStCJBeXtxzQ3FUZqRrU4FicY834E7ifl7S2acD8CR+6Lsm8MqjHZRZ/JsHf4qw9xjisDheo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303409; c=relaxed/simple; bh=EesZuqsIPfrlBbuqThECgtbHVtp6afgnRdhVk6MbMkE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=s9ues161jS5XHDN3EV4YbR91w1Sy2o26y1Da8YILTe+JKCOYpUSABMh+OI3OL31RbKM8hd3XY4Jn9W9RPsegf2Xr/BWg/52g9kssyfO9Ws7ZyrssEFiDDhxE1hiywvA1KANAdQslDcNB6DtIo7BoNZym3Br8eW3tBcZIw9VS8p0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Ro+lCC5Y; 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="Ro+lCC5Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 31F32C4CEFF; Fri, 24 Oct 2025 10:56:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303408; bh=EesZuqsIPfrlBbuqThECgtbHVtp6afgnRdhVk6MbMkE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ro+lCC5Yf7Hlct+M1M8L4C0hoBhxgozPARPCSXSmVQ/DS6KgSJqTNia0jJ0s5hXdQ HzDoVMclkyOge60jAoeVQZM3BkYO+UAMtvVcoDQ0wnD6mDxo6CjqSsSo4/VEFAmEo1 J+oQrxW5xzZ3ZsdFWiNTRmXhFNqnlbzn2odbsBDIV12QlzLaQ1+XmspvsR88qEAv4+ ajYs29y5vI92uTrV3woQObuWl4U7zSH2D7W1ta1v9uKWsAmp27bMrLAjdESIe4VUuQ z7eBDpQYorGDdYcoj4Gg7mS8R0dDLK1mMeDco9mMoYgpka1s2y9yUAzO2Sbn3I8/JJ DVAm1cejzYyKw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:14 +0200 Subject: [PATCH v3 45/70] 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: <20251024-work-namespace-nstree-listns-v3-45-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=1703; i=brauner@kernel.org; h=from:subject:message-id; bh=EesZuqsIPfrlBbuqThECgtbHVtp6afgnRdhVk6MbMkE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrjsXrsLrFwTqyUz2S/1ae9H7fHtE2sfb7F2iCs4 NmMw6pmHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABPRdGb4H5V5LWPn3t6TK6W3 hnEZ+572D0me9nLC30Nd51dnzTuzJIjhn2acwo99OisbfN76CxxYnMJjUrtxxiczRaHzVyPf3TK Q4QUA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test error cases for listns(). Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/listns_test.c | 49 ++++++++++++++++++++= ++++ 1 file changed, 49 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_test.c b/tools/testi= ng/selftests/namespaces/listns_test.c index d3be6f97d34e..8a95789d6a87 100644 --- a/tools/testing/selftests/namespaces/listns_test.c +++ b/tools/testing/selftests/namespaces/listns_test.c @@ -627,4 +627,53 @@ 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 (errno =3D=3D ENOSYS) { + /* listns() not supported, skip this check */ + } else { + ASSERT_LT(ret, 0); + ASSERT_EQ(errno, EINVAL); + } + + /* Test with NULL ns_ids array */ + ret =3D sys_listns(&req, NULL, 10, 0); + ASSERT_LT(ret, 0); + + /* Test with invalid spare field */ + req.spare =3D 1; + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (errno =3D=3D ENOSYS) { + /* listns() not supported, skip this check */ + } else { + ASSERT_LT(ret, 0); + ASSERT_EQ(errno, EINVAL); + } + req.spare =3D 0; + + /* Test with huge nr_ns_ids */ + ret =3D sys_listns(&req, ns_ids, 2000000, 0); + if (errno =3D=3D ENOSYS) { + /* listns() not supported, skip this check */ + } else { + ASSERT_LT(ret, 0); + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 4BCC931579F; Fri, 24 Oct 2025 10:56:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303414; cv=none; b=Ncfs9x8vXUyMM7brhZMm1LiOInHVSFMqWnggtuP0ESATXiVYnX4XCCSNoXMdwT9O7L2bFQUGD6d4mGyv/TAC6qR/O1Z+KT7dBzeuaR+4wiXls5HC9mFVyzCSXkJz4ja+KhyZ1fcgR76AExNnH0anNh4u1UHCFLnIjndsnTXNeis= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303414; c=relaxed/simple; bh=pxS104PFU7e80xD7prEOFJiL/3Pdar0FDU7ENFtkjlI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=J6XySqXKDj/gon690EmWao16LtMzt7p00BH01D4qU/EbODr4yGOcyZxSbl2vNqSeuB6OYEW3woCa74H7yji5WuVwSJJqoTbHhuWByRmmV9bPsqwjJJgJ5NxAE9qT/mrslFhXpapcJLYCdyZgY7SuwCTCN6ThD+tYBzi6B/joIsE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=O3VfXSb6; 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="O3VfXSb6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46479C4CEF1; Fri, 24 Oct 2025 10:56:49 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303413; bh=pxS104PFU7e80xD7prEOFJiL/3Pdar0FDU7ENFtkjlI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=O3VfXSb6vibuoqDKsFGACajpbhhLZlXtXe/HieULN+NQb+66BVhrLbMNQ7y+8G3nd zhmyj2h9Tcf8abiszTwynpojdPuDBlY2fM2H+Y2RmIiQWMQ1CbvQyUVHWz93UrPiwf C8YT3Yeffw9cavbSkcxSd6RmdVMyrgetzihr1d6PoYBb5NP/rpt11/S75qRwFL0NNT d85aaoqu3km/wA+bV8YXxPksFe4iM+j0cmjeHqltW49DoVzGF701aIKJAOysb7jUhF cDsvpvRHYUeLS1u6RXhAk71hYsaUIVpbpUOKghKMOOi3akGsVZUoKgWDFPUmhJ+Z+7 dioWButn7jt7g== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:15 +0200 Subject: [PATCH v3 46/70] 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: <20251024-work-namespace-nstree-listns-v3-46-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=4957; i=brauner@kernel.org; h=from:subject:message-id; bh=pxS104PFU7e80xD7prEOFJiL/3Pdar0FDU7ENFtkjlI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqbUO/SsU7AVnWq7mvlV3syuWYrGl3/8H1SSl2Sw A7m+cWJHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABORc2Bk+KTm+yioY6XvmzWV 8T++LxBUnjUjwizio+ZmzeMOM4U+HWRkuK9bkL9Ea+vJJ6uzFsrZnXx71f3ZWp2Q2bkz/zw9lXK 1mx8A 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 Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 3 +- .../selftests/namespaces/listns_permissions_test.c | 131 +++++++++++++++++= ++++ 3 files changed, 134 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..907fe419ec22 --- /dev/null +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -0,0 +1,131 @@ +// 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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 Sun Feb 8 07:58:47 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 6322831579F; Fri, 24 Oct 2025 10:56: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=1761303419; cv=none; b=HOOHFyXJ8r+b29039xGSSYDiUUpIpC5p1UUoJpt5iZgcLEpzd/OGE90VISS8itb6G0DyJ1FzS72yut4VUTyw0X+R0mLijYRUhy7yvO1n3a7UFnaqR7w0Z87gOjI5/+UI/n9I/ufIqFb1A/kHbl+/8nluEstxaKXj81eaNg5fUIk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303419; c=relaxed/simple; bh=/wqqJQoHPy6n2tHb+24Li+Lu21E+HeJSWgV7yWDzDrk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HAxaDyDBLQhmcpAjZbKQCMbYS3/ud5sue+uFMsm1RthQ0Lx/q3LiYlCI7/Y/86lnMmaLFJ/+F2Ej19ZOnqNwPREx2yKY1KwI+JkSMnMh2aT22ZycjIv3vLiKKvAU098NNEAf8rXunO8Bs0IWKtnTe1Whnq6pOdcY6xlaE92fZu0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Gd6JHXJE; 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="Gd6JHXJE" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6049DC4CEF5; Fri, 24 Oct 2025 10:56:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303419; bh=/wqqJQoHPy6n2tHb+24Li+Lu21E+HeJSWgV7yWDzDrk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Gd6JHXJEnkuJyVnUutC6WENomRFprtjaxjP5LCr+on0WziCzD1UrD+sV5i8QXKzXP q32vZMuHkj0OBA+TUSaxVMsuTo7jYnu7og9AtNcLBzHLjE7TL7diCjXX7rX+fUwd0C i40Fodwk8fD3Wh+OZG97N6wL2bU+KOU/Bc9XsMOgp8KTiT+ovcZmErPCS6nDa2TxVt MJexFw51p0nbwGnHBqh6WBLM7Rbs4vqrMtqebKf8aUWUHE1Bp2ux2Bl7FWIDz1kNac umB2qbNRevHT+M0d3vgCVLoclxyI0WsNbfLZxaSLC50+1Jdcd6tKIP95oN7DJ4w/9N kdGb+iLOgHE9g== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:16 +0200 Subject: [PATCH v3 47/70] 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: <20251024-work-namespace-nstree-listns-v3-47-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3018; i=brauner@kernel.org; h=from:subject:message-id; bh=/wqqJQoHPy6n2tHb+24Li+Lu21E+HeJSWgV7yWDzDrk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrXXHeaad/Dg8orr5aVVu0u8X85n+0Q6+cAHs7m/ 10Zd33vdpSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAExkTQwjw5pwV55zp3QFclVn /ux7FH3qlfrRI9euCOqtW2zk+DdL/ibDH67T+6fNzH6ko/xowWTZU7xXinbu9X5VejaHZ2lDvmv yUhYA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/listns_permissions_test.c | 100 +++++++++++++++++= ++++ 1 file changed, 100 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 907fe419ec22..c99c87cca046 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -128,4 +128,104 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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 Sun Feb 8 07:58:47 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 1BE1030EF7F; Fri, 24 Oct 2025 10:57: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=1761303424; cv=none; b=NbKMS14PqGDCNX0MDaRkHDa5RjuAYGNRdCUIaIXFY5r974ykoVhdF1JpqLwE30yAFWAiGYWyTKZU0CuTB7RsyXLcdAzwv/Gn/6RrxXMKey/gHSGKgU5zeFW9/HW2aNrKB3+GuFGmVhxEOFJduHX19OCkSi5iyM0eUYaGWTCTUNs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303424; c=relaxed/simple; bh=BRZDSulpqgKAoYJKytoqb4ZSZJTwZJCYiydXZiVuqVY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=VBxO3mWXlzF6AVq7SBYPXlfaOPaCDLgNYlrzP980N5APmT/lPThSDEsyNpWfA+qu7e/mSXKV/R8h1fASlabuIqCvIqsBw/qHZR23RnlcOZAjeHBRCrC1DbOJnfEJ7ww50kyMhyW0JeeKAq+dHdLVm0+w1pu3XMzUDmQHYGOCrCo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gjAXTWqJ; 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="gjAXTWqJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 69008C4CEF1; Fri, 24 Oct 2025 10:56:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303424; bh=BRZDSulpqgKAoYJKytoqb4ZSZJTwZJCYiydXZiVuqVY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gjAXTWqJcMc42xdPkJpt4ZAap9o8SP2d0RtgE8tIHCU0d/THlGNyRQ1hOisF/ht0f xcb/wSaajshO0Yx0T2SWxxlmonDCgtgQkuofFzl/Z1ixYjO694AWy64go9iMnP1VrT lc+DJ1r4960iuYYA8RGHDRhMdFHnxC4K1j4u2wI9ipI+fY8otbUuLluwCtGZwy55aV 7O7lu6lPSQUPEaDQeEYGr88JkqaibrXWKmYI2/gBdoWnMYXJHkTaCAXOEfbPLUvx/J wRswrQr/3si+aeua4uWovMcWsI9vrkugFCQ2W8RYrMVBtwVe+f17uF8kqKXJPa6V9L aKo9HMm4jAMzg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:17 +0200 Subject: [PATCH v3 48/70] 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: <20251024-work-namespace-nstree-listns-v3-48-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=BRZDSulpqgKAoYJKytoqb4ZSZJTwZJCYiydXZiVuqVY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrf+VT/TnD+ra/p1w9duDjf320Vm+Vls3nbZApzt D4cn8O0u6OUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAiNXMZGZ4z8ksm61xmL8hM YePPeXvKZ/XahrmmfCL20TftP/lx6DD8T6169IjBI6WC4enUZ7sZ3zXOapr1U0DpwrNFSzcddu2 t5wMA 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 Reviewed-by: Jeff Layton --- .../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 c99c87cca046..aed7288c7eca 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -228,4 +228,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 Sun Feb 8 07:58:47 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 323BD30EF7F; Fri, 24 Oct 2025 10:57: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=1761303429; cv=none; b=im/w9leOWblsv2qjLpWf6qY3HFTHbbLUSpZ8uwyQMap8wddthddVwYnCXpwMOkBE7zmtKHi0mH9isWRF9mea42xnwb7g2XxN0tDwzuwuFH8YoLKc3jzrOHjsnM3GyooudbyOSFxLI0ySdSvyiV/yn867Snq7/GDuZmEpixhvy2o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303429; c=relaxed/simple; bh=2cVn/rLMAtz+rjww4mseoVKumw7c91HQOHzmtSbA+4Q=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lTKr1i4fvFGTkJmK4nmuZ2YahKnPFtRNEBpG+QeBfp/ILXTBnnDIpJn3+hngPTKhQ/9blyq4JrQ+PkBw4oSbiXGsghWxd1cjp47MMcnQUUgCTOa4FcXjustlL2DN4jvQt9XrNJJQJW6JBB1mMOPujPCNQpV1M7+8C/96Hy7RQK8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ru3VUShH; 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="ru3VUShH" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6EB9EC4CEF1; Fri, 24 Oct 2025 10:57:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303429; bh=2cVn/rLMAtz+rjww4mseoVKumw7c91HQOHzmtSbA+4Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ru3VUShHYsZpTSVDRaeplR+ymH83SD+Tplx1TbaCwg5S6fxYsoSdC6U0jJ8ArL3Ku W10JIlQBkuMase7d/ATKcU9bBnfDFQWPhY3gXVdJBMXxU8v+yZtX2Dgdb5YTgmMBlu XFZkMIeijfarbZTBx9e9cb0GokCbT+Moo3jKuFS8YEp9pyrjjUu8yC427mXg5XqDe+ TDu2LmL3vsPkcP0neEGK11Y7SnR0HMV2volJScW0T2Hx/DmqWty3P1QpVRTKbEKsX7 g83G3BTYFnJP6KynMBYHlrK6mHx/FcO4giNc6Gh08pk8s1DTXp1bIJAl2ydIB8FIWn d/YboHjz/LpAw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:18 +0200 Subject: [PATCH v3 49/70] 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: <20251024-work-namespace-nstree-listns-v3-49-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2498; i=brauner@kernel.org; h=from:subject:message-id; bh=2cVn/rLMAtz+rjww4mseoVKumw7c91HQOHzmtSbA+4Q=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqPPhlgffhosnd7sEz+wcn8E86KqLOJB2rtirZ7t NiLfVZfRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwETOGzEyPHzvd9DOwnxrpf7T Q4GFZY9Vd0c/ZP9z+nbixLVv4zRmPmNkmBinqngr7cfkox/7A7//E+Gqc50665LT04+bRWujN7n bMQAA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/listns_permissions_test.c | 76 ++++++++++++++++++= ++++ 1 file changed, 76 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index aed7288c7eca..7727c5964104 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -366,4 +366,80 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + ASSERT_TRUE(success); + TH_LOG("LISTNS_CURRENT_USER returned %zd namespaces", count); +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 779B4315D5F; Fri, 24 Oct 2025 10:57: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=1761303434; cv=none; b=QvOabAUZqP7OpQ+/PcmTc8uPJzJQfmifp6bNtsGIHIPytkdmAEjKspJ0CsFdJocCFdnOGYs5tDT2Ufr3gwsZ/w3homzmAA9BlN8LvSlAi8inCYB7wKdWFm55+k3ur+37gB2yDCL8JWgIn5qjemDftJ12/YUWuD3q7CnBz3RjmhM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303434; c=relaxed/simple; bh=2cIPwZqTW4MWIZYsYx6FhB5M6WCZGsZgp86akiGTfiE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=lhqE6nzoUpqYnPkQ27FwuY1QYfOX0CmRHTb9o4ynW4/Zb08YjkVyWbXAYt69nHvtD5nYKFzaL0wxGheK/vJ7c/kFVV7Oody/sQYO8DOC/Xa1yvcrYerS8BEuUELASKLolQ8Tp7O8Jz/sImjlYs7R5ZT8mexADP37Xuz2xETp2Cc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=JuawUr7K; 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="JuawUr7K" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83BA6C113D0; Fri, 24 Oct 2025 10:57:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303434; bh=2cIPwZqTW4MWIZYsYx6FhB5M6WCZGsZgp86akiGTfiE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JuawUr7K8ktut6eWXmAuBdE3hkBdUxsW4sEInCknZW7mlFej4Z3g//UvORgsQaVP1 FmcMBP9T4mede1HNQ0TY/pcNVUZQ95r2v0g8FfSSojQkRwWi69EcnCUGYKV6EFKSE6 gsUFr2YczhlhvvMi5NU2j1oiPzX5jPdSPUvn/OVBrFLWSYcI/X2XyYk+NEOMOS6gK+ az27IEHbabwQ+qAMkeUFhCAlxEMfU5KWiNcpm77D9W9N6oICp47hpeuRmx2pKa3Yym 9ID0qAluhCBOAxVzAzgccELXFhOM7p5KrxZD7G114IYOyZ4O4TyJaliY7X3p6aWjiC vON4sSkCkEKSA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:19 +0200 Subject: [PATCH v3 50/70] 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: <20251024-work-namespace-nstree-listns-v3-50-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3453; i=brauner@kernel.org; h=from:subject:message-id; bh=2cIPwZqTW4MWIZYsYx6FhB5M6WCZGsZgp86akiGTfiE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp/uufOryq9U8u5F7aeL3u1LNps2sk17P/dS63NJ BeebWNK7yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIhz6Gf2arf72qsayf5sz6 wjGgZq1Iw2k2rcvvPUzKJybO9X108BQjw+TNC3f5xB7dFjv7TT2HzpWfTxX+WR2TNC6JYP6j+Y/ FlgMA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/listns_permissions_test.c | 119 +++++++++++++++++= ++++ 1 file changed, 119 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 7727c5964104..b990b785dd7f 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -442,4 +442,123 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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 Sun Feb 8 07:58:47 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 9CF8A35770C; Fri, 24 Oct 2025 10:57: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=1761303439; cv=none; b=L5nUk4JN2lAQXG1WBYLjw2V8jGESzoXavuI2YKr3IbrD3oRldrognY9Q6ulru9nCYOViKcYpREn+VE8zFOfZrGKO0wbh+3CsuuDhPFG8ViTAPsHyA19GDGBU9nwpM4bGqFdymGKAE6tbzfx2JgwvC8SNgYyAVYZK3zb5BMio7iU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303439; c=relaxed/simple; bh=jlxGmvG3TRBGBU95oespXIKDq7FaoNyvL6StJ8L+zuI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=c9mLpfSeBizT5DrBH6k0VElfFTqOF6WkKkPKHgyo62F6q56ke/8YSrQ++qTrnFd9hDjkfUyvOVtjLxrYE4E+GhLbM8ZPkSvBmAa2gh7MA1+a2hsfMZzbpZ74tuI9h4nt0i4BloQtQ056FsOMEwqYZEpHP5wJp/00M2pIjCyNj34= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bSJq/EQ9; 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="bSJq/EQ9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 83647C4CEF1; Fri, 24 Oct 2025 10:57:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303439; bh=jlxGmvG3TRBGBU95oespXIKDq7FaoNyvL6StJ8L+zuI=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bSJq/EQ9DjhEx3MRYq3pOGAC6ltXmTCFdPlaUN28UNpASiS28VRMD849WGQ977mvp s7afflNINQY3HswiChPKwFjEby9ZOgDfGz27YCjtBA4/UD33ZKvOpEGDMpwHXUW0e/ cHpBE5q+O0c5OpCCkwjyzJiAH4Ajrlo+3oheQ0rTr9+NFltT3RpH+S9s9NuMEjaF/6 rFXffrs1PQBOxssIJ5isXyA3lkPbC739yDvQd7qJ07jrSod5103cXTBT9FxI3Zbc+R Yt/5XyNETikpNDQh8PaqNkd2eLqr37K+1C11cNSklHfHWtwP8ERSmQLPT7IifYWe5v tMqxt5W7eapGw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:20 +0200 Subject: [PATCH v3 51/70] 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: <20251024-work-namespace-nstree-listns-v3-51-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=2646; i=brauner@kernel.org; h=from:subject:message-id; bh=jlxGmvG3TRBGBU95oespXIKDq7FaoNyvL6StJ8L+zuI=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqf99BFtPul0/WsYMfJz8/+XK8yo+LPZrEDTUdcq rqm7kh37yhlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZhIYi8jw7IJrJvlqu7qRa/4 GPT/Wl55Tlv2TNV9VqrLSvSmOlSKxjIyTEl4IGiZJVSd+viOfVZ2TtLv6qvP9wqW87uf+rz486a PbAA= 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/listns_permissions_test.c | 87 ++++++++++++++++++= ++++ 1 file changed, 87 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index b990b785dd7f..9aa06ff76333 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -561,4 +561,91 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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 Sun Feb 8 07:58:47 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 A80C4357A25; Fri, 24 Oct 2025 10:57: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=1761303444; cv=none; b=ZpcY5PBK4JzJ1XzmGDTlmrrwImXRHmNdecDofA5t3itZJ2+UrkfaJY1Q2pDQB2bEa+D2/sgC0MP/eunHueWXEnUmq+2cT4nHvru+2sVVom5cDQHGFoqmvdgQmpgei2ZduZPeyXBgIujaf3/UV6Af8XuwDLKgygGx960UOah6or0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303444; c=relaxed/simple; bh=lxk3HyfGnG2LzFtd9uD08385YY9HWIbP9txgILZ5aFQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N9kMcPazL1cmahp1L1yFBc60mQGx06jhsOSsSFVS2kEKc/vACLkh5u1RfMz0KCl/PLjTWJWYn50isG6TseXY9rc0nRhypr488HM3bs2zzYJpETIiKT6mvNiCMm8DRZ4lm0fCOXY/HByH/BgzPKS4RXVeKzcXV5IPw+8JdwDQ5Tw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fKaD/dhS; 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="fKaD/dhS" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B148C4CEF5; Fri, 24 Oct 2025 10:57:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303444; bh=lxk3HyfGnG2LzFtd9uD08385YY9HWIbP9txgILZ5aFQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fKaD/dhSXHJfBpSm7rd2BGc5mSjkqujo7rCWjxmDGP9hkBA8yFClgyPZpqVB8KCEi 3Np7MlSfdwhQOmz1uh2jpK65XkSyuahWdsGRtvNavXWOFv3QdIxa4KNH3M8A7zgniq ucFY3fFe4JpTu4h5Xm/ZggeRP0MIPNpX5P2Ttj0Wgf+kgTNy154Ax8inFsjE6N+dC1 E5fa7Fzd6GD2kCKGC+owyG/JJGRmfCxz++RbdfCbyadJc1PUTpkCBhIf24+zRhNE2E BXPVMTIwQILDIMh9Y6KphRtGQcdf3DeBjxit79BQIBwJGeu3DBB82Cug5FtmZOJQvq wOiAILQFP7F8g== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:21 +0200 Subject: [PATCH v3 52/70] 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: <20251024-work-namespace-nstree-listns-v3-52-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3491; i=brauner@kernel.org; h=from:subject:message-id; bh=lxk3HyfGnG2LzFtd9uD08385YY9HWIbP9txgILZ5aFQ=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmr3uGsoc2b2i/6a9qn3Gmrm6C0ysHDXLs1szYl7Y XP7j5dfRykLgxgXg6yYIotDu0m43HKeis1GmRowc1iZQIYwcHEKwEQeGTIy7P632urKvIwVVXvO cSnHX3N++WNCjNH+Vo9nYeWnX07wNGX4p6ew4gNXXX5s/6dtzq/zLp+acyoxo3GG5fFXp5VvCd2 fxAkA 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 Reviewed-by: Jeff Layton --- .../selftests/namespaces/listns_permissions_test.c | 108 +++++++++++++++++= ++++ 1 file changed, 108 insertions(+) diff --git a/tools/testing/selftests/namespaces/listns_permissions_test.c b= /tools/testing/selftests/namespaces/listns_permissions_test.c index 9aa06ff76333..82d818751a5f 100644 --- a/tools/testing/selftests/namespaces/listns_permissions_test.c +++ b/tools/testing/selftests/namespaces/listns_permissions_test.c @@ -648,4 +648,112 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + 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 Sun Feb 8 07:58:47 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 BA68F357A23; Fri, 24 Oct 2025 10:57:29 +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=1761303449; cv=none; b=jy/+QNgQCJ+BSOVcIMXmy5JJ3hzRpnXTbHQ0R0fUUDi/HqKc/osKPw00nET5IdKKhBkYEe3f1x6fPCUIqNiU0oGtZD24aqsr4vHE3IMgZnif8RHPNRdoToH82S1H6m283gxsdznqhwgMUrj6cuNli4+nk+e0K0sJSZXVW/RW09A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303449; c=relaxed/simple; bh=YEySNnwHHlcAx8fWB+paH4j8S+yvwldW7xKcAutT9lM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Hh0XAYD+NL3uPENovZZ4bsSSy4yMY+GLtfl+L9Ln32TW9PxeCD2+FJO4/7SgMHE4P3cBNf6RFjw6aHFzMiAsUI7/ZncjYgnJ2+JGrlOngM7IvRha2IutkBzNdFAQbI0bVxQFfcRH8V8BgbYNHhK8yWNHrKNUh68bZD4BZ8UIQWk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=CyEyAjsv; 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="CyEyAjsv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id AF417C4CEF1; Fri, 24 Oct 2025 10:57:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303449; bh=YEySNnwHHlcAx8fWB+paH4j8S+yvwldW7xKcAutT9lM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=CyEyAjsvDE6bSWNT9alXmGqU4mh8gU+yEmnb+hWeVEjaCVXgT8TRm2foUjlXC8RYo 3Wh3lFfRGM3CLHW1BFmRdgYomxy2377xVGVoTDMKp07v3/x/bbmAqrMpJid4q7j690 pCDUt74mBtY9n7UpwuAvji/zvJF/lKn7hnuJgMSHew+3a1ZzekqRjaQI6D3Csc3Kc9 yz2xAb8KsJganplYvkpBKjC2YU2Gu+YVFQeX+tnUCXCk4B/L2UmUb3A+7VSv8zsdu8 X74jsiqcQtGmjZ3K6Iuw9rDR2RKbScDleBi1yLKzKEoKHAz7WBa84fq22lDV2en9It tAZdJ6kyGuDiA== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:22 +0200 Subject: [PATCH v3 53/70] 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: <20251024-work-namespace-nstree-listns-v3-53-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrnlvfYdHWK0KKXaSmvzbsm7FtzS0JMv+/Mo6AE+ 2XrwhhZOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACZyP57hD3eo06+rrktzkiOD MnY0uE1otpjN0nBjlVtvb2n8/t8JPowMzw/evln66Ie8cup3Q/OtWgV/ToleUH9vNuF98fE6r4x WFgA= 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 Reviewed-by: Jeff Layton --- 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 Sun Feb 8 07:58:47 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 CD1983161BA; Fri, 24 Oct 2025 10:57:34 +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=1761303454; cv=none; b=Qp2S/1YsvI8BlvKHSy0Cz9XXP3uhFjnBIWZ6EIrszQ/2XMSMGTl+vmBm0yteur7gjNiE7/OnC9EB+NTE3ADdld7jDtY/pnuJMoHh0rZM/TiwBV/TOnAZDOhm6bXIcD1Cy2hFOC1qvl2YIknJSXjylrr2pZrXCesM95BWQhLAEqg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303454; c=relaxed/simple; bh=M5JYL/ItXnif2Vw7+GSIT6vFRcZ0KyLdqVkykps56SU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DJh446vXcxkSW0tm67ydxpc6oqHGmCBPASsV6cV8/Ht5wZOfgmSq6KTSTzqIUoN0j1DIRtbBwkvXLpMph7eO+vp4tEeW5GV+qduLxuiDRJKW2xWhJ2OTmwIEv2q/j6RTrs3n6KzPKODDHRd3TWPsA9xzdXekfkthoOiVw5UWDaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=ew7Zbyny; 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="ew7Zbyny" Received: by smtp.kernel.org (Postfix) with ESMTPSA id C606DC116B1; Fri, 24 Oct 2025 10:57:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303454; bh=M5JYL/ItXnif2Vw7+GSIT6vFRcZ0KyLdqVkykps56SU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ew7Zbynye8xWvABfMRcc/O/Duy3HUO61LC0x8VCMkyVJi3inR+S8fKmLnEugrtElC sOPAXgaDN0ty84MNJMOEV9D75EkS7/FFg8wi5T33/jFKnB2lJk522AfiIiL+SXZgYQ TVQs3cTEqBFko9aF+XNbUzjH0y2EdbXj3upvXivfGm7unqdZz3AbSY/6vcre8ug1Wa RB/USoHaHAAe/nEKtcyXun7HNwDVOqJwF1ETDjXKQpH0LC/LDEB9ZTNXtVNdrLZ9Jd GFdV6tGZ9DFJeCJHOlYS5iUXA7S7BaSe0xkIrRzvCXvzzAX1rFPnqLWw2N4x1YSr49 W3ZBQGggUU/LQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:23 +0200 Subject: [PATCH v3 54/70] 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: <20251024-work-namespace-nstree-listns-v3-54-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp/c/V+uvgOlzqDH/fj1k58HO8hOlXv0YktqiYTH J25+EI7OkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACbi5MjIcHn14uu3r83Ne2AY tObwaueveg8/nn6xyUvFpmrNV3tN22kMfwWULH7al3R+se/K3KOVunv3c88ZgWs7We74ZqrsZ+n hYAcA 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 Reviewed-by: Jeff Layton --- .../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 Sun Feb 8 07:58:47 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 8F7473590B4; Fri, 24 Oct 2025 10:57:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303459; cv=none; b=RpGMEqgvsg+UmnFdj/AMLvG7NjdsViIZbgjFVfWP+tqpPk3DSDkcD8AtnNhFXDza1NpahSm7DnOHa/ZEAi2hAf49Q1G8kuoaP//04Lo8nf3LyVkI/VTsdiF0GY0Kn7DkAit0dxyU/XXkzyHR82mf4IHsw5Y5Xx3RWlAmx+kq9Eo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303459; c=relaxed/simple; bh=Jefh0E5wrR69nQhrRe8vhHFWAuKaAVI3adTXCV7rO88=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=P5Z3GfmG6yDpSJpYydjJjPz3eZxTdD4WKkA0UNTpVWBeWOxuXV8IhK5iuly3wrX5YK1Px8JSmfj/HateyXdSIBQPLAKVt47V2b38nKR+IUhiRLtpie77MhZH+ytMiKKaVR6HnDFEsawWDmjHtPGz9Rn8huncQ7pZnTAtRSgQY6k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=G44AQ0rv; 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="G44AQ0rv" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D9918C4CEF1; Fri, 24 Oct 2025 10:57:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303459; bh=Jefh0E5wrR69nQhrRe8vhHFWAuKaAVI3adTXCV7rO88=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=G44AQ0rvIRzBP+W6LESmvu3KMQo/1PVUQOZb99S29fFu7dnfDvrpbNnvI2Q5ywGlZ Vu4MUqTwZ5BR0ye/iWdyu21Og/5oe7upd46WoSbNSUANmNF/yl0xbb1co96KYk6CDo mR17NBQqNMv3MY+CUJTkfM+KJVn4FZNzhpuql18e9dLN7a+5Ua+g7gjtyk3q+m3rE2 16PIWX1Px3tl0RxoVYKxYTaAzQWtZW8jIHWb13q38Ebg6LCjhRpxr8tqWmrBiwGKgo DqnzHM06GXlWo7YC25IWkZ1Ub8YSa4o6PvGHZxZBjJIgWT/WI1rW9AmQiwL7A8pH1c V1x8fjTiFul5A== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:24 +0200 Subject: [PATCH v3 55/70] 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: <20251024-work-namespace-nstree-listns-v3-55-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=Jefh0E5wrR69nQhrRe8vhHFWAuKaAVI3adTXCV7rO88=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrfU2Cd+na9HytbkErTxMp7+2/697u/c9o6T2j9Y 193+b43HaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABNZ0cfIcOHPXPV0lUCv+YqW aXsNEmyTKoK+lvoldC/viSk8q1Zgx/C/XOum++fkZ9+uaMr+k/d4enivjvPaTkfVmFMWjUsehp3 hBgA= 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 Reviewed-by: Jeff Layton --- .../testing/selftests/namespaces/siocgskns_test.c | 65 ++++++++++++++++++= +++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 0ad5e39b7e16..02798e59fc11 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -163,8 +163,7 @@ TEST(siocgskns_keeps_netns_active) /* 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"); + ASSERT_EQ(WEXITSTATUS(status), 0); =20 /* Get network namespace from socket */ netns_fd =3D ioctl(sock_fd, SIOCGSKNS); @@ -195,4 +194,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 Sun Feb 8 07:58:47 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 9A109359F95; Fri, 24 Oct 2025 10:57: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=1761303464; cv=none; b=tXpn3MKK50CrBSeQCucYJg4uyE71ciPc4XMAT1fYthBWu/YUG/Ct9pLTuo6wooQaE6CgNrmWL+/fmHt25ZIsZTED1jGq7h5TM3IiK9OoPe5x73dYDGkIVeayC7SQobqkFCWdIqp/W5vKhZGUWFRvb4pNol9onDmXDHX3571I4jM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303464; c=relaxed/simple; bh=BCihYefUNETnf9SgrifE/6AmFo1JxPKscMdQ4tQ9EDw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LQRjUHPg0arOnOPidHNNC+K8qrpv/i5rXAcf/Z7eqiLpw+b4iI2DAjOa0esP1BPlCDYM9OC7peubYXaF3a4uR/KDe0lfmhfrmqkK1iNoxxUH+18Sa0k5HQi16opcUbShN0pL3SQeXCJAkD07haPTqoq0jF8MNFoDF130xKN1xkY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=nNyb7/5D; 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="nNyb7/5D" Received: by smtp.kernel.org (Postfix) with ESMTPSA id E243EC113D0; Fri, 24 Oct 2025 10:57:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303464; bh=BCihYefUNETnf9SgrifE/6AmFo1JxPKscMdQ4tQ9EDw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nNyb7/5DUtDexae+j+ZgdLJera/saAvPv6qpaToXs2JbZ49bim7ADeJcqib15NdAj 6y03rXzSp1UVNnVftKGUWpA++RGKDhylYo87A0cF47xjsV18KanTQ4SbsJrBR+399y BPHAE2w1wEu1pWei9YYG1gh012LIYP0A2yV54lwSxnb8YjobJcL6g+AokeJdH2Umlj m9yfZj/9WwVemnMP/hlijWj7LZ7VfwRhxs95EiFaHd1mYHBdop2yrgqRPe1bj2c2dO x8L56CXj12Xnt1jLIhKGqSvFHN1BLLR+TfNw4Pa3S8Rephqo2bZUZtfx4XFnQYqFt3 Sm6Y8TI3Iv8mw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:25 +0200 Subject: [PATCH v3 56/70] 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: <20251024-work-namespace-nstree-listns-v3-56-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=BCihYefUNETnf9SgrifE/6AmFo1JxPKscMdQ4tQ9EDw=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmrX9VjosO/Ha9YF8pu+KXleMwgvtX9578f1Y+9+C ecq6ZvN6ShlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZjIgnBGhm/Km7jW7jn9aHtj x8EnZTOtJ/QqvAg4Yst25kxOydf9tYaMDL82FV89fd2+7QDD/6ofP8/MnLtgZ+GKZ0Vfn9YmJqU vC+UHAA== 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 Reviewed-by: Jeff Layton --- .../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 02798e59fc11..28e45954c4fa 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -256,4 +256,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 Sun Feb 8 07:58:47 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 F1BD231282A; Fri, 24 Oct 2025 10:58: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=1761303500; cv=none; b=oI0EQFcK557esJguw+1mRKoFB7Jbifnv0WLOsM3z6oHFdoWw3LeAbTCHNTmy5qqxjmGpwQI8hIXZLVpoHp1emcajGYTuGHoOEsMFixgnFmu06qULKd96xsqAbGMbm9nzPbw9qf0VVOgKb/Nf7Dw69Kk9x6FaQNIOT8hOGDYEk6k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303500; c=relaxed/simple; bh=KWYYGboDUt3swjKDxkebVx+xZOw67uWV/kh+IrzwFAE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NUR1gCveV4ADEg7DQE01Q9niem8rqj+c1B/MKVxTKRZV+CHwP25fiSQxNsjaGFh3wsr3l8lO+0npePO9q3EufioJPgL5TizUzbVXZiFNLa1CUYYyCoxXxbfvxgCUl3Q8VITD9U26euBskMcxxugv6izrDWpSTvl+MyhI7cxVfpE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Gz9HEOvN; 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="Gz9HEOvN" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 2F3B8C4CEF5; Fri, 24 Oct 2025 10:58:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303499; bh=KWYYGboDUt3swjKDxkebVx+xZOw67uWV/kh+IrzwFAE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Gz9HEOvNP4UjtLrocwrPt8BN+4wwQQT6254IgZSkahkgx0QcMzIYlodjNjs6bwGeS 4Y7r/PuS68T1GBPy7lpJxbRiTOxHcOW0EYKiO0fmFnObCOa8klxU74GSAP8TzbulTT Y3SLgEmd8YUWgyP1xer8xhd8/3LOVKJ1Jq2EVNBkYNvVLZrdAX8fKQFx1cYkXQBJVH DDTmDbHwoibJ2WbS1mpH+ghMXP5N1sSEUsMmRzYuH2tcv1Nd4hIdDx5FHxwllyf9/u 8mGx77clhg7Ezfzzp3eY2RDOKwiUsL4M6JDM2FOdcBtLNt4LZGmm86BDXTMIKqKs+7 TlmMZfIn9Cq1Q== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:26 +0200 Subject: [PATCH v3 57/70] 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: <20251024-work-namespace-nstree-listns-v3-57-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=KWYYGboDUt3swjKDxkebVx+xZOw67uWV/kh+IrzwFAE=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmo3X8M4RWJr04KuI0uW7t9zapLQ4bWsfX4lH8MFD y22rmPy7ChlYRDjYpAVU2RxaDcJl1vOU7HZKFMDZg4rE8gQBi5OAZiIyDGGP5wa2U26v6S3Ono8 4rAxfRF/sKKspPD0PStBlUOK+v8sXjH8lTfg2Lfq/v5jPrMu9qjumzPjcNOUxRnFPTN7so6s73y /hBcA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test SIOCGSKNS fails on non-socket file descriptors. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../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 28e45954c4fa..bbfef3c51ac1 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -307,4 +307,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 Sun Feb 8 07:58:47 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 3E80A31691E; Fri, 24 Oct 2025 10:58: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=1761303505; cv=none; b=QLZsrFVfdQEwmPoV6V8UMmMeNtZasW+mCeixSuwCRxX+jUyMSf4VyOX0tHoBIKANHHChDc3Y+ph3bM8KX18jkpqvIp7aB9/t+f4UM2HWhC9SMMo1+/KBu4ldRy8OjA4onmd7cZxS9foelsZiNJ5KwfACtyhM1DqjnRq6teB6fCU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303505; c=relaxed/simple; bh=m+pfjG9qzc5y9QbnPIMpZwGVfopUom8AcMnRPDQcZaU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sSQyFtw3sXZ54WZVNG9Ypz2K1RcYcZs4+7TSMSpNzzvCx0Kwbe+9OPMk9nKNnfx7d28gDqAe8Ixi4O3HvHCUbLvI1M4BUr2dp9yNNber6AyAUL+DYm0zGdheCR/sI5P22FAWsoaV7y+I5kmo7NW8uGjCUX1ZwAyWMEKlvja+ufg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=UBSgbyc9; 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="UBSgbyc9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 46E09C4CEF1; Fri, 24 Oct 2025 10:58:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303504; bh=m+pfjG9qzc5y9QbnPIMpZwGVfopUom8AcMnRPDQcZaU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=UBSgbyc9LNiC4nk00FHFX+8vYyMCbrKgtFW3rEtRKzB4FO62lN75caEZUdKCyTiyr TN782lYpj4Jo8M7OLYvNUVExX09PcbJo6bUZJFDx4gpdf3q+qd3k7LP3wupEmR0M9l aY7UFb2TmC3cfb8JRRv4JKR1FJ5yWzH+A1AFQI/o89mMWEni/wJ0mza+1Gn5aYOvdc ljO+00xGL6gRSkTbJ3rPcA3iYNcYn7EovBGt1IDbZcJBHBlYegZZ9KL7amuaxqjBPH KEgSaCE83mRPRZwRpXV2IDGVJr9eUqpTUkQe9Dk03cd4Tid42NHQEiQVWaTmy6sBgk u1xsy4i5yxPpw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:27 +0200 Subject: [PATCH v3 58/70] 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: <20251024-work-namespace-nstree-listns-v3-58-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=m+pfjG9qzc5y9QbnPIMpZwGVfopUom8AcMnRPDQcZaU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpfmsC9wugtd4HeA82wlXISnN/X5/hHZEcGJ1reS XRln8zWUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMBF7LYb/PjtELaZHf/+2Jdh8 rnGJuH+7x9q09Xd0tusHl1aU+tSvZWR4aL1Oq/RD+d0Ec85jvEbdxo2bJzBcNtcSMF7o9G3SvCB 2AA== 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 Reviewed-by: Jeff Layton --- .../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 bbfef3c51ac1..231830daf5dc 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -333,4 +333,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 Sun Feb 8 07:58:47 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 46D1731283B; Fri, 24 Oct 2025 10:58:29 +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=1761303510; cv=none; b=Ce1tUpZY0AUVoLro9Ja00uF7b+NsbyVSxOxygvffSMgoyBLVL1vbQyeu8lbXBagh1cHfcCeA3061HSO6tt1SotulTPjSjAlDV1fRQwlfbRkV/n2k1F4MgAjYLGOylzOl5jFeFomWc9jgOSLQ3gOoyUpVHm1woEYWudRFFCbedQ8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303510; c=relaxed/simple; bh=0F9mhX2Gl3SVx+//eDdT9Tj87KVi2B6yYobSD3BfDnA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=j+eFVIhaQBf92wZSxZgQAL3NN+/07Zh17IjKrU2i03MEbkQLI7QAs3wvCekIGdJ/TVg+REXNWRbV5AmNc00c0hTwGMxnLz5IIIOiSkM7D8RoyqDO816lAH+jSgXLye/+xJDR6kMZTeE8Tu9fB0mJ8ddWigRVXtRU1CQhxUv/lBU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=IEF6+UgI; 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="IEF6+UgI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 50F21C4CEFF; Fri, 24 Oct 2025 10:58:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303509; bh=0F9mhX2Gl3SVx+//eDdT9Tj87KVi2B6yYobSD3BfDnA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=IEF6+UgImUHAMjJgAitaBvd5OziaZdCqrfvP98/19wMazlvfUTqkz6UQU832nMbPh JlyhuZd2tETtISi72czGm9CPTocRiDEZ41LnZEQxIdO3PKghV26q85rFcN+0J6pnza iLqHIU8x76ElFWF61clouBwOk2v6VnHp8QvpBvcm9hUa9dAiP6xLuXGz3lh/mzanOQ OuGXvqVtm8Ttcg8/xDmmoNLhwDjfJBIlv1eyV3/h27vhFWRSqtrdjKlC2U9PpS9RdT ofmYGVdRGrEtEkHW59ZgrBP8kxaeW00Kt1XHcsB9l445vMsaiYIcYdAw6JtSMsqerg OrR6N1hLruk7w== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:28 +0200 Subject: [PATCH v3 59/70] 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: <20251024-work-namespace-nstree-listns-v3-59-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=0F9mhX2Gl3SVx+//eDdT9Tj87KVi2B6yYobSD3BfDnA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmqf5c3O9r02/2cqS1FOCcNOfw/jL8e9Fm631469/ Z23f8fOjlIWBjEuBlkxRRaHdpNwueU8FZuNMjVg5rAygQxh4OIUgIlUqTL8U2fVZtM9lynxfdrX tGXTjgq/ZUnIzpm7qeNM30bTS05BDowM82Md5Kwr8gO1SxmnWDh/msqpZPzMalvQV+0VXeXOk9U YAQ== 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 Reviewed-by: Jeff Layton --- .../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 231830daf5dc..60028eeecde0 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -401,4 +401,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 Sun Feb 8 07:58:47 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 4EAD03128BF; Fri, 24 Oct 2025 10:58: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=1761303515; cv=none; b=lP3eOkGs3vTYfrgi//n6KBwYh1kxifXvUSYF7j2WefM9SEuRtmchAPcxtRbcP9iMiFm1t7yRq4f+p3bshu3y9t+5UiwhKJpPWGiFDgqQmgrVZIa8KiYGshkfB5qf1JTym1PzN4Vv7pQlWtn/SmpFtXUxGgdmOCi9bnlRi8NH0HA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303515; c=relaxed/simple; bh=VBORRP+h0KErK54FHs98ti+2CEgWK2XfNgSQLs2e/YU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nm+4MzCLaod8VsNoNOzn59CDc5vDrJWu5r4m7OLy0eu5lKgg0erIt3WWSqlEf4mlY5ad1N5CD6JnXvaTECNm4e2BNVMRgWn9TFdBGg5YuX2SGkojqrO8+w3Vkj2BntfehjmVDgTJn4wF9wDVBpG8kqH6W0orSW23xvnhsFy3Luo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=bT3nUuPq; 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="bT3nUuPq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 490AEC4CEF1; Fri, 24 Oct 2025 10:58:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303514; bh=VBORRP+h0KErK54FHs98ti+2CEgWK2XfNgSQLs2e/YU=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=bT3nUuPqXS1+u2dJ5mTpEXg04aERyEjv4wHuQBxsv4ZM5g8pASQx50dfey6Dbv6Y8 ycW5FeU5zfvKyjZrEQh60f4otwVIvH3fdpbjyQN7FsT1Gaoi0V+MKIOZpJYd5xyaGD T/UZLiL9I8MEUlZ23KugN4uc4ZNYaUuxAPZGX8zAKT2+X0bx/jV0vL0nfUV4YRUWYI /g0L5WYK83FlhbdrYtyQzV9PlNrwdRBdtwPNM3qp1FkWB7dC1KvsKvM+dsBy+da2mi OumSIHXRNY+q6xqRfgVESYm0FdavGVAfe81eP0EaxSs0IWolIiPEEcgQcPY65nNm0j L4WvIcT7e6vPQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:29 +0200 Subject: [PATCH v3 60/70] 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: <20251024-work-namespace-nstree-listns-v3-60-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=VBORRP+h0KErK54FHs98ti+2CEgWK2XfNgSQLs2e/YU=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmp3+C++dPJhg8MCa9LifQ//i1/13+Vyjnh8UIqO9 c+kQ27PO0pZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTACYyV5bhf9AX8VxrMcM5/HuZ Kw8ffcn+O9K9+Ym+r+W2W0u5RZ4tjGD4p1v/zcnm7g636/eKq5rmtuVOk3AOs359viRKRCN6rrs oJwA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test IPv6 sockets also work with SIOCGSKNS. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../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 60028eeecde0..47c1524a8648 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -542,4 +542,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 Sun Feb 8 07:58:47 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 09946318142; Fri, 24 Oct 2025 10:58: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=1761303520; cv=none; b=X9U9keIh+acJBzDGFt59q0BkuYHbaM1OfLpFIuw+Bd6hJm9vD/tT8BgeI14XBo4vIOq5U/IsZTAm7ChMe3LJZI3e+m7Co19ZmqsokEtBBMR71y5K4S8ezVychSiv8TAuEb6BpT23VXbgVljW+5hf5NhFUHzB1UlKOX/TzolDy7M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303520; c=relaxed/simple; bh=2GRkF4aTvddGMSpKeYnAxQf+2i+z67SQVbcHcw3mqCk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=buWxFCbOuhGz1UvUYbCmD4koDJc7X1hvNqlKwvCLcGZHGUKaJ96C14/N2I0HrSiLAf35Uz3uuKrMS//Aw7KTueb6C/aTky2bKl48ip9wTnwKk8zXt8R6QJMDGJD1LolQ0TmAkZeYrvaFl4ynG3HQPvnfo/hsrJXB74IGiXqC+XI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=dlgs5ul2; 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="dlgs5ul2" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E0D2C4CEF5; Fri, 24 Oct 2025 10:58:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303519; bh=2GRkF4aTvddGMSpKeYnAxQf+2i+z67SQVbcHcw3mqCk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=dlgs5ul21HqMAKH0vzw3669fuZ2kyoxwus8rZOBODOyp0ZYU26c61rXzj+1iUcvCS T/XWXBWCWAiPP+ET/40hezlm3pTRZU5uQUexTRTWaCHKJNdGNnDmuNBDE3WFJ2DXPs brAlgHPNTMdVhM8wJqm46eiQDZ7xJv7aICoHrieTRqhGdhdoKrUTOLjuu5MRn/sE+r BpetiXzKh30mkFn6Vq9LsHQG+T2/82hwV0nmx8sr8rMhu15TsRArogh8MmV+ovcGse n8iEPAfOJL3U1EVsitGUnSk+87j9gR99kc1afAOcfQOAzOW3G4PSrU5MDEfNTT2WdU NQ/nyLnNTOswg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:30 +0200 Subject: [PATCH v3 61/70] 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: <20251024-work-namespace-nstree-listns-v3-61-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5894; i=brauner@kernel.org; h=from:subject:message-id; bh=2GRkF4aTvddGMSpKeYnAxQf+2i+z67SQVbcHcw3mqCk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmpf/246m7z+lg5H+4bNxy+8PHd4uU+lfeW9HS/3V 4nuTngzvaOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAi0tWMDM8Z4296n3+wY63b rPUlrnNXT2pXDf/u4C/MuOLAzjmtE08w/I81/7uvZnZPhmTOQt0nCgvTj0aKFN9nuxp4iGcKe/I 5YSYA 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 Reviewed-by: Jeff Layton --- .../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 47c1524a8648..98f6a0e1b9dd 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -576,4 +576,207 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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 Sun Feb 8 07:58:47 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 66AAF318142; Fri, 24 Oct 2025 10:58: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=1761303525; cv=none; b=K0+j2ZPiNDfSMSUZU+ka4QIFVKrwDdVx2HjakgPPRmKB1c8zfjdgDJcnE7df69z0DvG+tVFC16RpmGSu4iLFN8q0jOj6uR8tRhWGkJkqF1MbchrCXcTv+3LWnQYtlSCdsXTa3qMAb3rNxpQNxI2ElaTsHVO2DGkfW3OpTcRw7qE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303525; c=relaxed/simple; bh=cg2+/WFjpG13y8cnkuocp9/qhpt17gumOqmPdMg4wzY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FlezGG5r/1m0cAa807agWpJ0D2awfdUmU4M72IiipAmHJ7qcWV+AwtGXsnShnd95VJL9+1Jm+SQ7iyPjc3UDt93+OH9VZCGPPFjr+y9DOYgkqGZLpud4lba8ueBHuGHTMLeXagNX3rN9msVWqCIwNW6aOB1OKiwBQwsQxAJrRro= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=fh6EfgMI; 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="fh6EfgMI" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E659C4CEF1; Fri, 24 Oct 2025 10:58:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303524; bh=cg2+/WFjpG13y8cnkuocp9/qhpt17gumOqmPdMg4wzY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=fh6EfgMIaUShoZrsj8zsdvuMZObRgBsGzWihq1sPS/RyQIdcvgp3aSXKjyy5BncGM VjCVkUctfsC2+ndG5XCojnFfYwx6Rl4GtkV7DqQDKTqpd81naMhmoUdmCfLaTMYIc9 oQN+dM1zWWn4qH5jTBc8CxnZ8uoBog8pt7K4+SnCfw+4NaJrjPNkVQ8IHThLkrd27e 3khEqUN6h1ZQg12ub6myhtl7vjlffcvK19rXwxBJl5HLS7cBPnFsGzPU1S7HHJ6ZB1 teNsHupwGZ8eKFq0Zb2ngyOAnAkWDO3EBDF63SP4odqsqMxnnvIPJADfv8DfFC7Jpc 0wnHkZ0shT95w== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:31 +0200 Subject: [PATCH v3 62/70] 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: <20251024-work-namespace-nstree-listns-v3-62-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=6550; i=brauner@kernel.org; h=from:subject:message-id; bh=cg2+/WFjpG13y8cnkuocp9/qhpt17gumOqmPdMg4wzY=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jmoXXW78ie967jTf+jN/P/2VFfLi/NMtHsd+/YKXl 9RUgw1WHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABO5u5/hf2Sqf8JHATkPu+9v 1jlsYt79+UzZ1e7k1DMHpGdxz2l4O4GRoS3z0KVd0er/2U5uPCzNO/3kPGeJz7er2a/3/JbXNT9 zmQkA 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 Reviewed-by: Jeff Layton --- .../testing/selftests/namespaces/siocgskns_test.c | 195 +++++++++++++++++= ++++ 1 file changed, 195 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 98f6a0e1b9dd..a909232dba36 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -779,4 +779,199 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(reopened_fd, 0); + 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 Sun Feb 8 07:58:47 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 5A8203191BF; Fri, 24 Oct 2025 10:58:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303530; cv=none; b=rPoz5DY4oVV6ICxCIAInoP+5xRvFsUZ2uQ3oI7hqNbDsYlHhqxTOFJfd4TQ/JufjNb9E6r85uFFkJwsyGnvKbOorhYEAdy8sXf2qxkcYrmfO6nivYR1xhp3uB+gGWtOcp+N77OgT1DdurC1L+qt5WKqQgqgFmOT8dPLoe4OvvSo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303530; c=relaxed/simple; bh=sKXDidGiOR1H5xWVrgVg4FOPuYvFiXWeY9Fffw5SXJg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=HlgtwCQ5PJoRHtnakKG71C0SUUbHklapUExHZcvT0v5R0y7WXvb9kPAh7+AfxwiiuzzKO2MDRGKKxs0VtGcvP3sX/t1NvErF2Nja0MGebeSus81GX7wbZXttP6x988IfkKbM4Sw/KsNa6AUVFuHowtblDsJwqEQEB6/Mh9yHgUY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=lTFrwrW7; 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="lTFrwrW7" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5D70AC113D0; Fri, 24 Oct 2025 10:58:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303529; bh=sKXDidGiOR1H5xWVrgVg4FOPuYvFiXWeY9Fffw5SXJg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=lTFrwrW70s4sRusxH4re81GW027373cpyzv4mxtLIzsB/7OLmW6vuhk1d3ZD/YhrI InyL+OoOmqf4KMTx0j56/Q5Y58L8m5g6PlMLmrX2mWL/gtedXyyEJY/8Ba/dAoQt9f bHOxIGXXweLr2lsDE1JZvHuBf13jeINfDdS336C4W8FYRi93+HseXsB9fyl1I6FCCH X9mp6O9UC89nZEyyYTRsmyk7Mq6akoBBwpDhMfl67YZBpTWoRPV0Yq3gcfdGrpivLV iiA6rJn/8OHp3rCC3UdIRLUR6a0/AvdDWRdbLPUEg5Hevoqs1sgRIgZcVwJagHobCE UF8gnwdQJ0Rig== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:32 +0200 Subject: [PATCH v3 63/70] 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: <20251024-work-namespace-nstree-listns-v3-63-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=8469; i=brauner@kernel.org; h=from:subject:message-id; bh=sKXDidGiOR1H5xWVrgVg4FOPuYvFiXWeY9Fffw5SXJg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jurYt/KAWehyRc8lHh4dBtmdH9+XSrhcTXjl/+tEy a/rFgqnOkpZGMS4GGTFFFkc2k3C5ZbzVGw2ytSAmcPKBDKEgYtTAG7yVUaGrTLpT52DE+tv7dw2 44xLe+ac/83JU69+4zH9uj3B+VnzIYb/dWcLo3b+KpSXn9Fq8ej8stwGfaHeTuXPGYxnf/5lapf gAAA= 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 Reviewed-by: Jeff Layton --- .../testing/selftests/namespaces/siocgskns_test.c | 283 +++++++++++++++++= ++++ 1 file changed, 283 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index a909232dba36..706049768d52 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -974,4 +974,287 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* 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); + ASSERT_LT(reopened_fd, 0); + 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 Sun Feb 8 07:58:47 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 7257B3191BF; Fri, 24 Oct 2025 10:58: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=1761303535; cv=none; b=bxJUx4vLSd2gcXd/m3IrxtG3xGTX+dayybqBS5/3EEeO0XQpT3lNFxxfmNs567dQofnFJBmK3q7UYGLOwtsQRvu0PLNRMRUklGHnYm4XmGvgyFV0+rma+wlj1BggtE6TY8Eb5ukeG8rAWHlaTo6dySo89FK6S+/BOMl4s63mkXg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303535; c=relaxed/simple; bh=4DBUpYISpIFS5Tcy2WQb4n+lgh4Zbjunaz48EAgExJo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pBzl3lcyGC/0rr0SOcAoNyBIbtmBcXgBXYkEIESY+cAqZLbi1rSGLXtzwZC1b+WBzd5CRcTDVw8DbGm41TE/o6VVuYUDyS2iKk1Xg79yrwkflKYI8ZBwnGx9IGhaq989zAdik5ShKr9nVorQyGLAj7DNqKtw1mg5P/shm6abDao= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cAbGjjQR; 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="cAbGjjQR" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B8E4C4CEF1; Fri, 24 Oct 2025 10:58:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303535; bh=4DBUpYISpIFS5Tcy2WQb4n+lgh4Zbjunaz48EAgExJo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=cAbGjjQRfcry3g18EvsjRQNBsA4jq15iaFt6nVNu++Ghg1Znp8d2xf4iLMQ7mLzw/ b2s5fEWvMV85kGSXKvfVSg3Ua+Emeg7ZciPNszo6/c+qe9wbpD+hqzhHGiGHhiCHO1 fv5iJClRK6QLEhwVtg58eoEbjaCwh7793Fq3nTcAdejiftokuy+M9Av33cyjGajQ9t nL9hVaP/6lkr76ayE88WtslLQ0B506eFK+2uXmWgkRTNyJGaWkzNFHYY24hQTl+9oE uq85qqm+nXDLZGCDqYqLfW9XtAqo3R7isSL53bOC7y7FbaSC1RptaI20Spzl7gWdtg OMMHoCFan6jig== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:33 +0200 Subject: [PATCH v3 64/70] 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: <20251024-work-namespace-nstree-listns-v3-64-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=18059; i=brauner@kernel.org; h=from:subject:message-id; bh=4DBUpYISpIFS5Tcy2WQb4n+lgh4Zbjunaz48EAgExJo=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jup4df1c/y/GnStio51nTpLaUHj45NQi96Qi8e5Oa RZ37QXZHaUsDGJcDLJiiiwO7Sbhcst5KjYbZWrAzGFlAhnCwMUpABP55MDwv0a6WKTl19PdSl6L 13e/nWmwbm/AyzffN3w7w747ljVgYg3DP02bD4evTFk3KYohOWYq/0ztKYHfCqxc44RVL0928tu zigUA 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 Reviewed-by: Jeff Layton --- .../testing/selftests/namespaces/siocgskns_test.c | 564 +++++++++++++++++= ++++ 1 file changed, 564 insertions(+) diff --git a/tools/testing/selftests/namespaces/siocgskns_test.c b/tools/te= sting/selftests/namespaces/siocgskns_test.c index 706049768d52..ba689a22d82f 100644 --- a/tools/testing/selftests/namespaces/siocgskns_test.c +++ b/tools/testing/selftests/namespaces/siocgskns_test.c @@ -1257,4 +1257,568 @@ 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)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* + * 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 From nobody Sun Feb 8 07:58:47 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 9785C36C245; Fri, 24 Oct 2025 10:59: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=1761303540; cv=none; b=olPEyT52tU05obqgEwS1ua7r1zo1ORhbz+F1qHu25fmmm4IPsgxJPI19YwaZIJBMHS+ifG6VPMbFF9xPAGEmsKVviEXCbQFPRbEGxEtCr7nCR5xphNrOgiiZCu9wXl1nwOropuoYQ8Gz1XNabBOHnEVM3kjemfv7nxmA6A5rsSY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303540; c=relaxed/simple; bh=WqVUkxH4ZBiU30MvQT3O+adj44+G6SHOGkbS5VtGikk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qLaPrdxmR1iW8Q4Tppgdip/Fpif2gQg2oH4y7CmRRsK/EH2agaNRbvFUNrYUmwtnVmHLQt7fy0L2jPjE5pBtdfllQaz2GUCphvNoxmQWQ/QWSrRwVEJGSsRgp+dKJLY/ULRG32ha8MaYXH46luIIMBMd9PSAVI3Yf+1moVL2XmE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=tSlzC7e4; 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="tSlzC7e4" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7FE48C113D0; Fri, 24 Oct 2025 10:58:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303540; bh=WqVUkxH4ZBiU30MvQT3O+adj44+G6SHOGkbS5VtGikk=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=tSlzC7e4j3jM0TnsmBpG9ygZRTDeG0oCzatX7Bx62nyYTJFAPnZbArKHQkMbOwGmw 2ppZzY2Y0lN+A+fEqVOlmwMZ/YPhJbi7hbL7xWHlzn0WBF6qXc7QkJi1Mb0770lIbo I0E3ndgQCiXDHjm4QCP+Ppt2gU0hSp8Dj2++2jPTUxMeEa54FhceUaM/SEzDlM8Y+6 82y85nJ4IFzxy3WVYH7Hz6ZawXYFim/U+Xku/RhiTIXv35PI3aNKDVyUm7IwEhBzgQ QQJXqrbeZxhx/vOvOr9d3Cb2Cxklc1gPgm6L1C5LdFZ6D1i90tEdcdGi+G2HxPqqP/ JjIZfRtnr+yqw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:34 +0200 Subject: [PATCH v3 65/70] selftests/namespace: first threaded active reference count 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: <20251024-work-namespace-nstree-listns-v3-65-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=4736; i=brauner@kernel.org; h=from:subject:message-id; bh=WqVUkxH4ZBiU30MvQT3O+adj44+G6SHOGkbS5VtGikk=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8juqo3ZfBdH/T7Zvp5xadnHbn69FfaksSrRPfbNc29 Dv7nb3KqaOUhUGMi0FWTJHFod0kXG45T8Vmo0wNmDmsTCBDGLg4BWAi4jcZ/qf87ftsHjwpNLOI 95hR7WXT7Uft1m61/RP6py929t1HaW8YGU56vmaYxsYYukzTTPq3UltjuaXUPJsDSWVnY3j5G7f d5AQA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that namespace becomes inactive after thread exits. This verifies active reference counting works with threads, not just processes. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../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 b7fa973a2572..0c6c4869bb16 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -12,9 +12,12 @@ #include #include #include +#include #include +#include #include "../kselftest_harness.h" #include "../filesystems/utils.h" +#include "wrappers.h" =20 #ifndef FD_NSFS_ROOT #define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */ @@ -2113,4 +2116,139 @@ TEST(ns_mixed_types_same_owner) ASSERT_LT(u_fd, 0); } =20 +/* Thread test helpers and structures */ +struct thread_ns_info { + __u64 ns_id; + int pipefd; + int syncfd_read; + int syncfd_write; + int exit_code; +}; + +static void *thread_create_namespace(void *arg) +{ + struct thread_ns_info *info =3D (struct thread_ns_info *)arg; + int ret; + + /* Create new network namespace */ + ret =3D unshare(CLONE_NEWNET); + if (ret < 0) { + info->exit_code =3D 1; + return NULL; + } + + /* Get namespace ID */ + int fd =3D open("/proc/thread-self/ns/net", O_RDONLY); + if (fd < 0) { + info->exit_code =3D 2; + return NULL; + } + + ret =3D ioctl(fd, NS_GET_ID, &info->ns_id); + close(fd); + if (ret < 0) { + info->exit_code =3D 3; + return NULL; + } + + /* Send namespace ID to main thread */ + if (write(info->pipefd, &info->ns_id, sizeof(info->ns_id)) !=3D sizeof(in= fo->ns_id)) { + info->exit_code =3D 4; + return NULL; + } + + /* Wait for signal to exit */ + char sync_byte; + if (read(info->syncfd_read, &sync_byte, 1) !=3D 1) { + info->exit_code =3D 5; + return NULL; + } + + info->exit_code =3D 0; + return NULL; +} + +/* + * Test that namespace becomes inactive after thread exits. + * This verifies active reference counting works with threads, not just pr= ocesses. + */ +TEST(thread_ns_inactive_after_exit) +{ + pthread_t thread; + struct thread_ns_info info; + struct file_handle *handle; + int pipefd[2]; + int syncpipe[2]; + int ret; + char sync_byte; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + ASSERT_EQ(pipe(syncpipe), 0); + + info.pipefd =3D pipefd[1]; + info.syncfd_read =3D syncpipe[0]; + info.syncfd_write =3D -1; + info.exit_code =3D -1; + + /* Create thread that will create a namespace */ + ret =3D pthread_create(&thread, NULL, thread_create_namespace, &info); + ASSERT_EQ(ret, 0); + + /* Read namespace ID from thread */ + __u64 ns_id; + ret =3D read(pipefd[0], &ns_id, sizeof(ns_id)); + if (ret !=3D sizeof(ns_id)) { + sync_byte =3D 'X'; + write(syncpipe[1], &sync_byte, 1); + pthread_join(thread, NULL); + close(pipefd[0]); + close(pipefd[1]); + close(syncpipe[0]); + close(syncpipe[1]); + SKIP(return, "Failed to read namespace ID from thread"); + } + + TH_LOG("Thread created namespace with ID %llu", (unsigned long long)ns_id= ); + + /* Construct file handle */ + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *fh =3D (struct nsfs_file_handle *)handle->f_hand= le; + fh->ns_id =3D ns_id; + fh->ns_type =3D 0; + fh->ns_inum =3D 0; + + /* Namespace should be active while thread is alive */ + TH_LOG("Attempting to open namespace while thread is alive (should succee= d)"); + int nsfd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + ASSERT_GE(nsfd, 0); + close(nsfd); + + /* Signal thread to exit */ + TH_LOG("Signaling thread to exit"); + sync_byte =3D 'X'; + ASSERT_EQ(write(syncpipe[1], &sync_byte, 1), 1); + close(syncpipe[1]); + + /* Wait for thread to exit */ + ASSERT_EQ(pthread_join(thread, NULL), 0); + close(pipefd[0]); + close(pipefd[1]); + close(syncpipe[0]); + + if (info.exit_code !=3D 0) + SKIP(return, "Thread failed to create namespace"); + + TH_LOG("Thread exited, namespace should be inactive"); + + /* Namespace should now be inactive */ + nsfd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + ASSERT_LT(nsfd, 0); + /* Should fail with ENOENT (inactive) or ESTALE (gone) */ + TH_LOG("Namespace 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 Sun Feb 8 07:58:47 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 4AD2D3191D8; Fri, 24 Oct 2025 10:59: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=1761303545; cv=none; b=dr8a01HWFsDPqa4vQHtM4Mzu0ZcqKvExu2hJWZTOtjZUd8dWaKIm/eQU6njgBBMRWsUJZZMEr1S/Fxg367ugDxZgghGpJHd2n5OCIsKeBJ8xSGX+AhQLrOtjs9el2K1+J2Qw4ouVbqRkVqyXmLKVxguSw+VZzd5DhhTXkF4gmzY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303545; c=relaxed/simple; bh=+kgGWvLMBNpy0C4YEMZXDEKTpLYegwzhaVcMRXxEJRg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Iu4VX79tSepGEm0/sD2Tp4SEqfBIZvcYgPciUt+KkNwyF7xpo1bTuhgEYSXA3ygmZmRzprLXrXq8b6OVz2Kp+OTxmuEtTcdGhdSon4YYysl/1JTznJ+doK9mijXCU9m690ePXovtxZDcFJG+KsSuBUrpxpp6PfNdJSlyTLD18rE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=OS9VuFq+; 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="OS9VuFq+" Received: by smtp.kernel.org (Postfix) with ESMTPSA id A17CAC4CEFF; Fri, 24 Oct 2025 10:59:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303545; bh=+kgGWvLMBNpy0C4YEMZXDEKTpLYegwzhaVcMRXxEJRg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=OS9VuFq+p15knQbrnvWBwJblwGdno3oU59XB0mMm6SUD48391bR0SpVaxLCk/u2Wf impzdD4YedlLes45Ec6LF4lUDYYr4jiuipgpOjLG4hhnaqwW42Fr7UfnMnVnk7onw2 GGRWo5mLghvuiRmf/sPL7jgf56HsF2QDiCUwM+nh0NZNxds5dPp08VMhiN15np/fBF /Bz3eIQ9kQ+yFjmNlnhxckedjjnpZkVn5tfzqKkg2nkJov0psm/0vnsSNlh6rVOXeT KVwC4w7JG3THen32DAd8iO5tYbBI0pNJ0BFWuVwZu8pgyDMdBjv9czwH1RIZOIHNtj hRvH89Cyp9vPg== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:35 +0200 Subject: [PATCH v3 66/70] selftests/namespace: second threaded active reference count 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: <20251024-work-namespace-nstree-listns-v3-66-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=3834; i=brauner@kernel.org; h=from:subject:message-id; bh=+kgGWvLMBNpy0C4YEMZXDEKTpLYegwzhaVcMRXxEJRg=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8juoI73luXFt+yfSE8Ydd6umC5iXqJSYn1gWyvOnIc a4UUHnYUcrCIMbFICumyOLQbhIut5ynYrNRpgbMHFYmkCEMXJwCMBGlVEaGWc6uJ2I7p7xKUV6h vt9m1QKl6qlGt/PynOQ/JqfzvLwfyPDPcq9q/em0WYfnRWl9n3fQzECb07ax7sVFla+G0rfTdvO yAgA= X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that a namespace remains active while a thread holds an fd to it. Even after the thread exits, the namespace should remain active as long as another thread holds a file descriptor to it. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 99 ++++++++++++++++++= ++++ 1 file changed, 99 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 0c6c4869bb16..24dc8ef106b9 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -2251,4 +2251,103 @@ TEST(thread_ns_inactive_after_exit) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =20 +/* + * Test that a namespace remains active while a thread holds an fd to it. + * Even after the thread exits, the namespace should remain active as long= as + * another thread holds a file descriptor to it. + */ +TEST(thread_ns_fd_keeps_active) +{ + pthread_t thread; + struct thread_ns_info info; + struct file_handle *handle; + int pipefd[2]; + int syncpipe[2]; + int ret; + char sync_byte; + char buf[sizeof(*handle) + MAX_HANDLE_SZ]; + + ASSERT_EQ(pipe(pipefd), 0); + ASSERT_EQ(pipe(syncpipe), 0); + + info.pipefd =3D pipefd[1]; + info.syncfd_read =3D syncpipe[0]; + info.syncfd_write =3D -1; + info.exit_code =3D -1; + + /* Create thread that will create a namespace */ + ret =3D pthread_create(&thread, NULL, thread_create_namespace, &info); + ASSERT_EQ(ret, 0); + + /* Read namespace ID from thread */ + __u64 ns_id; + ret =3D read(pipefd[0], &ns_id, sizeof(ns_id)); + if (ret !=3D sizeof(ns_id)) { + sync_byte =3D 'X'; + write(syncpipe[1], &sync_byte, 1); + pthread_join(thread, NULL); + close(pipefd[0]); + close(pipefd[1]); + close(syncpipe[0]); + close(syncpipe[1]); + SKIP(return, "Failed to read namespace ID from thread"); + } + + TH_LOG("Thread created namespace with ID %llu", (unsigned long long)ns_id= ); + + /* Construct file handle */ + handle =3D (struct file_handle *)buf; + handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *fh =3D (struct nsfs_file_handle *)handle->f_hand= le; + fh->ns_id =3D ns_id; + fh->ns_type =3D 0; + fh->ns_inum =3D 0; + + /* Open namespace while thread is alive */ + TH_LOG("Opening namespace while thread is alive"); + int nsfd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + ASSERT_GE(nsfd, 0); + + /* Signal thread to exit */ + TH_LOG("Signaling thread to exit"); + sync_byte =3D 'X'; + write(syncpipe[1], &sync_byte, 1); + close(syncpipe[1]); + + /* Wait for thread to exit */ + pthread_join(thread, NULL); + close(pipefd[0]); + close(pipefd[1]); + close(syncpipe[0]); + + if (info.exit_code !=3D 0) { + close(nsfd); + SKIP(return, "Thread failed to create namespace"); + } + + TH_LOG("Thread exited, but main thread holds fd - namespace should remain= active"); + + /* Namespace should still be active because we hold an fd */ + int nsfd2 =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + ASSERT_GE(nsfd2, 0); + + /* Verify it's the same namespace */ + struct stat st1, st2; + ASSERT_EQ(fstat(nsfd, &st1), 0); + ASSERT_EQ(fstat(nsfd2, &st2), 0); + ASSERT_EQ(st1.st_ino, st2.st_ino); + close(nsfd2); + + TH_LOG("Closing fd - namespace should become inactive"); + close(nsfd); + + /* Now namespace should be inactive */ + nsfd =3D open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY); + ASSERT_LT(nsfd, 0); + /* Should fail with ENOENT (inactive) or ESTALE (gone) */ + TH_LOG("Namespace 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 Sun Feb 8 07:58:47 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 66E7F319843; Fri, 24 Oct 2025 10:59: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=1761303550; cv=none; b=o1cuB53Jxg8E0GY4LGemEYWMvX7scrrr1sfJhdT4bOicFB7GsteDJfLr5Lg4HKcjqg162H+hjN2Aii5POdKzURbG44et7tC2J+IFy9LlijMUvQBOyidYArtBXqA00+mrsiCYtBGityAnR4Cp5QQnP5zTeWgHlHhTkrB+3QOMNMM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303550; c=relaxed/simple; bh=wjpkLSx2K2iB/mWZZQZcuIqQ514ywG7UHLGyzr0x04k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MMink3SWkcIc7dH+/EGe6wikBsjx7f6SsLDYXHYiss8meiI/6Y3t/VkfrFs0BKWDL/3r/WfzRfMZnb+oxamkTJS13134svbg7Q3ExDObLuXefuqpD7rRnHCR4gQ49gbh9SggFzDz8Q6+zxdllbmOLYZRvA8chgjREJmx22dIX+c= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=YFTNuFSj; 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="YFTNuFSj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9E94BC4CEF1; Fri, 24 Oct 2025 10:59:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303550; bh=wjpkLSx2K2iB/mWZZQZcuIqQ514ywG7UHLGyzr0x04k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=YFTNuFSjSB3jOliTHKvt9NNckQS3AgEWAAjZAcg2tgiLz/3+JLJt48UZtKv2ikiB1 uk7fiXJmzQh/BTp5mnBoPAFtYhzQ3DTAizNqQ2nmPx4WjmzlkllNHdbHhuab/txTpW DDzS1yC1UpmTvlV9+OmO37w9iAjZ5fuWS5pPHV3BxPwGnzDAjPOqRj8wxc0VWNi6JU VaYoBOxHBCsffFX6qMIAW21k3OEK9SehKzQ8c6lDFwVXPM88ZAn8MK35Qf84X6isN2 MNoPWt7h05P5X3fOESAKzvnniBYjnaHYxL1gCY5YcjhGoNVVjZ6fkraJi3reNJFDpl vgs/JaMGY7Srw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:36 +0200 Subject: [PATCH v3 67/70] selftests/namespace: third threaded active reference count 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: <20251024-work-namespace-nstree-listns-v3-67-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=11371; i=brauner@kernel.org; h=from:subject:message-id; bh=wjpkLSx2K2iB/mWZZQZcuIqQ514ywG7UHLGyzr0x04k=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jur4OLtGsW32X391m/cv9x36pb//8HqbOfJvCmZXC 5RVHuaa3VHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRnniG/4GHg5wfRGdvLLIp PlfLmXx9fsHar+Lnl9rK3VB/HqzQI83IsP1KndOW0n/vtx+qrl3zgLnk0NSz59PnHFo2U3rC7v5 0Nz4A X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test that namespaces become inactive after subprocess with multiple threads exits. Create a subprocess that unshares user and network namespaces, then creates two threads that share those namespaces. Verify that after all threads and subprocess exit, the namespaces are no longer listed by listns() and cannot be opened by open_by_handle_at(). Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- .../selftests/namespaces/ns_active_ref_test.c | 319 +++++++++++++++++= ++++ 1 file changed, 319 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 24dc8ef106b9..093268f0efaa 100644 --- a/tools/testing/selftests/namespaces/ns_active_ref_test.c +++ b/tools/testing/selftests/namespaces/ns_active_ref_test.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -2350,4 +2351,322 @@ TEST(thread_ns_fd_keeps_active) ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); } =20 +/* Structure for thread data in subprocess */ +struct thread_sleep_data { + int syncfd_read; +}; + +static void *thread_sleep_and_wait(void *arg) +{ + struct thread_sleep_data *data =3D (struct thread_sleep_data *)arg; + char sync_byte; + + /* Wait for signal to exit - read will unblock when pipe is closed */ + (void)read(data->syncfd_read, &sync_byte, 1); + return NULL; +} + +/* + * Test that namespaces become inactive after subprocess with multiple thr= eads exits. + * Create a subprocess that unshares user and network namespaces, then cre= ates two + * threads that share those namespaces. Verify that after all threads and = subprocess + * exit, the namespaces are no longer listed by listns() and cannot be ope= ned by + * open_by_handle_at(). + */ +TEST(thread_subprocess_ns_inactive_after_all_exit) +{ + int pipefd[2]; + int sv[2]; + pid_t pid; + int status; + __u64 user_id, net_id; + struct file_handle *user_handle, *net_handle; + char user_buf[sizeof(*user_handle) + MAX_HANDLE_SZ]; + char net_buf[sizeof(*net_handle) + MAX_HANDLE_SZ]; + char sync_byte; + int ret; + + ASSERT_EQ(pipe(pipefd), 0); + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + close(pipefd[0]); + close(sv[0]); + + /* Create user namespace with mappings */ + if (setup_userns() < 0) { + fprintf(stderr, "Child: setup_userns() failed: %s\n", strerror(errno)); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + fprintf(stderr, "Child: setup_userns() succeeded\n"); + + /* Get user namespace ID */ + int user_fd =3D open("/proc/self/ns/user", O_RDONLY); + if (user_fd < 0) { + fprintf(stderr, "Child: open(/proc/self/ns/user) failed: %s\n", strerro= r(errno)); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + + if (ioctl(user_fd, NS_GET_ID, &user_id) < 0) { + fprintf(stderr, "Child: ioctl(NS_GET_ID) for user ns failed: %s\n", str= error(errno)); + close(user_fd); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + close(user_fd); + fprintf(stderr, "Child: user ns ID =3D %llu\n", (unsigned long long)user= _id); + + /* Unshare network namespace */ + if (unshare(CLONE_NEWNET) < 0) { + fprintf(stderr, "Child: unshare(CLONE_NEWNET) failed: %s\n", strerror(e= rrno)); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + fprintf(stderr, "Child: unshare(CLONE_NEWNET) succeeded\n"); + + /* Get network namespace ID */ + int net_fd =3D open("/proc/self/ns/net", O_RDONLY); + if (net_fd < 0) { + fprintf(stderr, "Child: open(/proc/self/ns/net) failed: %s\n", strerror= (errno)); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + + if (ioctl(net_fd, NS_GET_ID, &net_id) < 0) { + fprintf(stderr, "Child: ioctl(NS_GET_ID) for net ns failed: %s\n", stre= rror(errno)); + close(net_fd); + close(pipefd[1]); + close(sv[1]); + exit(1); + } + close(net_fd); + fprintf(stderr, "Child: net ns ID =3D %llu\n", (unsigned long long)net_i= d); + + /* Send namespace IDs to parent */ + if (write(pipefd[1], &user_id, sizeof(user_id)) !=3D sizeof(user_id)) { + fprintf(stderr, "Child: write(user_id) failed: %s\n", strerror(errno)); + exit(1); + } + if (write(pipefd[1], &net_id, sizeof(net_id)) !=3D sizeof(net_id)) { + fprintf(stderr, "Child: write(net_id) failed: %s\n", strerror(errno)); + exit(1); + } + close(pipefd[1]); + fprintf(stderr, "Child: sent namespace IDs to parent\n"); + + /* Create two threads that share the namespaces */ + pthread_t thread1, thread2; + struct thread_sleep_data data; + data.syncfd_read =3D sv[1]; + + int ret_thread =3D pthread_create(&thread1, NULL, thread_sleep_and_wait,= &data); + if (ret_thread !=3D 0) { + fprintf(stderr, "Child: pthread_create(thread1) failed: %s\n", strerror= (ret_thread)); + close(sv[1]); + exit(1); + } + fprintf(stderr, "Child: created thread1\n"); + + ret_thread =3D pthread_create(&thread2, NULL, thread_sleep_and_wait, &da= ta); + if (ret_thread !=3D 0) { + fprintf(stderr, "Child: pthread_create(thread2) failed: %s\n", strerror= (ret_thread)); + close(sv[1]); + pthread_cancel(thread1); + exit(1); + } + fprintf(stderr, "Child: created thread2\n"); + + /* Wait for threads to complete - they will unblock when parent writes */ + fprintf(stderr, "Child: waiting for threads to exit\n"); + pthread_join(thread1, NULL); + fprintf(stderr, "Child: thread1 exited\n"); + pthread_join(thread2, NULL); + fprintf(stderr, "Child: thread2 exited\n"); + + close(sv[1]); + + /* Exit - namespaces should become inactive */ + fprintf(stderr, "Child: all threads joined, exiting with success\n"); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + close(sv[1]); + + TH_LOG("Parent: waiting to read namespace IDs from child"); + + /* Read namespace IDs from child */ + ret =3D read(pipefd[0], &user_id, sizeof(user_id)); + if (ret !=3D sizeof(user_id)) { + TH_LOG("Parent: failed to read user_id, ret=3D%d, errno=3D%s", ret, stre= rror(errno)); + close(pipefd[0]); + sync_byte =3D 'X'; + (void)write(sv[0], &sync_byte, 1); + close(sv[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read user namespace ID from child"); + } + + ret =3D read(pipefd[0], &net_id, sizeof(net_id)); + close(pipefd[0]); + if (ret !=3D sizeof(net_id)) { + TH_LOG("Parent: failed to read net_id, ret=3D%d, errno=3D%s", ret, strer= ror(errno)); + sync_byte =3D 'X'; + (void)write(sv[0], &sync_byte, 1); + close(sv[0]); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to read network namespace ID from child"); + } + + TH_LOG("Child created user ns %llu and net ns %llu with 2 threads", + (unsigned long long)user_id, (unsigned long long)net_id); + + /* Construct file handles */ + user_handle =3D (struct file_handle *)user_buf; + user_handle->handle_bytes =3D sizeof(struct nsfs_file_handle); + user_handle->handle_type =3D FILEID_NSFS; + struct nsfs_file_handle *user_fh =3D (struct nsfs_file_handle *)user_hand= le->f_handle; + user_fh->ns_id =3D user_id; + user_fh->ns_type =3D 0; + user_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; + + /* Verify namespaces are active while subprocess and threads are alive */ + TH_LOG("Verifying namespaces are active while subprocess with threads is = running"); + int user_fd =3D open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); + ASSERT_GE(user_fd, 0); + + int net_fd =3D open_by_handle_at(FD_NSFS_ROOT, net_handle, O_RDONLY); + ASSERT_GE(net_fd, 0); + + close(user_fd); + close(net_fd); + + /* Also verify they appear in listns() */ + TH_LOG("Verifying namespaces appear in listns() while active"); + struct ns_id_req req =3D { + .size =3D sizeof(struct ns_id_req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWUSER, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids[256]; + int nr_ids =3D sys_listns(&req, ns_ids, 256, 0); + if (nr_ids < 0) { + TH_LOG("listns() not available, skipping listns verification"); + } else { + /* Check if user_id is in the list */ + int found_user =3D 0; + for (int i =3D 0; i < nr_ids; i++) { + if (ns_ids[i] =3D=3D user_id) { + found_user =3D 1; + break; + } + } + ASSERT_TRUE(found_user); + TH_LOG("User namespace found in listns() as expected"); + + /* Check network namespace */ + req.ns_type =3D CLONE_NEWNET; + nr_ids =3D sys_listns(&req, ns_ids, 256, 0); + if (nr_ids >=3D 0) { + int found_net =3D 0; + for (int i =3D 0; i < nr_ids; i++) { + if (ns_ids[i] =3D=3D net_id) { + found_net =3D 1; + break; + } + } + ASSERT_TRUE(found_net); + TH_LOG("Network namespace found in listns() as expected"); + } + } + + /* Signal threads to exit */ + TH_LOG("Signaling threads to exit"); + sync_byte =3D 'X'; + /* Write two bytes - one for each thread */ + ASSERT_EQ(write(sv[0], &sync_byte, 1), 1); + ASSERT_EQ(write(sv[0], &sync_byte, 1), 1); + close(sv[0]); + + /* Wait for child process to exit */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + if (WEXITSTATUS(status) !=3D 0) { + TH_LOG("Child process failed with exit code %d", WEXITSTATUS(status)); + SKIP(return, "Child process failed"); + } + + TH_LOG("Subprocess and all threads have exited successfully"); + + /* Verify namespaces are now inactive - open_by_handle_at should fail */ + TH_LOG("Verifying namespaces are inactive after subprocess and threads ex= it"); + user_fd =3D open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); + ASSERT_LT(user_fd, 0); + TH_LOG("User namespace inactive as expected: %s (errno=3D%d)", + strerror(errno), errno); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + + net_fd =3D open_by_handle_at(FD_NSFS_ROOT, net_handle, O_RDONLY); + ASSERT_LT(net_fd, 0); + TH_LOG("Network namespace inactive as expected: %s (errno=3D%d)", + strerror(errno), errno); + ASSERT_TRUE(errno =3D=3D ENOENT || errno =3D=3D ESTALE); + + /* Verify namespaces do NOT appear in listns() */ + TH_LOG("Verifying namespaces do NOT appear in listns() when inactive"); + memset(&req, 0, sizeof(req)); + req.size =3D sizeof(struct ns_id_req); + req.ns_type =3D CLONE_NEWUSER; + nr_ids =3D sys_listns(&req, ns_ids, 256, 0); + if (nr_ids >=3D 0) { + int found_user =3D 0; + for (int i =3D 0; i < nr_ids; i++) { + if (ns_ids[i] =3D=3D user_id) { + found_user =3D 1; + break; + } + } + ASSERT_FALSE(found_user); + TH_LOG("User namespace correctly not listed in listns()"); + + /* Check network namespace */ + req.ns_type =3D CLONE_NEWNET; + nr_ids =3D sys_listns(&req, ns_ids, 256, 0); + if (nr_ids >=3D 0) { + int found_net =3D 0; + for (int i =3D 0; i < nr_ids; i++) { + if (ns_ids[i] =3D=3D net_id) { + found_net =3D 1; + break; + } + } + ASSERT_FALSE(found_net); + TH_LOG("Network namespace correctly not listed in listns()"); + } + } +} + TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 BD87D374ADC; Fri, 24 Oct 2025 10:59: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=1761303555; cv=none; b=esDRv/VarN3Gj9PP6MdhQReJbTOGlI/bLyv4Kly8Ja3US+ZuuFN6FjB8lzHOGkWR4eD1QxElbof73fKTOVjL8XwtNRb3uiWgBR34TAuYK3p0fMEXy75d8BRt93cHx40aOrBxwbwdbz6nCAv5SBUbxXu81iHaxrurB3Rt1AIRPbo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303555; c=relaxed/simple; bh=VQz+kdDDu0oyl8QafRMlRfX35XuungB3DQURbW3q4p0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RefjfYAYhkY6ePC210r+qpNs2jk1Aj+vKBtTdEZWkU7pyBgGee/6Kmo680MuyNpIvN9G34v3Ll5f8yp6Q1yKjGSy6mAfjrx2VNxwFYQYdR3PL0oytwwakdRdFeFf7lE+iwTNNrBxH+7FANbd0H7mz8o0Tj0gUeOWMQ6DGDhE9vQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Due4P/nq; 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="Due4P/nq" Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC986C113D0; Fri, 24 Oct 2025 10:59:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303555; bh=VQz+kdDDu0oyl8QafRMlRfX35XuungB3DQURbW3q4p0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Due4P/nqZrrkK2241JdmzWjAO2+QJg0aiobYsUO+yCIY4EpauXu1EnCsNBUPC516F 0uTTGSp92QHQG5te62HGbknzex9q4i1WmS5jV9W40EFM1DNb8ZRHsDNc3cm45qEPuX XnEwvUHbiuky1HfOSSgQkWmvfHtieO7Ad9vNuibgl6RkK5DtUO8nbGEmZa1bzb3ESa gbuwH3V7znT9bx/QDjrQQkMlUdvnPK8r1O//2XF576P+ZVP3GAaIvs9/GwG4KSH1ms QqECLq2waNNbzyj/xJ8YANmfX4YSLYSn2g17HOMKQJdJ0qNyJRmQN9ebiHzCc4WKR/ Gi/hD7rKGxI4g== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:37 +0200 Subject: [PATCH v3 68/70] selftests/namespace: commit_creds() active reference 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: <20251024-work-namespace-nstree-listns-v3-68-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=20385; i=brauner@kernel.org; h=from:subject:message-id; bh=VQz+kdDDu0oyl8QafRMlRfX35XuungB3DQURbW3q4p0=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8jur4rMrFwWoafk1IxfKArcmFE0axItpTLa8nMp3cn XxdopOzo5SFQYyLQVZMkcWh3SRcbjlPxWajTA2YOaxMIEMYuDgFYCJbeBj+h3WsKIpSyg0KrJfk NJ23renVmezj4Q/X3T6p7HXDq9QjnpHhy+af926cuRD8asKNfetuKKVNyyt/c7H6wKFGK5VfW35 G8gIA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Test credential changes and their impact on namespace active references. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 4 +- .../selftests/namespaces/cred_change_test.c | 814 +++++++++++++++++= ++++ 3 files changed, 818 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index aeb5f2711ff6..0091a7dfff20 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -5,3 +5,4 @@ ns_active_ref_test listns_test listns_permissions_test siocgskns_test +cred_change_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index d456505189cd..5d73f8dde6a0 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -8,7 +8,8 @@ TEST_GEN_PROGS :=3D nsid_test \ ns_active_ref_test \ listns_test \ listns_permissions_test \ - siocgskns_test + siocgskns_test \ + cred_change_test =20 include ../lib.mk =20 @@ -16,4 +17,5 @@ $(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 +$(OUTPUT)/cred_change_test: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/cred_change_test.c b/tools/= testing/selftests/namespaces/cred_change_test.c new file mode 100644 index 000000000000..7b4f5ad3f725 --- /dev/null +++ b/tools/testing/selftests/namespaces/cred_change_test.c @@ -0,0 +1,814 @@ +// 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 "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +/* + * Test credential changes and their impact on namespace active references. + */ + +/* + * Test setuid() in a user namespace properly swaps active references. + * Create a user namespace with multiple UIDs mapped, then setuid() betwee= n them. + * Verify that the user namespace remains active throughout. + */ +TEST(setuid_preserves_active_refs) +{ + pid_t pid; + int status; + __u64 userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 child_userns_id; + uid_t orig_uid =3D getuid(); + int setuid_count; + + close(pipefd[0]); + + /* Create new user namespace with multiple UIDs mapped (0-9) */ + userns_fd =3D get_userns_fd(0, orig_uid, 10); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* 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, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send namespace ID to parent */ + write(pipefd[1], &child_userns_id, sizeof(child_userns_id)); + + /* + * Perform multiple setuid() calls. + * Each setuid() triggers commit_creds() which should properly + * swap active references via switch_cred_namespaces(). + */ + for (setuid_count =3D 0; setuid_count < 50; setuid_count++) { + uid_t target_uid =3D (setuid_count % 10); + if (setuid(target_uid) < 0) { + if (errno !=3D EPERM) { + close(pipefd[1]); + exit(1); + } + } + } + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + if (read(pipefd[0], &userns_id, sizeof(userns_id)) !=3D sizeof(userns_id)= ) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace ID from child"); + } + close(pipefd[0]); + + TH_LOG("Child user namespace ID: %llu", (unsigned long long)userns_id); + + /* Verify namespace is active while child is running */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + ASSERT_TRUE(found); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify namespace becomes inactive after child exits */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + found =3D false; + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + + ASSERT_FALSE(found); + TH_LOG("setuid() correctly preserved active references (no leak)"); +} + +/* + * Test setgid() in a user namespace properly handles active references. + */ +TEST(setgid_preserves_active_refs) +{ + pid_t pid; + int status; + __u64 userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 child_userns_id; + uid_t orig_uid =3D getuid(); + int setgid_count; + + close(pipefd[0]); + + /* Create new user namespace with multiple GIDs mapped */ + userns_fd =3D get_userns_fd(0, orig_uid, 10); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* 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, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + write(pipefd[1], &child_userns_id, sizeof(child_userns_id)); + + /* Perform multiple setgid() calls */ + for (setgid_count =3D 0; setgid_count < 50; setgid_count++) { + gid_t target_gid =3D (setgid_count % 10); + if (setgid(target_gid) < 0) { + if (errno !=3D EPERM) { + close(pipefd[1]); + exit(1); + } + } + } + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + if (read(pipefd[0], &userns_id, sizeof(userns_id)) !=3D sizeof(userns_id)= ) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace ID from child"); + } + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify namespace becomes inactive */ + 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"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + + ASSERT_FALSE(found); + TH_LOG("setgid() correctly preserved active references (no leak)"); +} + +/* + * Test setresuid() which changes real, effective, and saved UIDs. + * This should properly swap active references via commit_creds(). + */ +TEST(setresuid_preserves_active_refs) +{ + pid_t pid; + int status; + __u64 userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 child_userns_id; + uid_t orig_uid =3D getuid(); + int setres_count; + + close(pipefd[0]); + + /* Create new user namespace */ + userns_fd =3D get_userns_fd(0, orig_uid, 10); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* 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, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + write(pipefd[1], &child_userns_id, sizeof(child_userns_id)); + + /* Perform multiple setresuid() calls */ + for (setres_count =3D 0; setres_count < 30; setres_count++) { + uid_t uid1 =3D (setres_count % 5); + uid_t uid2 =3D ((setres_count + 1) % 5); + uid_t uid3 =3D ((setres_count + 2) % 5); + + if (setresuid(uid1, uid2, uid3) < 0) { + if (errno !=3D EPERM) { + close(pipefd[1]); + exit(1); + } + } + } + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + if (read(pipefd[0], &userns_id, sizeof(userns_id)) !=3D sizeof(userns_id)= ) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace ID from child"); + } + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify namespace becomes inactive */ + 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"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + + ASSERT_FALSE(found); + TH_LOG("setresuid() correctly preserved active references (no leak)"); +} + +/* + * Test credential changes across multiple user namespaces. + * Create nested user namespaces and verify active reference tracking. + */ +TEST(cred_change_nested_userns) +{ + pid_t pid; + int status; + __u64 parent_userns_id, child_userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found_parent =3D false, found_child =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 parent_id, child_id; + uid_t orig_uid =3D getuid(); + + close(pipefd[0]); + + /* Create first user namespace */ + userns_fd =3D get_userns_fd(0, orig_uid, 1); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* Get first 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_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Create nested user namespace */ + userns_fd =3D get_userns_fd(0, 0, 1); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* Get nested 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_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + /* Send both IDs to parent */ + write(pipefd[1], &parent_id, sizeof(parent_id)); + write(pipefd[1], &child_id, sizeof(child_id)); + + /* Perform some credential changes in nested namespace */ + setuid(0); + setgid(0); + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + /* Read both namespace IDs */ + if (read(pipefd[0], &parent_userns_id, sizeof(parent_userns_id)) !=3D siz= eof(parent_userns_id)) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get parent namespace ID"); + } + + if (read(pipefd[0], &child_userns_id, sizeof(child_userns_id)) !=3D sizeo= f(child_userns_id)) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get child namespace ID"); + } + close(pipefd[0]); + + TH_LOG("Parent userns: %llu, Child userns: %llu", + (unsigned long long)parent_userns_id, + (unsigned long long)child_userns_id); + + /* Verify both namespaces are active */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + if (ret < 0) { + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + if (errno =3D=3D ENOSYS) + SKIP(return, "listns() not supported"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D parent_userns_id) + found_parent =3D true; + if (ns_ids[i] =3D=3D child_userns_id) + found_child =3D true; + } + + ASSERT_TRUE(found_parent); + ASSERT_TRUE(found_child); + + /* Wait for child */ + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify both namespaces become inactive */ + ret =3D sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); + ASSERT_GE(ret, 0); + + found_parent =3D false; + found_child =3D false; + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D parent_userns_id) + found_parent =3D true; + if (ns_ids[i] =3D=3D child_userns_id) + found_child =3D true; + } + + ASSERT_FALSE(found_parent); + ASSERT_FALSE(found_child); + TH_LOG("Nested user namespace credential changes preserved active refs (n= o leak)"); +} + +/* + * Test rapid credential changes don't cause refcount imbalances. + * This stress-tests the switch_cred_namespaces() logic. + */ +TEST(rapid_cred_changes_no_leak) +{ + pid_t pid; + int status; + __u64 userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 child_userns_id; + uid_t orig_uid =3D getuid(); + int change_count; + + close(pipefd[0]); + + /* Create new user namespace with wider range of UIDs/GIDs */ + userns_fd =3D get_userns_fd(0, orig_uid, 100); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* 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, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + write(pipefd[1], &child_userns_id, sizeof(child_userns_id)); + + /* + * Perform many rapid credential changes. + * Mix setuid, setgid, setreuid, setregid, setresuid, setresgid. + */ + for (change_count =3D 0; change_count < 200; change_count++) { + switch (change_count % 6) { + case 0: + setuid(change_count % 50); + break; + case 1: + setgid(change_count % 50); + break; + case 2: + setreuid(change_count % 50, (change_count + 1) % 50); + break; + case 3: + setregid(change_count % 50, (change_count + 1) % 50); + break; + case 4: + setresuid(change_count % 50, (change_count + 1) % 50, (change_count + = 2) % 50); + break; + case 5: + setresgid(change_count % 50, (change_count + 1) % 50, (change_count + = 2) % 50); + break; + } + } + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + if (read(pipefd[0], &userns_id, sizeof(userns_id)) !=3D sizeof(userns_id)= ) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace ID from child"); + } + close(pipefd[0]); + + TH_LOG("Testing with user namespace ID: %llu", (unsigned long long)userns= _id); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify namespace becomes inactive (no leaked active refs) */ + 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"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + + ASSERT_FALSE(found); + TH_LOG("200 rapid credential changes completed with no active ref leak"); +} + +/* + * Test setfsuid/setfsgid which change filesystem UID/GID. + * These also trigger credential changes but may have different code paths. + */ +TEST(setfsuid_preserves_active_refs) +{ + pid_t pid; + int status; + __u64 userns_id; + 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 ns_ids[256]; + ssize_t ret; + int i; + bool found =3D false; + int pipefd[2]; + + ASSERT_EQ(pipe(pipefd), 0); + + pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child process */ + int fd, userns_fd; + __u64 child_userns_id; + uid_t orig_uid =3D getuid(); + int change_count; + + close(pipefd[0]); + + /* Create new user namespace */ + userns_fd =3D get_userns_fd(0, orig_uid, 10); + if (userns_fd < 0) { + close(pipefd[1]); + exit(1); + } + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + close(pipefd[1]); + exit(1); + } + close(userns_fd); + + /* 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, &child_userns_id) < 0) { + close(fd); + close(pipefd[1]); + exit(1); + } + close(fd); + + write(pipefd[1], &child_userns_id, sizeof(child_userns_id)); + + /* Perform multiple setfsuid/setfsgid calls */ + for (change_count =3D 0; change_count < 50; change_count++) { + setfsuid(change_count % 10); + setfsgid(change_count % 10); + } + + close(pipefd[1]); + exit(0); + } + + /* Parent process */ + close(pipefd[1]); + + if (read(pipefd[0], &userns_id, sizeof(userns_id)) !=3D sizeof(userns_id)= ) { + close(pipefd[0]); + kill(pid, SIGKILL); + waitpid(pid, NULL, 0); + SKIP(return, "Failed to get namespace ID from child"); + } + close(pipefd[0]); + + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + + /* Verify namespace becomes inactive */ + 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"); + ASSERT_GE(ret, 0); + } + + for (i =3D 0; i < ret; i++) { + if (ns_ids[i] =3D=3D userns_id) { + found =3D true; + break; + } + } + + ASSERT_FALSE(found); + TH_LOG("setfsuid/setfsgid correctly preserved active references (no leak)= "); +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 99E5D375746; Fri, 24 Oct 2025 10:59: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=1761303560; cv=none; b=YtGemGnPI+vu4EsNoUZYKD9gdU/fgs1l6qP+lN2dLZG84rw2tcoYP15saxI/blBAJFfPXi423rJaQOq9Si4HpANg/disJR/vahWKa/nB3NshCMUBCIydBvac7NwSgFvxX6BW2bLvkS+8L8Cb2YxGaPXXMxA/OHSZN3DI7WMyyY0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303560; c=relaxed/simple; bh=g358ZvosiSM60y9eCxcqiXUo4S81KVXpq23srWS/+30=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Zj6MtPOqZT3m7x8oF4E787Y/izD3OGqL8P2prqybPQNN4dQ4msm7E8Vnc04f9886kFnAeMF0KlJiTjSk+YcXx3PiBfQRTCNnSMmNi8W5At1uOgOYSviLFdjkTNFr4CZPKBcwAfeqc8fsGYo2BeMGD7cfiDVGci5cpSNra5pZ4MU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Y6ixUWbg; 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="Y6ixUWbg" Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA1C0C4CEF5; Fri, 24 Oct 2025 10:59:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303560; bh=g358ZvosiSM60y9eCxcqiXUo4S81KVXpq23srWS/+30=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Y6ixUWbgyKD2ZWAR//MpakCyyePuxVTbyyzuhaYGU20BEjxPnPRvXrqF03McsRUOY wypYDtbFYLOFs2t+olXG4okfek4FDTR3ALo3qLlPP1otez77M98b3hMRcEzrx0Wt28 MUWEJMiPyneKZ3xxHDKXYysFWWqBhZf8ZVdT82I+bcj81Y1zKEU0lXI/hrhw09NotG kHikvLLQ38oD3AD1fCT8mm5SgmIlcNo7hb+MZKNOuxZLA9eBDXD1DHhMj66jhZ3utV GkQTNS+VfSZEQqnqijtfkUZnjJLer4xfbZ9mJwcO6ksV4MB28VF/kKT3hasKUiT8t8 KyV1TAqzyGrXQ== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:38 +0200 Subject: [PATCH v3 69/70] selftests/namespace: add stress 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: <20251024-work-namespace-nstree-listns-v3-69-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=18002; i=brauner@kernel.org; h=from:subject:message-id; bh=g358ZvosiSM60y9eCxcqiXUo4S81KVXpq23srWS/+30=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8juqQSCnfYCaveNiCfcKE0v8u/Ov2Pb18rPnxNHbnz TO2Wqzb3lHKwiDGxSArpsji0G4SLrecp2KzUaYGzBxWJpAhDFycAjCRompGhi2z9zcIrrqqebjF KGflh+pv+9n+qpy+Kiha32nLPUn3nCsjw0PTg+ddpVwjgiMnVL1m9DgmxlqwylznRv23tYnHi3T nsQEA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Stress tests for namespace active reference counting. These tests validate that the active reference counting system can handle high load scenarios including rapid namespace creation/destruction, large numbers of concurrent namespaces, and various edge cases under stress. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 4 +- tools/testing/selftests/namespaces/stress_test.c | 626 +++++++++++++++++++= ++++ 3 files changed, 630 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index 0091a7dfff20..f6dcf769f150 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -6,3 +6,4 @@ listns_test listns_permissions_test siocgskns_test cred_change_test +stress_test diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index 5d73f8dde6a0..3c776740f3ac 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -9,7 +9,8 @@ TEST_GEN_PROGS :=3D nsid_test \ listns_test \ listns_permissions_test \ siocgskns_test \ - cred_change_test + cred_change_test \ + stress_test =20 include ../lib.mk =20 @@ -18,4 +19,5 @@ $(OUTPUT)/listns_test: ../filesystems/utils.c $(OUTPUT)/listns_permissions_test: ../filesystems/utils.c $(OUTPUT)/siocgskns_test: ../filesystems/utils.c $(OUTPUT)/cred_change_test: ../filesystems/utils.c +$(OUTPUT)/stress_test: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/stress_test.c b/tools/testi= ng/selftests/namespaces/stress_test.c new file mode 100644 index 000000000000..dd7df7d6cb27 --- /dev/null +++ b/tools/testing/selftests/namespaces/stress_test.c @@ -0,0 +1,626 @@ +// 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 "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +/* + * Stress tests for namespace active reference counting. + * + * These tests validate that the active reference counting system can hand= le + * high load scenarios including rapid namespace creation/destruction, lar= ge + * numbers of concurrent namespaces, and various edge cases under stress. + */ + +/* + * Test rapid creation and destruction of user namespaces. + * Create and destroy namespaces in quick succession to stress the + * active reference tracking and ensure no leaks occur. + */ +TEST(rapid_namespace_creation_destruction) +{ + 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 ns_ids_before[256], ns_ids_after[256]; + ssize_t ret_before, ret_after; + int i; + + /* Get baseline count of active user namespaces */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active user namespaces", ret_before); + + /* Rapidly create and destroy 100 user namespaces */ + for (i =3D 0; i < 100; i++) { + pid_t pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create user namespace and immediately exit */ + if (setup_userns() < 0) + exit(1); + exit(0); + } + + /* Parent: wait for child */ + int status; + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + } + + /* Verify we're back to baseline (no leaked namespaces) */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After 100 rapid create/destroy cycles: %zd active user namespaces= ", ret_after); + ASSERT_EQ(ret_before, ret_after); +} + +/* + * Test creating many concurrent namespaces. + * Verify that listns() correctly tracks all of them and that they all + * become inactive after processes exit. + */ +TEST(many_concurrent_namespaces) +{ + 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 ns_ids_before[512], ns_ids_during[512], ns_ids_after[512]; + ssize_t ret_before, ret_during, ret_after; + pid_t pids[50]; + int num_children =3D 50; + int i; + int sv[2]; + + /* Get baseline */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active user namespaces", ret_before); + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + /* Create many children, each with their own user namespace */ + for (i =3D 0; i < num_children; i++) { + pids[i] =3D fork(); + ASSERT_GE(pids[i], 0); + + if (pids[i] =3D=3D 0) { + /* Child: create user namespace and wait for parent signal */ + char c; + + close(sv[0]); + + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + /* Signal parent we're ready */ + if (write(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + /* Wait for parent signal to exit */ + if (read(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + close(sv[1]); + exit(0); + } + } + + close(sv[1]); + + /* Wait for all children to signal ready */ + for (i =3D 0; i < num_children; i++) { + char c; + if (read(sv[0], &c, 1) !=3D 1) { + /* If we fail to read, kill all children and exit */ + close(sv[0]); + for (int j =3D 0; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + /* List namespaces while all children are running */ + ret_during =3D sys_listns(&req, ns_ids_during, ARRAY_SIZE(ns_ids_during),= 0); + ASSERT_GE(ret_during, 0); + + TH_LOG("With %d children running: %zd active user namespaces", num_childr= en, ret_during); + + /* Should have at least num_children more namespaces than baseline */ + ASSERT_GE(ret_during, ret_before + num_children); + + /* Signal all children to exit */ + for (i =3D 0; i < num_children; i++) { + char c =3D 'X'; + if (write(sv[0], &c, 1) !=3D 1) { + /* If we fail to write, kill remaining children */ + close(sv[0]); + for (int j =3D i; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + close(sv[0]); + + /* Wait for all children */ + for (i =3D 0; i < num_children; i++) { + int status; + waitpid(pids[i], &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + } + + /* Verify we're back to baseline */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After all children exit: %zd active user namespaces", ret_after); + ASSERT_EQ(ret_before, ret_after); +} + +/* + * Test rapid namespace creation with different namespace types. + * Create multiple types of namespaces rapidly to stress the tracking syst= em. + */ +TEST(rapid_mixed_namespace_creation) +{ + 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, + }; + __u64 ns_ids_before[512], ns_ids_after[512]; + ssize_t ret_before, ret_after; + int i; + + /* Get baseline count */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active namespaces (all types)", ret_before); + + /* Rapidly create and destroy namespaces with multiple types */ + for (i =3D 0; i < 50; i++) { + pid_t pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + /* Child: create multiple namespace types */ + if (setup_userns() < 0) + exit(1); + + /* Create additional namespace types */ + if (unshare(CLONE_NEWNET) < 0) + exit(1); + if (unshare(CLONE_NEWUTS) < 0) + exit(1); + if (unshare(CLONE_NEWIPC) < 0) + exit(1); + + exit(0); + } + + /* Parent: wait for child */ + int status; + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + } + + /* Verify we're back to baseline */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After 50 rapid mixed namespace cycles: %zd active namespaces", re= t_after); + ASSERT_EQ(ret_before, ret_after); +} + +/* + * Test nested namespace creation under stress. + * Create deeply nested namespace hierarchies and verify proper cleanup. + */ +TEST(nested_namespace_stress) +{ + 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 ns_ids_before[512], ns_ids_after[512]; + ssize_t ret_before, ret_after; + int i; + + /* Get baseline */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active user namespaces", ret_before); + + /* Create 20 processes, each with nested user namespaces */ + for (i =3D 0; i < 20; i++) { + pid_t pid =3D fork(); + ASSERT_GE(pid, 0); + + if (pid =3D=3D 0) { + int userns_fd; + uid_t orig_uid =3D getuid(); + int depth; + + /* Create nested user namespaces (up to 5 levels) */ + for (depth =3D 0; depth < 5; depth++) { + userns_fd =3D get_userns_fd(0, (depth =3D=3D 0) ? orig_uid : 0, 1); + if (userns_fd < 0) + exit(1); + + if (setns(userns_fd, CLONE_NEWUSER) < 0) { + close(userns_fd); + exit(1); + } + close(userns_fd); + } + + exit(0); + } + + /* Parent: wait for child */ + int status; + waitpid(pid, &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + } + + /* Verify we're back to baseline */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After 20 nested namespace hierarchies: %zd active user namespaces= ", ret_after); + ASSERT_EQ(ret_before, ret_after); +} + +/* + * Test listns() pagination under stress. + * Create many namespaces and verify pagination works correctly. + */ +TEST(listns_pagination_stress) +{ + 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, + }; + pid_t pids[30]; + int num_children =3D 30; + int i; + int sv[2]; + __u64 all_ns_ids[512]; + int total_found =3D 0; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + /* Create many children with user namespaces */ + for (i =3D 0; i < num_children; i++) { + pids[i] =3D fork(); + ASSERT_GE(pids[i], 0); + + if (pids[i] =3D=3D 0) { + char c; + close(sv[0]); + + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + /* Signal parent we're ready */ + if (write(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + /* Wait for parent signal to exit */ + if (read(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + close(sv[1]); + exit(0); + } + } + + close(sv[1]); + + /* Wait for all children to signal ready */ + for (i =3D 0; i < num_children; i++) { + char c; + if (read(sv[0], &c, 1) !=3D 1) { + /* If we fail to read, kill all children and exit */ + close(sv[0]); + for (int j =3D 0; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + /* Paginate through all namespaces using small batch sizes */ + req.ns_id =3D 0; + while (1) { + __u64 batch[5]; /* Small batch size to force pagination */ + ssize_t ret; + + ret =3D sys_listns(&req, batch, ARRAY_SIZE(batch), 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) { + close(sv[0]); + for (i =3D 0; i < num_children; i++) + kill(pids[i], SIGKILL); + for (i =3D 0; i < num_children; i++) + waitpid(pids[i], NULL, 0); + SKIP(return, "listns() not supported"); + } + ASSERT_GE(ret, 0); + } + + if (ret =3D=3D 0) + break; + + /* Store results */ + for (i =3D 0; i < ret && total_found < 512; i++) { + all_ns_ids[total_found++] =3D batch[i]; + } + + /* Update cursor for next batch */ + if (ret =3D=3D ARRAY_SIZE(batch)) + req.ns_id =3D batch[ret - 1]; + else + break; + } + + TH_LOG("Paginated through %d user namespaces", total_found); + + /* Verify no duplicates in pagination */ + for (i =3D 0; i < total_found; i++) { + for (int j =3D i + 1; j < total_found; j++) { + if (all_ns_ids[i] =3D=3D all_ns_ids[j]) { + TH_LOG("Found duplicate ns_id: %llu at positions %d and %d", + (unsigned long long)all_ns_ids[i], i, j); + ASSERT_TRUE(false); + } + } + } + + /* Signal all children to exit */ + for (i =3D 0; i < num_children; i++) { + char c =3D 'X'; + if (write(sv[0], &c, 1) !=3D 1) { + close(sv[0]); + for (int j =3D i; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + close(sv[0]); + + /* Wait for all children */ + for (i =3D 0; i < num_children; i++) { + int status; + waitpid(pids[i], &status, 0); + } +} + +/* + * Test concurrent namespace operations. + * Multiple processes creating, querying, and destroying namespaces concur= rently. + */ +TEST(concurrent_namespace_operations) +{ + 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_before[512], ns_ids_after[512]; + ssize_t ret_before, ret_after; + pid_t pids[20]; + int num_workers =3D 20; + int i; + + /* Get baseline */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active namespaces", ret_before); + + /* Create worker processes that do concurrent operations */ + for (i =3D 0; i < num_workers; i++) { + pids[i] =3D fork(); + ASSERT_GE(pids[i], 0); + + if (pids[i] =3D=3D 0) { + /* Each worker: create namespaces, list them, repeat */ + int iterations; + + for (iterations =3D 0; iterations < 10; iterations++) { + int userns_fd; + __u64 temp_ns_ids[100]; + ssize_t ret; + + /* Create a user namespace */ + userns_fd =3D get_userns_fd(0, getuid(), 1); + if (userns_fd < 0) + continue; + + /* List namespaces */ + ret =3D sys_listns(&req, temp_ns_ids, ARRAY_SIZE(temp_ns_ids), 0); + (void)ret; + + close(userns_fd); + + /* Small delay */ + usleep(1000); + } + + exit(0); + } + } + + /* Wait for all workers */ + for (i =3D 0; i < num_workers; i++) { + int status; + waitpid(pids[i], &status, 0); + ASSERT_TRUE(WIFEXITED(status)); + ASSERT_EQ(WEXITSTATUS(status), 0); + } + + /* Verify we're back to baseline */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After concurrent operations: %zd active namespaces", ret_after); + ASSERT_EQ(ret_before, ret_after); +} + +/* + * Test namespace churn - continuous creation and destruction. + * Simulates high-churn scenarios like container orchestration. + */ +TEST(namespace_churn) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWUSER | CLONE_NEWNET | CLONE_NEWUTS, + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + __u64 ns_ids_before[512], ns_ids_after[512]; + ssize_t ret_before, ret_after; + int cycle; + + /* Get baseline */ + 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"); + ASSERT_GE(ret_before, 0); + } + + TH_LOG("Baseline: %zd active namespaces", ret_before); + + /* Simulate churn: batches of namespaces created and destroyed */ + for (cycle =3D 0; cycle < 10; cycle++) { + pid_t batch_pids[10]; + int i; + + /* Create batch */ + for (i =3D 0; i < 10; i++) { + batch_pids[i] =3D fork(); + ASSERT_GE(batch_pids[i], 0); + + if (batch_pids[i] =3D=3D 0) { + /* Create multiple namespace types */ + if (setup_userns() < 0) + exit(1); + if (unshare(CLONE_NEWNET) < 0) + exit(1); + if (unshare(CLONE_NEWUTS) < 0) + exit(1); + + /* Keep namespaces alive briefly */ + usleep(10000); + exit(0); + } + } + + /* Wait for batch to complete */ + for (i =3D 0; i < 10; i++) { + int status; + waitpid(batch_pids[i], &status, 0); + } + } + + /* Verify we're back to baseline */ + ret_after =3D sys_listns(&req, ns_ids_after, ARRAY_SIZE(ns_ids_after), 0); + ASSERT_GE(ret_after, 0); + + TH_LOG("After 10 churn cycles (100 namespace sets): %zd active namespaces= ", ret_after); + ASSERT_EQ(ret_before, ret_after); +} + +TEST_HARNESS_MAIN --=20 2.47.3 From nobody Sun Feb 8 07:58:47 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 9EC9931A053; Fri, 24 Oct 2025 10:59: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=1761303565; cv=none; b=sPh+42rNnvXvX63m1qQkHCMgl517SpdG8W2TgT+6i8upuaThxTR2V/hbzC2gxSL6vmsMRehpsUaYvOurOXM6z9q/1IJ3zQjGQFwwkhTmfO6S6000MR0/oUvcgM3XStEDoOav7UG8e8HTdrD1JuCrWsku/EteCoTsvAKR2BARXrc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761303565; c=relaxed/simple; bh=QwDkSH3kLhu9Ya7BrIayv5fawfziMOL3Z/w1iCrFClA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=scrvy6DTZvMuHGWqDqsrhJeUwj3xve6ij20nk6eAVriiUpqAhB98iobvoXHXYIis3lAqbRBGzsk7eCyR3HaDE3He72G9nsWOF5TARkDNK8b5L3lQ+of3uLIAGCCai4/v2uOCFicM5D/lPIrFaylr761nD31biCKE+0eS2c64qPw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=W5fkK2O6; 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="W5fkK2O6" Received: by smtp.kernel.org (Postfix) with ESMTPSA id EF4C7C4CEF5; Fri, 24 Oct 2025 10:59:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1761303565; bh=QwDkSH3kLhu9Ya7BrIayv5fawfziMOL3Z/w1iCrFClA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=W5fkK2O6ood/eZ2MioGr5FOn8MmFQgD5BK6WGd1JeyrwnpVvGLZEYHcG6bPgBzYIs Y+336uTvHOglol8wNJCZvPtXdrEDGJr4/0OcjlAuY+mxGIcIEuObbol67F3Ii3jfVV Iy1UQBgGyesZQTK5pQbEefGHsZvUC+QOVj2H+/F/Iu9S7Yv4KF2asv4dJdfdkLCY28 qa1eswPqtIUJdHU6A7XqqiCl3+FUGq9ClRaPm+U/Q4t5jLyv48rZCJpWIsJt85elvp tdW4PRDx09+DGk8pMigmVYFmFDaO60Tn5v9TOqWXs6ioFnNYyYhBw57oOFoDrh54l2 qyZcM9wQG2ZKw== From: Christian Brauner Date: Fri, 24 Oct 2025 12:53:39 +0200 Subject: [PATCH v3 70/70] selftests/namespace: test listns() pagination 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: <20251024-work-namespace-nstree-listns-v3-70-b6241981b72b@kernel.org> References: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@kernel.org> In-Reply-To: <20251024-work-namespace-nstree-listns-v3-0-b6241981b72b@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=5137; i=brauner@kernel.org; h=from:subject:message-id; bh=QwDkSH3kLhu9Ya7BrIayv5fawfziMOL3Z/w1iCrFClA=; b=owGbwMvMwCU28Zj0gdSKO4sYT6slMWT8juow+zIx/fDv6H+C/RdiSyec6pjWoPXUwj55555dR 3/7KAqHdZSyMIhxMciKKbI4tJuEyy3nqdhslKkBM4eVCWQIAxenAEzkohnDf++O1yWdBXr3tb58 LF/AfGue19KoIBGbV0IrKy3uGN2UzGH47/LuQgrz69u3Zqt6P6tNbtzx4MXKx5ei2U5WWRV9z5C 6wwgA X-Developer-Key: i=brauner@kernel.org; a=openpgp; fpr=4880B8C9BD0E5106FC070F4F7B3C391EFEA93624 Minimal test case to reproduce KASAN out-of-bounds in listns pagination. Signed-off-by: Christian Brauner Reviewed-by: Jeff Layton --- tools/testing/selftests/namespaces/.gitignore | 1 + tools/testing/selftests/namespaces/Makefile | 4 +- .../selftests/namespaces/listns_pagination_bug.c | 138 +++++++++++++++++= ++++ 3 files changed, 142 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/namespaces/.gitignore b/tools/testing/= selftests/namespaces/.gitignore index f6dcf769f150..f4d2209ca4e4 100644 --- a/tools/testing/selftests/namespaces/.gitignore +++ b/tools/testing/selftests/namespaces/.gitignore @@ -7,3 +7,4 @@ listns_permissions_test siocgskns_test cred_change_test stress_test +listns_pagination_bug diff --git a/tools/testing/selftests/namespaces/Makefile b/tools/testing/se= lftests/namespaces/Makefile index 3c776740f3ac..01569e0abbdb 100644 --- a/tools/testing/selftests/namespaces/Makefile +++ b/tools/testing/selftests/namespaces/Makefile @@ -10,7 +10,8 @@ TEST_GEN_PROGS :=3D nsid_test \ listns_permissions_test \ siocgskns_test \ cred_change_test \ - stress_test + stress_test \ + listns_pagination_bug =20 include ../lib.mk =20 @@ -20,4 +21,5 @@ $(OUTPUT)/listns_permissions_test: ../filesystems/utils.c $(OUTPUT)/siocgskns_test: ../filesystems/utils.c $(OUTPUT)/cred_change_test: ../filesystems/utils.c $(OUTPUT)/stress_test: ../filesystems/utils.c +$(OUTPUT)/listns_pagination_bug: ../filesystems/utils.c =20 diff --git a/tools/testing/selftests/namespaces/listns_pagination_bug.c b/t= ools/testing/selftests/namespaces/listns_pagination_bug.c new file mode 100644 index 000000000000..da7d33f96397 --- /dev/null +++ b/tools/testing/selftests/namespaces/listns_pagination_bug.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest_harness.h" +#include "../filesystems/utils.h" +#include "wrappers.h" + +/* + * Minimal test case to reproduce KASAN out-of-bounds in listns pagination. + * + * The bug occurs when: + * 1. Filtering by a specific namespace type (e.g., CLONE_NEWUSER) + * 2. Using pagination (req.ns_id !=3D 0) + * 3. The lookup_ns_id_at() call in do_listns() passes ns_type=3D0 instead= of + * the filtered type, causing it to search the unified tree and potenti= ally + * return a namespace of the wrong type. + */ +TEST(pagination_with_type_filter) +{ + struct ns_id_req req =3D { + .size =3D sizeof(req), + .spare =3D 0, + .ns_id =3D 0, + .ns_type =3D CLONE_NEWUSER, /* Filter by user namespace */ + .spare2 =3D 0, + .user_ns_id =3D 0, + }; + pid_t pids[10]; + int num_children =3D 10; + int i; + int sv[2]; + __u64 first_batch[3]; + ssize_t ret; + + ASSERT_EQ(socketpair(AF_UNIX, SOCK_STREAM, 0, sv), 0); + + /* Create children with user namespaces */ + for (i =3D 0; i < num_children; i++) { + pids[i] =3D fork(); + ASSERT_GE(pids[i], 0); + + if (pids[i] =3D=3D 0) { + char c; + close(sv[0]); + + if (setup_userns() < 0) { + close(sv[1]); + exit(1); + } + + /* Signal parent we're ready */ + if (write(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + /* Wait for parent signal to exit */ + if (read(sv[1], &c, 1) !=3D 1) { + close(sv[1]); + exit(1); + } + + close(sv[1]); + exit(0); + } + } + + close(sv[1]); + + /* Wait for all children to signal ready */ + for (i =3D 0; i < num_children; i++) { + char c; + if (read(sv[0], &c, 1) !=3D 1) { + close(sv[0]); + for (int j =3D 0; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + /* First batch - this should work */ + ret =3D sys_listns(&req, first_batch, 3, 0); + if (ret < 0) { + if (errno =3D=3D ENOSYS) { + close(sv[0]); + for (i =3D 0; i < num_children; i++) + kill(pids[i], SIGKILL); + for (i =3D 0; i < num_children; i++) + waitpid(pids[i], NULL, 0); + SKIP(return, "listns() not supported"); + } + ASSERT_GE(ret, 0); + } + + TH_LOG("First batch returned %zd entries", ret); + + if (ret =3D=3D 3) { + __u64 second_batch[3]; + + /* Second batch - pagination triggers the bug */ + req.ns_id =3D first_batch[2]; /* Continue from last ID */ + ret =3D sys_listns(&req, second_batch, 3, 0); + + TH_LOG("Second batch returned %zd entries", ret); + ASSERT_GE(ret, 0); + } + + /* Signal all children to exit */ + for (i =3D 0; i < num_children; i++) { + char c =3D 'X'; + if (write(sv[0], &c, 1) !=3D 1) { + close(sv[0]); + for (int j =3D i; j < num_children; j++) + kill(pids[j], SIGKILL); + for (int j =3D 0; j < num_children; j++) + waitpid(pids[j], NULL, 0); + ASSERT_TRUE(false); + } + } + + close(sv[0]); + + /* Cleanup */ + for (i =3D 0; i < num_children; i++) { + int status; + waitpid(pids[i], &status, 0); + } +} + +TEST_HARNESS_MAIN --=20 2.47.3