Netdev List
 help / color / mirror / Atom feed
From: Randy Dunlap <rdunlap@infradead.org>
To: Chuck Lever <cel@kernel.org>,
	Trond Myklebust <trondmy@kernel.org>,
	Anna Schumaker <anna@kernel.org>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Simon Horman <horms@kernel.org>, Jonathan Corbet <corbet@lwn.net>,
	Shuah Khan <skhan@linuxfoundation.org>,
	Christian Brauner <brauner@kernel.org>,
	David Howells <dhowells@redhat.com>,
	Sagi Grimberg <sagi@grimberg.me>
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
Subject: Re: [PATCH RFC 5/5] NFS: add a key type that reveals the namespace .nfs keyring serial
Date: Fri, 18 Sep 2026 11:00:52 -0700	[thread overview]
Message-ID: <8d635404-f85f-48fa-817a-88d3c1ecd344@infradead.org> (raw)
In-Reply-To: <20260918-nfs-mtls-identity-v1-5-197e568d78a7@kernel.org>

Hi,

On 9/18/26 7:05 AM, Chuck Lever wrote:
> The per-namespace .nfs keyring is linked into no keyring that
> userspace possesses, so a tool that provisions x509 credentials, or a
> mount helper that searches for them, cannot reach it. Every keyring
> operation from userspace takes a serial, and nothing hands this one
> out.
> 
> Register an "nfs_keyring" key type whose request_key handler runs in
> the caller's context, without an upcall, and instantiates the key
> with the serial of the caller's namespace .nfs keyring. Userspace
> reads the serial with one request_key() and one keyctl_read().
> 
> A keyring search runs before the handler does, and a task keeps its
> session keyring across setns(). The type carries KEY_TYPE_NET_DOMAIN
> so a key instantiated in one namespace does not answer a request from
> another. Its preparse accepts no payload but the caller's own serial,
> so a key planted by add_key() cannot misdirect a later request.
> 
> Register the type after register_pernet_subsys() has installed
> nfs_net_id, and unregister it before the per-namespace state goes
> away. unregister_key_type() waits for in-flight request_key() calls
> to drain, so the handler never runs against a freed struct nfs_net.
> 
> Signed-off-by: Chuck Lever <cel@kernel.org>
> ---
>  Documentation/filesystems/nfs/index.rst   |  1 +
>  Documentation/filesystems/nfs/keyring.rst | 67 ++++++++++++++++++++++
>  fs/nfs/inode.c                            | 94 ++++++++++++++++++++++++++++++-
>  3 files changed, 161 insertions(+), 1 deletion(-)
> 

This might be a locale thing, but using serial as a noun here seems
awkward to me.  Is this like "serial number" with the "number" omitted?

Serial as a noun usually means a publication in a series (TV, comics, etc.).

Or is this some special security-related usage of the word serial?

> diff --git a/Documentation/filesystems/nfs/keyring.rst b/Documentation/filesystems/nfs/keyring.rst
> new file mode 100644
> index 000000000000..5b3d3d0f5f91
> --- /dev/null
> +++ b/Documentation/filesystems/nfs/keyring.rst
> @@ -0,0 +1,67 @@
> +.. SPDX-License-Identifier: GPL-2.0
> +
> +====================================
> +The per-namespace NFS client keyring
> +====================================
> +
> +The NFS client holds one keyring, named ".nfs", per network
> +namespace. An xprtsec=mtls mount presents the client certificate and
> +private key named by its cert_serial= and privkey_serial= mount
> +options, and the handshake links the mount's namespace .nfs keyring
> +into tlshd before tlshd reads those keys. Keys placed on the .nfs
> +keyring therefore need not grant user read permission: tlshd reaches
> +them as a possessor, and a tlshd in another network namespace never
> +possesses them.
> +
> +The keyring is owned by global root, with KEY_POS_ALL and KEY_USR_ALL
> +less SETATTR. It is not charged to any quota. Keys added to it by
> +userspace are charged to the user that adds them.
> +
> +Finding the keyring serial
> +==========================
> +
> +The .nfs keyring is not linked into any keyring that userspace
> +possesses, so a serial is the only way to name it. The NFS client
> +registers a key type, "nfs_keyring", whose sole purpose is to hand
> +that serial out. Its request_key handler runs in the caller's context
> +and does not upcall to /sbin/request-key.
> +
> +To obtain the serial, request a key of type "nfs_keyring" with the
> +description ".nfs" and read its payload::
> +
> +	id=$(keyctl request2 nfs_keyring .nfs "" @s)
> +	serial=$(keyctl print $id)
> +
> +The contract of the key type is:
> +
> + * The description is the string ".nfs". Any other description is
> +   rejected with EINVAL before a key is allocated.
> +
> + * The callout info must be present. request_key() with a NULL
> +   callout_info never invokes a handler and returns ENOKEY when no
> +   matching key exists, so use request_key() with an empty string, or
> +   ``keyctl request2`` rather than ``keyctl request``. The content of
> +   the callout info is ignored.
> +
> + * The payload is the keyring serial as decimal ASCII digits with no
> +   terminating NUL. The return value of keyctl_read() gives the
> +   length; a buffer of 12 bytes is sufficient.
> +
> + * add_key() with this type accepts only that payload. A key carrying
> +   any other value is rejected with EINVAL, so a key found in the
> +   caller's keyrings always holds the serial of the caller's namespace.
> +
> + * The key type carries KEY_TYPE_NET_DOMAIN. A key instantiated in one
> +   network namespace does not answer a request made in another, so a
> +   process that keeps its session keyring across setns() receives the
> +   serial of the namespace it is in at the time of the request.
> +
> +The serial is not a secret. The keyring's own permissions decide what
> +a caller can do with it.
> +
> +Provisioning credentials
> +========================
> +
> +Add the client certificate and private key to the .nfs keyring as
> +keys that grant no user read permission, then pass their serials as
> +cert_serial= and privkey_serial= mount options.

thanks.
-- 
~Randy


  reply	other threads:[~2026-09-18 18:00 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-18 14:05 [PATCH RFC 0/5] NFS: isolate mTLS client credentials by network namespace Chuck Lever
2026-09-18 14:05 ` [PATCH RFC 1/5] NFS: name the init_nfs_fs() error labels Chuck Lever
2026-09-18 14:05 ` [PATCH RFC 2/5] NFS: allocate the .nfs keyring per network namespace Chuck Lever
2026-09-18 14:44   ` Hannes Reinecke
2026-09-18 15:15     ` Chuck Lever
2026-09-19 16:22     ` Chuck Lever
2026-09-18 14:05 ` [PATCH RFC 3/5] SUNRPC: pass a keyring serial to the TLS handshake Chuck Lever
2026-09-18 14:05 ` [PATCH RFC 4/5] NFS: name the namespace .nfs keyring in the x509 handshake Chuck Lever
2026-09-18 14:05 ` [PATCH RFC 5/5] NFS: add a key type that reveals the namespace .nfs keyring serial Chuck Lever
2026-09-18 18:00   ` Randy Dunlap [this message]
2026-09-19 15:59     ` Chuck Lever
2026-09-18 17:21 ` [PATCH RFC 0/5] NFS: isolate mTLS client credentials by network namespace Benjamin Coddington
2026-09-19 15:46   ` Chuck Lever
2026-09-21  8:45   ` Hannes Reinecke
2026-09-21 11:17     ` Benjamin Coddington

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=8d635404-f85f-48fa-817a-88d3c1ecd344@infradead.org \
    --to=rdunlap@infradead.org \
    --cc=anna@kernel.org \
    --cc=brauner@kernel.org \
    --cc=cel@kernel.org \
    --cc=corbet@lwn.net \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kernel-tls-handshake@lists.linux.dev \
    --cc=keyrings@vger.kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=sagi@grimberg.me \
    --cc=skhan@linuxfoundation.org \
    --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