This repository was archived by the owner on Oct 1, 2026. It is now read-only.
NFS mTLS client identity management - #163
Merged
Merged
Conversation
tlshd links the .nfs and .nfsd keyrings into its session keyring when it starts and when it reloads its configuration. The kernel creates each keyring when the owning module loads, so a tlshd that starts before nfs.ko or nfsd.ko is loaded never possesses the keyring, and a handshake that names a key on it fails with EACCES until the administrator sends tlshd a SIGHUP. tlshd starts before remote-fs-pre.target, so on a freshly booted NFS client that is the common ordering. The startup link also hands possession of every NFS credential to the long-lived parent and to every handshake child, whether or not the handshake uses them. The handshake upcall already carries a keyring serial that the kernel links into the process keyring of the child that accepts the request. That link is private to the child and is released when it exits. Give handshakes whose request names no keyring the same treatment: link .nfs into the process keyring of a client handshake child, and .nfsd into that of a server handshake child, just before the child reads its certificate from the keyring. By then the keyring exists, since the kernel handed out serials on it, so the startup ordering no longer matters. The .nvme keyring keeps its startup link. The child also links the keyring the request named into its session keyring and unlinks it when the handshake is done. The session keyring is shared with the parent and with every sibling child, so that link grants possession beyond the one handshake for as long as it lasts. The kernel's process keyring link has been present since the handshake upcall was introduced, so drop the session keyring link and unlink. The server PSK callbacks find the peer's key by description, and a search of the session keyring does not reach the process keyring, so search the process keyring first. Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
An xprtsec=mtls mount names its client certificate and private key by keyring serial. The administrator loads both into a keyring by hand, reads the serials back, and pastes them onto the mount command line, where they are opaque, differ on every boot, and are easy to transpose. The keys also sit wherever the administrator put them, readable by whatever can reach that keyring. Add nfstlskey, which provisions a named identity onto the .nfs keyring of the caller's network namespace as a pair of "user" keys readable by possessors only. It converts PEM input to DER, refuses a certificate chain or a key that does not match the certificate, prints the mount options that select an identity, and replaces the key material of one in place so that a renewed certificate reaches mounts without a remount. nfstlskey(8) documents the tool and its keyring layout. The tool locates the namespace keyring through the nfs_keyring key type. A kernel without that type has a single .nfs keyring, created at nfs module load since v6.17, that tlshd already links into its session keyring. When the nfs_keyring request fails with ENOKEY after nfs.ko is loaded, find that keyring by scanning /proc/keys, the way tlshd does, and continue with the same trust check, link, and key management. Only the kernel can create a keyring whose name begins with a period, so the scan cannot be answered by a keyring another process planted. Report on stderr that the shared keyring is in use, since identities on it are visible to mounts in every network namespace. Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
tlshd_x509_retrieve_key_cb() logs "Selecting x509.certificate from conf file" whenever it hands GnuTLS the non-PQ certificate. A handshake request that carries certificate and private key serials loads that certificate from the keyring, so on every keyring-based handshake the line names the wrong source, right after the line that reports the keyring read. Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
tlshd links the .nfs and .nfsd keyrings into its session keyring only at
startup and on SIGHUP. The kernel creates each keyring when nfs.ko or
nfsd.ko loads, and tlshd starts before remote-fs-pre.target, so on a
freshly booted client a handshake naming a key on .nfs fails with EACCES
until an administrator sends SIGHUP. The startup link also hands every
NFS credential in the keyring to the long-lived tlshd parent and to
every handshake child, whether or not that handshake uses them.
This series moves the link to per-handshake instead: a handshake child
links .nfs or .nfsd into its own process keyring just before it reads
its certificate, by which point the keyring already exists, so startup
ordering no longer matters.
nfstlskey provisions NFS mTLS client identities onto that same .nfs
keyring, in place of an administrator loading keys by hand and pasting
boot-variable, opaque serials onto mount command lines. It locates the
keyring through the nfs_keyring key type where available, and on a
kernel without that type falls back to the same /proc/keys scan tlshd
itself uses to find the keyring the kernel creates at module load.