diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index ba2c6e3c78a6..48e774034195 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -78,6 +78,7 @@
EM(rxgk_abort_2_short_encdata, "rxgk2-short-encdata") \
EM(rxgk_abort_2_short_header, "rxgk2-short-hdr") \
EM(rxgk_abort_bad_key_number, "rxgk-bad-key-num") \
+ EM(rxgk_abort_chall_bad_app_key, "rxgk-chall-bad-app-key")\
EM(rxgk_abort_chall_key_expired, "rxgk-chall-key-exp") \
EM(rxgk_abort_chall_no_key, "rxgk-chall-nokey") \
EM(rxgk_abort_chall_short, "rxgk-chall-short") \
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index a19c0fd3c51a..9eb6ca3c5ebf 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -598,10 +598,7 @@ static int rxrpc_sendmsg(struct socket *sock, struct msghdr *m, size_t len)
fallthrough;
case RXRPC_SERVER_BOUND:
case RXRPC_SERVER_LISTENING:
- if (m->msg_flags & MSG_OOB)
- ret = rxrpc_sendmsg_oob(rx, m, len);
- else
- ret = rxrpc_do_sendmsg(rx, m, len);
+ ret = rxrpc_do_sendmsg(rx, m, len);
/* The socket has been unlocked */
goto out;
default:
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 611c790bc6d0..9146b9d4c2ac 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -279,10 +279,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
switch (sp->hdr.type) {
case RXRPC_PACKET_TYPE_CHALLENGE:
- ret = conn->security->respond_to_challenge(conn, skb);
- sp->chall.conn = NULL;
- rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
- return ret;
+ return conn->security->respond_to_challenge(conn, skb);
case RXRPC_PACKET_TYPE_RESPONSE:
spin_lock_irq(&conn->state_lock);@@ -425,66 +422,6 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn,
rxrpc_queue_conn(conn, rxrpc_conn_queue_rx_work);
}
-/*
- * Post a CHALLENGE packet to the socket of one of a connection's calls so that
- * it can get application data to include in the packet, possibly querying
- * userspace.
- */
-static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
- struct sk_buff *skb)
-{
- struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- struct rxrpc_call *call = NULL;
- struct rxrpc_sock *rx;
- bool respond = false, queued = false;
-
- sp->chall.conn =
- rxrpc_get_connection(conn, rxrpc_conn_get_challenge_input);
-
- if (!conn->security->challenge_to_recvmsg) {
- rxrpc_post_packet_to_conn(conn, skb);
- return true;
- }
-
- rcu_read_lock();
-
- for (int i = 0; i < ARRAY_SIZE(conn->channels); i++) {
- if (conn->channels[i].call) {
- call = conn->channels[i].call;
- rx = rcu_dereference(call->socket);
- if (!rx) {
- call = NULL;
- continue;
- }
-
- respond = true;
- if (test_bit(RXRPC_SOCK_MANAGE_RESPONSE, &rx->flags))
- break;
- call = NULL;
- }
- }
-
- if (!respond) {
- rcu_read_unlock();
- rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
- sp->chall.conn = NULL;
- return false;
- }
-
- if (call)
- queued = rxrpc_notify_socket_oob(call, skb);
- rcu_read_unlock();
- if (call && !queued) {
- rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
- sp->chall.conn = NULL;
- return false;
- }
-
- if (!call)
- rxrpc_post_packet_to_conn(conn, skb);
- return true;
-}
-
/*
* Input a connection-level packet.
*/@@ -513,7 +450,8 @@ bool rxrpc_input_conn_packet(struct rxrpc_connection *conn, struct sk_buff *skb)
}
if (!conn->security->validate_challenge(conn, skb))
return false;
- return rxrpc_post_challenge(conn, skb);
+ rxrpc_post_packet_to_conn(conn, skb);
+ return true;
case RXRPC_PACKET_TYPE_RESPONSE:
if (rxrpc_is_conn_aborted(conn)) {diff --git a/net/rxrpc/rxgk.c b/net/rxrpc/rxgk.c
index 77a67ace1d24..031c6719d33e 100644
--- a/net/rxrpc/rxgk.c
+++ b/net/rxrpc/rxgk.c
@@ -11,6 +11,7 @@
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/key-type.h>
+#include <keys/user-type.h>
#include "ar-internal.h"
#include "rxgk_common.h"
@@ -837,7 +838,7 @@ static noinline ssize_t rxgk_insert_response_header(struct rxrpc_connection *con
*/
static ssize_t rxgk_construct_authenticator(struct rxrpc_connection *conn,
struct sk_buff *challenge,
- const struct krb5_buffer *appdata,
+ const struct user_key_payload *appdata,
struct sk_buff *response,
size_t offset)
{@@ -859,20 +860,20 @@ static ssize_t rxgk_construct_authenticator(struct rxrpc_connection *conn,
if (ret < 0)
return -EPROTO;
- a.appdata_len = htonl(appdata->len);
+ a.appdata_len = htonl(appdata->datalen);
ret = skb_store_bits(response, offset, &a, sizeof(a));
if (ret < 0)
return ret;
offset += sizeof(a);
- if (appdata->len) {
- ret = skb_store_bits(response, offset, appdata->data, appdata->len);
+ if (appdata->datalen) {
+ ret = skb_store_bits(response, offset, appdata->data, appdata->datalen);
if (ret < 0)
return ret;
- offset += appdata->len;
+ offset += appdata->datalen;
- ret = rxgk_pad_out(response, appdata->len, offset);
+ ret = rxgk_pad_out(response, appdata->datalen, offset);
if (ret < 0)
return ret;
offset += ret;@@ -890,7 +891,7 @@ static ssize_t rxgk_construct_authenticator(struct rxrpc_connection *conn,
ret = skb_store_bits(response, offset, &b, sizeof(b));
if (ret < 0)
return ret;
- return sizeof(a) + xdr_round_up(appdata->len) + sizeof(b);
+ return sizeof(a) + xdr_round_up(appdata->datalen) + sizeof(b);
}
static ssize_t rxgk_encrypt_authenticator(struct rxrpc_connection *conn,
@@ -923,7 +924,7 @@ static ssize_t rxgk_encrypt_authenticator(struct rxrpc_connection *conn,
*/
static int rxgk_construct_response(struct rxrpc_connection *conn,
struct sk_buff *challenge,
- struct krb5_buffer *appdata)
+ const struct user_key_payload *appdata)
{
struct rxrpc_skb_priv *csp, *rsp;
struct rxgk_context *gk;@@ -936,11 +937,11 @@ static int rxgk_construct_response(struct rxrpc_connection *conn,
if (IS_ERR(gk))
return PTR_ERR(gk);
- auth_len = 20 + (4 + appdata->len) + 12 + (1 + 4) * 4;
+ auth_len = 20 + xdr_object_len(appdata->datalen) + 12 + (1 + 4) * 4;
authx_len = crypto_krb5_how_much_buffer(gk->krb5, KRB5_ENCRYPT_MODE,
auth_len, &auth_offset);
len = sizeof(struct rxrpc_wire_header) +
- 8 + (4 + xdr_round_up(gk->key->ticket.len)) + (4 + authx_len);
+ 8 + xdr_object_len(gk->key->ticket.len) + xdr_object_len(authx_len);
response = alloc_skb_with_frags(0, len, 0, &ret, GFP_NOFS);
if (!response)
@@ -1011,24 +1012,44 @@ static int rxgk_construct_response(struct rxrpc_connection *conn,
* Respond to a challenge packet.
*/
static int rxgk_respond_to_challenge(struct rxrpc_connection *conn,
- struct sk_buff *challenge,
- struct krb5_buffer *appdata)
+ struct sk_buff *challenge)
{
- _enter("{%d,%x}", conn->debug_id, key_serial(conn->key));
+ struct user_key_payload dummy = {}, *appdata = &dummy;
+ int ret;
+
+ _enter("{%d,%u,%x,%x}",
+ conn->debug_id, conn->service_id,
+ key_serial(conn->key), key_serial(conn->bundle->app_data));
if (key_validate(conn->key) < 0)
return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EPROTO,
rxgk_abort_chall_key_expired);
- return rxgk_construct_response(conn, challenge, appdata);
-}
+ if (conn->bundle->app_data) {
+ struct key *app_key = conn->bundle->app_data;
+
+ /* The wrong sort of key shouldn't get this far. */
+ if (WARN_ON_ONCE(app_key->type != &key_type_user &&
+ app_key->type != &key_type_logon))
+ return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EKEYREJECTED,
+ rxgk_abort_chall_bad_app_key);
+
+ rcu_read_lock();
+ appdata = (struct user_key_payload *)
+ user_key_payload_rcu(conn->bundle->app_data);
+ if (appdata && !refcount_inc_not_zero(&appdata->ref))
+ appdata = NULL;
+ rcu_read_unlock();
+ if (!appdata)
+ return rxrpc_abort_conn(conn, NULL, RXGK_EXPIRED, -EKEYREVOKED,
+ rxgk_abort_chall_key_expired);
+ }
-static int rxgk_respond_to_challenge_no_appdata(struct rxrpc_connection *conn,
- struct sk_buff *challenge)
-{
- struct krb5_buffer appdata = {};
+ ret = rxgk_construct_response(conn, challenge, appdata);
- return rxgk_respond_to_challenge(conn, challenge, &appdata);
+ if (appdata != &dummy)
+ put_user_key_payload(appdata);
+ return ret;
}
/**@@ -1044,9 +1065,7 @@ static int rxgk_respond_to_challenge_no_appdata(struct rxrpc_connection *conn,
int rxgk_kernel_respond_to_challenge(struct sk_buff *challenge,
struct krb5_buffer *appdata)
{
- struct rxrpc_skb_priv *csp = rxrpc_skb(challenge);
-
- return rxgk_respond_to_challenge(csp->chall.conn, challenge, appdata);
+ return -EINVAL;
}
EXPORT_SYMBOL(rxgk_kernel_respond_to_challenge);
@@ -1348,7 +1367,7 @@ const struct rxrpc_security rxgk_yfs = {
.validate_challenge = rxgk_validate_challenge,
.challenge_to_recvmsg = rxgk_challenge_to_recvmsg,
.sendmsg_respond_to_challenge = rxgk_sendmsg_respond_to_challenge,
- .respond_to_challenge = rxgk_respond_to_challenge_no_appdata,
+ .respond_to_challenge = rxgk_respond_to_challenge,
.verify_response = rxgk_verify_response,
.clear = rxgk_clear,
.default_decode_ticket = rxgk_yfs_decode_ticket,