From: "Chuck Lever" <cel@kernel.org>
To: "Hannes Reinecke" <hare@suse.de>,
"Christian Brauner" <brauner@kernel.org>
Cc: keyrings@vger.kernel.org, kernel-tls-handshake@lists.linux.dev,
netdev@vger.kernel.org, "Trond Myklebust" <trondmy@kernel.org>,
"Anna Schumaker" <anna@kernel.org>,
"Christoph Hellwig" <hch@lst.de>,
"David Howells" <dhowells@redhat.com>,
"Jarkko Sakkinen" <jarkko@kernel.org>,
"Sagi Grimberg" <sagi@grimberg.me>,
linux-nfs@vger.kernel.org
Subject: Re: [RFC] NFS: named client identities for mTLS mounts and a per-namespace .nfs keyring
Date: Fri, 11 Sep 2026 15:20:13 -0400 [thread overview]
Message-ID: <4ff29ed1-e963-4010-a7a1-73b229cc8bd0@app.fastmail.com> (raw)
In-Reply-To: <bb9a872a-d4aa-467a-b4c9-7bca174a6bbc@suse.de>
Christian, we're interested in the question below about user-ns
versus net-ns for keyring ownership.
On Tue, Jun 2, 2026, at 9:39 PM, Hannes Reinecke wrote:
> 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
> hare@suse.de +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
--
Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)
next prev parent reply other threads:[~2026-09-11 19:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-02 15:47 [RFC] NFS: named client identities for mTLS mounts and a per-namespace .nfs keyring Chuck Lever
2026-06-03 1:39 ` Hannes Reinecke
2026-06-03 14:27 ` Chuck Lever
2026-06-05 21:32 ` Sagi Grimberg
2026-06-05 22:07 ` Chuck Lever
2026-09-11 19:20 ` Chuck Lever [this message]
2026-06-05 21:44 ` Sagi Grimberg
2026-06-06 6:50 ` Hannes Reinecke
2026-09-13 16:05 ` Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4ff29ed1-e963-4010-a7a1-73b229cc8bd0@app.fastmail.com \
--to=cel@kernel.org \
--cc=anna@kernel.org \
--cc=brauner@kernel.org \
--cc=dhowells@redhat.com \
--cc=hare@suse.de \
--cc=hch@lst.de \
--cc=jarkko@kernel.org \
--cc=kernel-tls-handshake@lists.linux.dev \
--cc=keyrings@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=sagi@grimberg.me \
--cc=trondmy@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox