From 7856eb255ef9ea70a3a4f5764c8f1fcdb72b0896 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Oct 2026 11:31:14 -0400 Subject: [PATCH] SUNRPC: pass a keyring serial number to the TLS handshake The handshake upcall links the keyring named in ta_keyring into tlshd's process keyring before tlshd reads the client certificate and private key. That link is how tlshd gains possession of keys that grant no user read permission. xprtsock never fills the field, so an x509 handshake can present only keys that tlshd's own credentials can read. Add a keyring serial number to struct xprtsec_parms and pass it to the x509 handshake, so an RPC client can name the keyring that holds its credentials. Signed-off-by: Chuck Lever Signed-off-by: Anna Schumaker --- fs/nfs/fs_context.c | 1 + fs/nfs/nfs3client.c | 1 + fs/nfs/nfs4client.c | 1 + include/linux/sunrpc/xprt.h | 1 + net/sunrpc/xprtsock.c | 1 + 5 files changed, 5 insertions(+) diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index 1967de7d1dff..f8f5f8b2954e 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -1750,6 +1750,7 @@ static int nfs_init_fs_context(struct fs_context *fc) ctx->minorversion = 0; ctx->need_mount = true; ctx->xprtsec.policy = RPC_XPRTSEC_NONE; + ctx->xprtsec.keyring_serial = TLS_NO_KEYRING; ctx->xprtsec.cert_serial = TLS_NO_CERT; ctx->xprtsec.privkey_serial = TLS_NO_PRIVKEY; diff --git a/fs/nfs/nfs3client.c b/fs/nfs/nfs3client.c index cf2f7be4b435..4d9d43f687e3 100644 --- a/fs/nfs/nfs3client.c +++ b/fs/nfs/nfs3client.c @@ -102,6 +102,7 @@ struct nfs_client *nfs3_set_ds_client(struct nfs_server *mds_srv, .cred = mds_srv->cred, .xprtsec = { .policy = RPC_XPRTSEC_NONE, + .keyring_serial = TLS_NO_KEYRING, .cert_serial = TLS_NO_CERT, .privkey_serial = TLS_NO_PRIVKEY, }, diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index fe779fb2ec72..5d054d3dced1 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -812,6 +812,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv, .cred = mds_srv->cred, .xprtsec = { .policy = RPC_XPRTSEC_NONE, + .keyring_serial = TLS_NO_KEYRING, .cert_serial = TLS_NO_CERT, .privkey_serial = TLS_NO_PRIVKEY, }, diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index a82045804d34..005730623f3b 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -145,6 +145,7 @@ struct xprtsec_parms { enum xprtsec_policies policy; /* authentication material */ + key_serial_t keyring_serial; key_serial_t cert_serial; key_serial_t privkey_serial; }; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index f5a5136327ba..77e4c87bf2e1 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2637,6 +2637,7 @@ static int xs_tls_handshake_sync(struct rpc_xprt *lower_xprt, struct xprtsec_par goto out_put_xprt; break; case RPC_XPRTSEC_TLS_X509: + args.ta_keyring = xprtsec->keyring_serial; args.ta_my_cert = xprtsec->cert_serial; args.ta_my_privkey = xprtsec->privkey_serial; rc = tls_client_hello_x509(&args, GFP_KERNEL);