[PATCH net 4/4] rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation
Simon Horman
horms at kernel.org
Thu Jul 9 03:37:53 PDT 2026
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
Full review at: https://sashiko.dev
---
Subject: rxrpc: Fix CHALLENGE packet overqueuing and simplify RESPONSE generation
This commit removes the out-of-band queueing mechanism for CHALLENGE
packets. It transitions the connection event processor to handle
CHALLENGE parsing and RESPONSE generation directly, while allowing
application data to be passed via a user-type key.
Link: https://sashiko.dev/#/patchset/20260624163819.3017002-1-dhowells%40redhat.com
> diff --git a/fs/afs/cm_security.c b/fs/afs/cm_security.c
> index 103168c70dd4d..db2a3b30f0209 100644
> --- a/fs/afs/cm_security.c
> +++ b/fs/afs/cm_security.c
> @@ -295,13 +295,22 @@ static int afs_create_yfs_cm_token(struct sk_buff *challenge,
> if (ret < 0)
> goto out_aead;
>
> - server->cm_rxgk_appdata.len = adatasize;
> - server->cm_rxgk_appdata.data = appdata;
> - appdata = NULL;
> + appdata_key = key_alloc(&key_type_user, "rxrpc: afs rxgk appdata",
> + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(),
> + KEY_POS_VIEW | KEY_POS_SEARCH | KEY_USR_VIEW,
> + KEY_ALLOC_NOT_IN_QUOTA, NULL);
> + if (IS_ERR(appdata_key)) {
> + ret = PTR_ERR(appdata_key);
> + goto out_aead;
> + }
> +
> + ret = key_instantiate_and_link(appdata_key, appdata, adatasize, NULL, NULL);
> + if (ret < 0) {
> + key_put(appdata_key);
> + goto out_aead;
> + }
> +
> + server->cm_rxgk_appdata = appdata_key;
[Severity: Medium]
Does this plain store require memory barriers? afs_make_call() appears to
read call->server->cm_rxgk_appdata concurrently without holding the
cm_token_lock. Without smp_store_release() here and a corresponding
smp_load_acquire() or READ_ONCE() on the read side, could the reader
observe the pointer before the key object's initialization is completely
visible to other CPUs?
> diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
> index 05fcb9b6adde7..ae48c15b3db94 100644
> --- a/fs/afs/rxrpc.c
> +++ b/fs/afs/rxrpc.c
> @@ -373,8 +373,25 @@ void afs_make_call(struct afs_call *call, gfp_t gfp)
> call->drop_ref = true;
> }
>
> + if (call->key && call->server) {
> + u32 krb5_enctype = 0;
> + u8 security_index = 0;
> +
> + rxrpc_kernel_query_key(call->key, &security_index, &krb5_enctype);
> + switch (security_index) {
> +#ifdef CONFIG_RXGK
> + case RXRPC_SECURITY_YFS_RXGK:
> + app_data = call->server->cm_rxgk_appdata;
> + break;
[Severity: Medium]
Following up on the previous observation, is it safe to perform a plain
read of the cm_rxgk_appdata pointer here in afs_make_call() without
READ_ONCE() or a lock?
> diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
> index 77a67ace1d248..9ab766d5f0b6c 100644
> --- a/net/rxrpc/rxgk.c
> +++ b/net/rxrpc/rxgk.c
> @@ -981,36 +981,36 @@ static int rxgk_construct_response(struct rxrpc_connection *conn,
> [ ... ]
> + if (conn->bundle->app_data) {
> + rcu_read_lock();
> + appdata = (struct user_key_payload *)
> + user_key_payload_rcu(conn->bundle->app_data);
[Severity: High]
If an attacker passes the ID of a non-user key (like an asymmetric key
or keyring) during sendmsg(), could casting that key's payload to struct
user_key_payload and modifying its refcount cause memory corruption?
> + if (!refcount_inc_not_zero(&appdata->ref))
[Severity: High]
Can user_key_payload_rcu() return NULL here if the user key has been
revoked by userspace via keyctl(KEYCTL_REVOKE)? If appdata evaluates to
NULL, would calling refcount_inc_not_zero(&appdata->ref) attempt to
dereference a low offset address and trigger a kernel panic?
> diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
> index 4c754f78ece9a..225eec410bedc 100644
> --- a/net/rxrpc/sendmsg.c
> +++ b/net/rxrpc/sendmsg.c
> @@ -590,6 +592,18 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
> [ ... ]
> + case RXRPC_RESPONSE_APPDATA:
> + if (len != sizeof(key_serial_t))
> + return -EINVAL;
> + if (p->call.app_data)
> + return -EINVAL;
> + key_id = *(key_serial_t *)CMSG_DATA(cmsg);
> + key = lookup_user_key(key_id, 0, KEY_NEED_SEARCH);
> + if (IS_ERR(key))
> + return PTR_ERR(key);
> + p->call.app_data = key_ref_to_ptr(key);
> + break;
[Severity: High]
Should there be a check here in rxrpc_sendmsg_cmsg() to verify that the
fetched key is actually a user-type key (e.g., key->type == &key_type_user)?
Without validation, any key type could be assigned to p->call.app_data,
leading to the invalid cast mentioned previously in
rxgk_respond_to_challenge().
> @@ -677 +716 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
> [ ... ]
> call = rxrpc_find_call_by_user_ID(rx, p.call.user_call_ID);
> if (!call) {
> [ ... ]
> + call = rxrpc_new_client_call_for_sendmsg(rx, msg, &p);
> + /* The socket is now unlocked... */
> + if (IS_ERR(call))
> + return PTR_ERR(call);
[Severity: High]
Does this direct return leak the key reference acquired by lookup_user_key()
and stored in p.call.app_data when rxrpc_new_client_call_for_sendmsg()
fails?
> @@ -803,6 +803,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
> out_put_unlock:
> if (!dropped_lock)
> mutex_unlock(&call->user_mutex);
> error_put:
> rxrpc_put_call(call, rxrpc_call_put_sendmsg);
> _leave(" = %d", ret);
> return ret;
>
> error_release_sock:
> release_sock(&rx->sk);
> + key_put(p.call.app_data);
> return ret;
> }
[Severity: High]
Do the out_put_unlock and error_put paths in rxrpc_do_sendmsg() also need
to call key_put(p.call.app_data)? It appears rxrpc_alloc_client_call()
takes its own reference on the key via key_get(), which means the original
reference acquired during rxrpc_sendmsg_cmsg() will be leaked on successful
operations or when failing after the socket lock is released.
More information about the linux-afs
mailing list