From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (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 163794E2F07; Fri, 25 Sep 2026 19:16:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790363802; cv=none; b=RcagKU5S9cEtT8i+7DzJzKgMlZsqzAmWIkLPl6JEKVQx3dTm2ikJEjkRgDib1dBT0fCu0sSNH1TvqQB+CiXEPq4wSmp6NPcBG2T+tuiUF1sk3d60rJ67ldaTr8fFfNiYWWiTkgDTk1WbYDNdFNjwCsohNqKJmiK6ZrjqNp6DMwo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790363802; c=relaxed/simple; bh=KBQ45uEsnPiS9q4BtxHEsGEJscvlRLmVHvTHnHFbsgY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=b5udWwn40FflNA93sUGARb3jxyfF25fnNWHOgBY5PM6j/ACFP5AnPJFUpIUCMIP1WRy8lMMotFgM2cI113njfVUgeLdnwubEXHGELt3Ant/pfGHiOkHI4HkMa7TtHAh3YJEziE/M+v907PFqvc5sPXFXgtkj4sP5RVeWdwTnSlM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=h7xB8zak; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="h7xB8zak" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 77CFE1F00898; Fri, 25 Sep 2026 19:16:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1790363800; bh=sSa7lUoM1JtWHx3tzZE/3Q9qFY63oIBNpQpRQV79Vlg=; h=From:Date:Subject:References:In-Reply-To:To:Cc; b=h7xB8zakKU0vmv2mUhKpjXFNvf6FTiH8CpoeAl1U9F4VaOFdIFeq3p2ZNoqX2WIDm gb5KBlPnf2wxJiNFjY20NkUVxMGCWkmwphf81XIra7qSYaT//gM0TO836xTRjY8K+q 9DM59SKm9o9SkEealfnPRpOajS7nst+ejtBFuhvDoEa7o2Kc11oGxdfivjv3Bivd/S xlSPZOAztAtXHJ0+MoQSLjzOzJsCQUpmiivgEjGqdjh+ujKj/2yinUeOSIIxpQUfvW mDCXQHjLCtoECK78oqCwA6ATAxAqxTh5kqw8G91KWHtcw0hXn+rhjt74ZBLv4jpAuF a+aK0Bpap/MjA== From: Chuck Lever Date: Fri, 25 Sep 2026 15:16:24 -0400 Subject: [PATCH RFC v2 2/5] NFS: allocate the .nfs keyring per network namespace Precedence: bulk X-Mailing-List: linux-doc@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20260925-nfs-mtls-identity-v2-2-aa3ad17dd6c8@kernel.org> References: <20260925-nfs-mtls-identity-v2-0-aa3ad17dd6c8@kernel.org> In-Reply-To: <20260925-nfs-mtls-identity-v2-0-aa3ad17dd6c8@kernel.org> To: Trond Myklebust , Anna Schumaker , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Jonathan Corbet , Shuah Khan , Randy Dunlap , Christian Brauner , David Howells , Sagi Grimberg Cc: linux-nfs@vger.kernel.org, keyrings@vger.kernel.org, kernel-tls-handshake@lists.linux.dev, netdev@vger.kernel.org, linux-doc@vger.kernel.org, Chuck Lever X-Mailer: b4 0.16-dev-da966 X-Developer-Signature: v=1; a=openpgp-sha256; l=5131; i=cel@kernel.org; h=from:subject:message-id; bh=KBQ45uEsnPiS9q4BtxHEsGEJscvlRLmVHvTHnHFbsgY=; b=owEBbQKS/ZANAwAKATNqszNvZn+XAcsmYgBqtsiTfZ03+4rWe1K2ZnzhZhnbpiUQvEFYwOT7y krdAa9qjZ2JAjMEAAEKAB0WIQQosuWwEobfJDzyPv4zarMzb2Z/lwUCarbIkwAKCRAzarMzb2Z/ l4OHD/4833y49PBQ3P56Ugab481LWMcDRJl7MLyuORF/kr9ZdPC+nqzM0Ed+94qJZgndJ/dW4CR ZrySpsOPnTbtQEgatZD/UuSH3myIJUs7FlSh8QIjLHWAPEUhgizdr1BBYlkz8FEaENlugOE/bj/ jN38lk14frA0DgoNap/ixgmx/kqo0gLztNkUEJHFvZdZ7OKTuupe+xUyXPCgogZUtVOYlALTZln lbpn4tot569TIwGksnypc2zEdUyqWVZIztDze9oEC07RsCdIilKU5RTo/+MEZ4qbHxEm6LCKqB7 cA0nsx8U/HJJBjUwfDN2qAdfrhZ0lbiS70oY5fRfmH5wYpwxGByH/GQ/aWSIpN3GFtdAmxU3bUU OWeUX5DBnZSOdfnn4rrKhZuniuZWKDE1bz/nYAbc9CUT5cVDJ2zb14EorXGKMXlkb9DvErkZ8OU Llc6QRBtRyaDhH8IB6Dk43NuIMa+INPfSLk7WMJI9Zz/87FvVzgJ/q+O/X8T+v1DibkRn99Z1eq o8qqW7rKY67qUvDrUPXui8D9My4Lr5OJgh4MK+U74QDWFY1u9zN4AOseen4+euh9ogA4vxNZMG6 DZ8qKJvS98/smZEy2tUC6qbQSUZl4fZwGZBACPQUnJ2iI34SwcjIlYb+gf+7qfDL2BffDtqpqSi d1Cu1BehG1vO/MQ== X-Developer-Key: i=cel@kernel.org; a=openpgp; fpr=28B2E5B01286DF243CF23EFE336AB3336F667F97 Commit 87268f7a4f1f ("nfs: create a kernel keyring") allocates one .nfs keyring at module load, and nothing in the NFS client reads it. One module-wide keyring also cannot isolate x.509 credentials between network namespaces. Each tlshd instance services the handshake socket of one network namespace, so a credential provisioned for that namespace's mounts has to be reachable by that tlshd and by no other. Allocate one .nfs keyring per network namespace in nfs_net_init() and release it in nfs_net_exit(). tlshd finds a keyring by name through /proc/keys, which is not namespace scoped, so each handshake request has to carry the keyring serial number instead. Allocate the keyring under a kernel credential rather than that of the task creating the namespace, so an LSM labels every namespace's keyring the same way. The keyring grants its owner every permission and everyone else none. Make the owner of the network namespace's user namespace the keyring's owner, so that in a container with its own user namespace the container's root can provision the keyring and its tlshd can link it. Signed-off-by: Chuck Lever --- fs/nfs/inode.c | 83 ++++++++++++++++++++++++++++++++-------------------------- fs/nfs/netns.h | 2 ++ 2 files changed, 48 insertions(+), 37 deletions(-) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 832923be43a9..2b494fa5ecc0 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -2641,11 +2641,52 @@ static int nfsiod_start(void) unsigned int nfs_net_id; EXPORT_SYMBOL_GPL(nfs_net_id); +#ifdef CONFIG_KEYS +static int nfs_init_keyring(struct net *net) +{ + struct nfs_net *nn = net_generic(net, nfs_net_id); + struct cred *cred; + struct key *keyring; + + cred = prepare_kernel_cred(&init_task); + if (!cred) + return -ENOMEM; + keyring = keyring_alloc(".nfs", net->user_ns->owner, + net->user_ns->group, cred, + (KEY_POS_ALL & ~KEY_POS_SETATTR) | + (KEY_USR_ALL & ~KEY_USR_SETATTR), + KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); + put_cred(cred); + if (IS_ERR(keyring)) + return PTR_ERR(keyring); + nn->nfs_keyring = keyring; + return 0; +} + +static void nfs_exit_keyring(struct nfs_net *nn) +{ + key_put(nn->nfs_keyring); +} +#else +static inline int nfs_init_keyring(struct net *net) +{ + return 0; +} + +static inline void nfs_exit_keyring(struct nfs_net *nn) +{ +} +#endif /* CONFIG_KEYS */ + static int nfs_net_init(struct net *net) { struct nfs_net *nn = net_generic(net, nfs_net_id); int err; + err = nfs_init_keyring(net); + if (err) + return err; + nfs_clients_init(net); if (!rpc_proc_register(net, &nn->rpcstats)) { @@ -2663,14 +2704,18 @@ static int nfs_net_init(struct net *net) rpc_proc_unregister(net, "nfs"); err_proc_rpc: nfs_clients_exit(net); + nfs_exit_keyring(nn); return err; } static void nfs_net_exit(struct net *net) { + struct nfs_net *nn = net_generic(net, nfs_net_id); + rpc_proc_unregister(net, "nfs"); nfs_fs_proc_net_exit(net); nfs_clients_exit(net); + nfs_exit_keyring(nn); } static struct pernet_operations nfs_net_ops = { @@ -2680,35 +2725,6 @@ static struct pernet_operations nfs_net_ops = { .size = sizeof(struct nfs_net), }; -#ifdef CONFIG_KEYS -static struct key *nfs_keyring; - -static int __init nfs_init_keyring(void) -{ - nfs_keyring = keyring_alloc(".nfs", - GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, - current_cred(), - (KEY_POS_ALL & ~KEY_POS_SETATTR) | - (KEY_USR_ALL & ~KEY_USR_SETATTR), - KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL); - return PTR_ERR_OR_ZERO(nfs_keyring); -} - -static void nfs_exit_keyring(void) -{ - key_put(nfs_keyring); -} -#else -static inline int nfs_init_keyring(void) -{ - return 0; -} - -static inline void nfs_exit_keyring(void) -{ -} -#endif /* CONFIG_KEYS */ - /* * Initialize NFS */ @@ -2716,13 +2732,9 @@ static int __init init_nfs_fs(void) { int err; - err = nfs_init_keyring(); - if (err) - return err; - err = nfs_sysfs_init(); if (err < 0) - goto err_keyring; + return err; err = register_pernet_subsys(&nfs_net_ops); if (err < 0) @@ -2779,8 +2791,6 @@ static int __init init_nfs_fs(void) unregister_pernet_subsys(&nfs_net_ops); err_sysfs: nfs_sysfs_exit(); -err_keyring: - nfs_exit_keyring(); return err; } @@ -2796,7 +2806,6 @@ static void __exit exit_nfs_fs(void) nfs_fs_proc_exit(); nfsiod_stop(); nfs_sysfs_exit(); - nfs_exit_keyring(); } /* Not quite true; I just maintain it */ diff --git a/fs/nfs/netns.h b/fs/nfs/netns.h index 36658579100d..da0854510404 100644 --- a/fs/nfs/netns.h +++ b/fs/nfs/netns.h @@ -16,6 +16,7 @@ struct bl_dev_msg { uint32_t major, minor; }; +struct key; struct nfs_netns_client; struct nfs_net { @@ -36,6 +37,7 @@ struct nfs_net { #endif /* CONFIG_NFS_V4 */ struct nfs_netns_client *nfs_client; spinlock_t nfs_client_lock; + struct key *nfs_keyring; ktime_t boot_time; struct rpc_stat rpcstats; #ifdef CONFIG_PROC_FS -- 2.55.0