Re: [RFC] NFS: named client identities for mTLS mounts and a per-namespace .nfs keyring

Hannes Reinecke <[email protected]> Wed, 3 Jun 2026 03:39:29 +0200
Newsgroups dev.linux.lists.kernel-tls-handshake,org.kernel.vger.keyrings,org.kernel.vger.linux-nfs,org.kernel.vger.netdev
Message-ID <[email protected]>
On 6/2/26 17:47, Chuck Lever wrote:
> Today, exactly one x.509 certificate and private key pair can be
> used at a time for all NFS mounts. The location of that pair is
> set in /etc/tlshd/config.
> 
> We currently have an awkward experimental mechanism for specifying
> an alternative x.509 certificate and private key for an xprtsec=mtls
> NFS mount, but it needs to be completed so it can be documented and
> advertised for use.
> 
> I asked Claude to write a rough draft of a design document that
> outlines what needs to be done to finish the work. I would like
> input on the kernel-side mechanism in particular for the
> per-network-namespace keyring and the way userspace reaches it.
> 
> 
> Problem
> =======
> 
> NFS mutual-TLS mounts (xprtsec=mtls) need the client to present an
> x.509 certificate and prove possession of its private key. The
> handshake runs in userspace in tlshd; the kernel hands tlshd the
> credentials by keyring serial number over the handshake genetlink
> upcall.
> 
> The only front end today is two undocumented integer mount options:
> 
>      mount -o xprtsec=mtls,cert_serial=723847,privkey_serial=723848 \
>            server:/export /mnt
> 
> The administrator must load the cert and key into the keyring out of
> band, discover the integer serials, and paste them onto the command
> line. Serials are opaque, non-reproducible across boots, and easy to
> transpose. There is also no isolation: nfs_tls_key_verify() does a
> global key_lookup() on the serial, and the .nfs keyring created in
> fs/nfs/inode.c is module-global and never referenced again -- any tlshd
> that learns a serial can read the key.
> 
> This RFC proposes a named, per-mount client-identity interface backed
> by a provisioning CLI, and fixes the keyring to isolate credentials per
> network namespace. The kernel handshake ABI (integer serials over
> genetlink) does not change.
> 
> 
> The cross-subsystem ask: a per-netns .nfs keyring
> =================================================
> 
> Network namespace is the correct isolation domain. tlshd is bound to a
> network namespace, not a user namespace: it services sockets passed up
> from the kernel over the per-netns handshake genetlink socket, and one
> tlshd runs per network namespace that needs TLS-protected mounts.
> 
>    - Replace the dead module-global .nfs keyring with one keyring per
>      network namespace, held in struct nfs_net (fs/nfs/netns.h) and
>      allocated at nfs_net_init(). The keys subsystem otherwise
>      namespaces on user_namespace, so this is a kernel-held object
>      referenced from nfs_net (like today's global keyring, but one per
>      netns). The DNS resolver's per-netns key scoping (net->key_domain,
>      request_key_net()) is precedent that netns-scoped key handling is
>      acceptable.
> 
>    - tlshd attaches at handshake time, not at launch. This matters: the
>      keyring may be empty or freshly created when tlshd starts, so
>      linking it by name at startup is the wrong model. Instead NFS sets
>      ta_keyring to the netns .nfs keyring serial in
>      xs_tls_handshake_sync(), the kernel sends it as
>      HANDSHAKE_A_ACCEPT_KEYRING, and tlshd links that serial into its
>      session keyring per handshake -- the path tlshd already implements.
>      Linking grants tlshd possession of the keyring and, through it, of
>      the possessor-scoped cert and privkey keys.
> 
>    - Credential keys are created possessor-readable only (no
>      KEY_USR_READ). That is what makes isolation enforceable rather
>      than advisory: a key provisioned in namespace A is absent from B's
>      keyring and unreadable by B's tlshd even if its serial leaks.
> 
> Open question, and where I most want input: userspace -- the
> provisioning CLI and mount.nfs -- needs to name the kernel-held netns
> keyring in order to add and search keys. Candidates, modeled on
> KEYCTL_GET_PERSISTENT (security/keys/persistent.c):
> 
>    (a) a new keyctl command that links the caller's netns .nfs keyring
>        into a destination keyring and returns its serial;
>    (b) an NFS-specific request_key key type the module instantiates to
>        point at the netns keyring;
>    (c) a per-netns serial exported via procfs or netlink.
> 
> The per-netns keyring decision itself I consider settled; the retrieval
> primitive is the open one. There is also a user_namespace accounting
> nuance: keys added by userspace are quota-charged against a key_user
> keyed by user_namespace even though the keyring lives in nfs_net. I
> would like the keyrings folks to confirm the quota and ownership
> interaction is sane when the user_ns and net_ns boundaries do not
> coincide.
>

I am all for making keyrings namespace-aware. Logically I _think_ they
should be tagged per user-namespace, as this really is about the 
filesystem (and as such would warrant to be tagged per mount ns).
Tagging it per net-namespace is not a great fit (well, for me, at 
least), as also block devices might require keys to present the
bdev (eg nvme authentication)

I might be okay to have it tagged per net-namespace, though, as all
current users are in some shape or form being network related.
But I'm not sure if that stays that way, so I am worried if we're
not restricting ourselves to much by that choice.
As really, the question is: what is the driving the namespace selection?
Is it the _requesting_ layer, ie the layer issuing the mount() call?
Or is it the _providing_ layer, ie the layer providing the 
devices/interfaces where the mount() call is operating on?
If it's the former, then we need to tag is as
net-namespace. If it's the latter, then we need to tag it as a
user-namespace / mount-ns.

We should probably ask Christian ...

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                  Kernel Storage Architect
[email protected]                                +49 911 74053 688
SUSE Software Solutions GmbH, Frankenstr. 146, 90461 Nürnberg
HRB 36809 (AG Nürnberg), GF: I. Totev, A. McDonald, W. Knoblich