1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* Out of band message handling (e.g. challenge-response) 3 * 4 * Copyright (C) 2025 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.com) 6 */ 7 8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 9 10 #include <linux/net.h> 11 #include <linux/gfp.h> 12 #include <linux/skbuff.h> 13 #include <linux/export.h> 14 #include <linux/sched/signal.h> 15 #include <net/sock.h> 16 #include <net/af_rxrpc.h> 17 #include "ar-internal.h" 18 19 enum rxrpc_oob_command { 20 RXRPC_OOB_CMD_UNSET, 21 RXRPC_OOB_CMD_RESPOND, 22 } __mode(byte); 23 24 struct rxrpc_oob_params { 25 u64 oob_id; /* ID number of message if reply */ 26 s32 abort_code; 27 enum rxrpc_oob_command command; 28 bool have_oob_id:1; 29 }; 30 31 /* 32 * Post an out-of-band message for attention by the socket or kernel service 33 * associated with a reference call. 34 */ 35 void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb) 36 { 37 struct rxrpc_skb_priv *sp = rxrpc_skb(skb); 38 struct rxrpc_sock *rx; 39 struct sock *sk; 40 41 rcu_read_lock(); 42 43 rx = rcu_dereference(call->socket); 44 if (rx) { 45 sk = &rx->sk; 46 spin_lock_irq(&rx->recvmsg_lock); 47 48 if (sk->sk_state < RXRPC_CLOSE) { 49 skb->skb_mstamp_ns = rx->oob_id_counter++; 50 rxrpc_get_skb(skb, rxrpc_skb_get_post_oob); 51 skb_queue_tail(&rx->recvmsg_oobq, skb); 52 53 trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial); 54 if (rx->app_ops) 55 rx->app_ops->notify_oob(sk, skb); 56 } 57 58 spin_unlock_irq(&rx->recvmsg_lock); 59 if (!rx->app_ops && !sock_flag(sk, SOCK_DEAD)) 60 sk->sk_data_ready(sk); 61 } 62 63 rcu_read_unlock(); 64 } 65 66 /* 67 * Locate the OOB message to respond to by its ID. 68 */ 69 static struct sk_buff *rxrpc_find_pending_oob(struct rxrpc_sock *rx, u64 oob_id) 70 { 71 struct rb_node *p; 72 struct sk_buff *skb; 73 74 p = rx->pending_oobq.rb_node; 75 while (p) { 76 skb = rb_entry(p, struct sk_buff, rbnode); 77 78 if (oob_id < skb->skb_mstamp_ns) 79 p = p->rb_left; 80 else if (oob_id > skb->skb_mstamp_ns) 81 p = p->rb_right; 82 else 83 return skb; 84 } 85 86 return NULL; 87 } 88 89 /* 90 * Add an OOB message into the pending-response set. We always assign the next 91 * value from a 64-bit counter to the oob_id, so just assume we're always going 92 * to be on the right-hand edge of the tree and that the counter won't wrap. 93 * The tree is also given a ref to the message. 94 */ 95 void rxrpc_add_pending_oob(struct rxrpc_sock *rx, struct sk_buff *skb) 96 { 97 struct rb_node **pp = &rx->pending_oobq.rb_node, *p = NULL; 98 99 while (*pp) { 100 p = *pp; 101 pp = &(*pp)->rb_right; 102 } 103 104 rb_link_node(&skb->rbnode, p, pp); 105 rb_insert_color(&skb->rbnode, &rx->pending_oobq); 106 } 107 108 /* 109 * Extract control messages from the sendmsg() control buffer. 110 */ 111 static int rxrpc_sendmsg_oob_cmsg(struct msghdr *msg, struct rxrpc_oob_params *p) 112 { 113 struct cmsghdr *cmsg; 114 int len; 115 116 if (msg->msg_controllen == 0) 117 return -EINVAL; 118 119 for_each_cmsghdr(cmsg, msg) { 120 if (!CMSG_OK(msg, cmsg)) 121 return -EINVAL; 122 123 len = cmsg->cmsg_len - sizeof(struct cmsghdr); 124 _debug("CMSG %d, %d, %d", 125 cmsg->cmsg_level, cmsg->cmsg_type, len); 126 127 if (cmsg->cmsg_level != SOL_RXRPC) 128 continue; 129 130 switch (cmsg->cmsg_type) { 131 case RXRPC_OOB_ID: 132 if (len != sizeof(p->oob_id) || p->have_oob_id) 133 return -EINVAL; 134 memcpy(&p->oob_id, CMSG_DATA(cmsg), sizeof(p->oob_id)); 135 p->have_oob_id = true; 136 break; 137 case RXRPC_RESPOND: 138 if (p->command != RXRPC_OOB_CMD_UNSET) 139 return -EINVAL; 140 p->command = RXRPC_OOB_CMD_RESPOND; 141 break; 142 case RXRPC_ABORT: 143 if (len != sizeof(p->abort_code) || p->abort_code) 144 return -EINVAL; 145 memcpy(&p->abort_code, CMSG_DATA(cmsg), sizeof(p->abort_code)); 146 if (p->abort_code == 0) 147 return -EINVAL; 148 break; 149 case RXRPC_RESP_RXGK_APPDATA: 150 if (p->command != RXRPC_OOB_CMD_RESPOND) 151 return -EINVAL; 152 break; 153 default: 154 return -EINVAL; 155 } 156 } 157 158 switch (p->command) { 159 case RXRPC_OOB_CMD_RESPOND: 160 if (!p->have_oob_id) 161 return -EBADSLT; 162 break; 163 default: 164 return -EINVAL; 165 } 166 167 return 0; 168 } 169 170 /* 171 * Allow userspace to respond to an OOB using sendmsg(). 172 */ 173 static int rxrpc_respond_to_oob(struct rxrpc_sock *rx, 174 struct rxrpc_oob_params *p, 175 struct msghdr *msg) 176 { 177 struct rxrpc_connection *conn; 178 struct rxrpc_skb_priv *sp; 179 struct sk_buff *skb; 180 int ret; 181 182 skb = rxrpc_find_pending_oob(rx, p->oob_id); 183 if (skb) 184 rb_erase(&skb->rbnode, &rx->pending_oobq); 185 release_sock(&rx->sk); 186 if (!skb) 187 return -EBADSLT; 188 189 sp = rxrpc_skb(skb); 190 191 switch (p->command) { 192 case RXRPC_OOB_CMD_RESPOND: 193 ret = -EPROTO; 194 if (skb->mark != RXRPC_OOB_CHALLENGE) 195 break; 196 conn = sp->chall.conn; 197 ret = -EOPNOTSUPP; 198 if (!conn->security->sendmsg_respond_to_challenge) 199 break; 200 if (p->abort_code) { 201 rxrpc_abort_conn(conn, NULL, p->abort_code, -ECONNABORTED, 202 rxrpc_abort_response_sendmsg); 203 ret = 0; 204 } else { 205 ret = conn->security->sendmsg_respond_to_challenge(skb, msg); 206 } 207 break; 208 default: 209 ret = -EINVAL; 210 break; 211 } 212 213 rxrpc_free_skb(skb, rxrpc_skb_put_oob); 214 return ret; 215 } 216 217 /* 218 * Send an out-of-band message or respond to a received out-of-band message. 219 * - caller gives us the socket lock 220 * - the socket may be either a client socket or a server socket 221 */ 222 int rxrpc_sendmsg_oob(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) 223 { 224 struct rxrpc_oob_params p = {}; 225 int ret; 226 227 _enter(""); 228 229 ret = rxrpc_sendmsg_oob_cmsg(msg, &p); 230 if (ret < 0) 231 goto error_release_sock; 232 233 if (p.have_oob_id) 234 return rxrpc_respond_to_oob(rx, &p, msg); 235 236 release_sock(&rx->sk); 237 238 switch (p.command) { 239 default: 240 ret = -EINVAL; 241 break; 242 } 243 244 _leave(" = %d", ret); 245 return ret; 246 247 error_release_sock: 248 release_sock(&rx->sk); 249 return ret; 250 } 251 252 /** 253 * rxrpc_kernel_query_oob - Query the parameters of an out-of-band message 254 * @oob: The message to query 255 * @_peer: Where to return the peer record 256 * @_peer_appdata: The application data attached to a peer record 257 * 258 * Extract useful parameters from an out-of-band message. The source peer 259 * parameters are returned through the argument list and the message type is 260 * returned. 261 * 262 * Return: 263 * * %RXRPC_OOB_CHALLENGE - Challenge wanting a response. 264 */ 265 enum rxrpc_oob_type rxrpc_kernel_query_oob(struct sk_buff *oob, 266 struct rxrpc_peer **_peer, 267 unsigned long *_peer_appdata) 268 { 269 struct rxrpc_skb_priv *sp = rxrpc_skb(oob); 270 enum rxrpc_oob_type type = oob->mark; 271 272 switch (type) { 273 case RXRPC_OOB_CHALLENGE: 274 *_peer = sp->chall.conn->peer; 275 *_peer_appdata = sp->chall.conn->peer->app_data; 276 break; 277 default: 278 WARN_ON_ONCE(1); 279 *_peer = NULL; 280 *_peer_appdata = 0; 281 break; 282 } 283 284 return type; 285 } 286 EXPORT_SYMBOL(rxrpc_kernel_query_oob); 287 288 /** 289 * rxrpc_kernel_dequeue_oob - Dequeue and return the front OOB message 290 * @sock: The socket to query 291 * @_type: Where to return the message type 292 * 293 * Dequeue the front OOB message, if there is one, and return it and 294 * its type. 295 * 296 * Return: The sk_buff representing the OOB message or %NULL if the queue was 297 * empty. 298 */ 299 struct sk_buff *rxrpc_kernel_dequeue_oob(struct socket *sock, 300 enum rxrpc_oob_type *_type) 301 { 302 struct rxrpc_sock *rx = rxrpc_sk(sock->sk); 303 struct sk_buff *oob; 304 305 oob = skb_dequeue(&rx->recvmsg_oobq); 306 if (oob) 307 *_type = oob->mark; 308 return oob; 309 } 310 EXPORT_SYMBOL(rxrpc_kernel_dequeue_oob); 311 312 /** 313 * rxrpc_kernel_free_oob - Free an out-of-band message 314 * @oob: The OOB message to free 315 * 316 * Free an OOB message along with any resources it holds. 317 */ 318 void rxrpc_kernel_free_oob(struct sk_buff *oob) 319 { 320 struct rxrpc_skb_priv *sp = rxrpc_skb(oob); 321 322 switch (oob->mark) { 323 case RXRPC_OOB_CHALLENGE: 324 rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob); 325 break; 326 } 327 328 rxrpc_free_skb(oob, rxrpc_skb_put_purge_oob); 329 } 330 EXPORT_SYMBOL(rxrpc_kernel_free_oob); 331 332 /** 333 * rxrpc_kernel_query_challenge - Query the parameters of a challenge 334 * @challenge: The challenge to query 335 * @_peer: Where to return the peer record 336 * @_peer_appdata: The application data attached to a peer record 337 * @_service_id: Where to return the connection service ID 338 * @_security_index: Where to return the connection security index 339 * 340 * Extract useful parameters from a CHALLENGE message. 341 */ 342 void rxrpc_kernel_query_challenge(struct sk_buff *challenge, 343 struct rxrpc_peer **_peer, 344 unsigned long *_peer_appdata, 345 u16 *_service_id, u8 *_security_index) 346 { 347 struct rxrpc_skb_priv *sp = rxrpc_skb(challenge); 348 349 *_peer = sp->chall.conn->peer; 350 *_peer_appdata = sp->chall.conn->peer->app_data; 351 *_service_id = sp->hdr.serviceId; 352 *_security_index = sp->hdr.securityIndex; 353 } 354 EXPORT_SYMBOL(rxrpc_kernel_query_challenge); 355 356 /** 357 * rxrpc_kernel_reject_challenge - Allow a kernel service to reject a challenge 358 * @challenge: The challenge to be rejected 359 * @abort_code: The abort code to stick into the ABORT packet 360 * @error: Local error value 361 * @why: Indication as to why. 362 * 363 * Allow a kernel service to reject a challenge by aborting the connection if 364 * it's still in an abortable state. The error is returned so this function 365 * can be used with a return statement. 366 * 367 * Return: The %error parameter. 368 */ 369 int rxrpc_kernel_reject_challenge(struct sk_buff *challenge, u32 abort_code, 370 int error, enum rxrpc_abort_reason why) 371 { 372 struct rxrpc_skb_priv *sp = rxrpc_skb(challenge); 373 374 _enter("{%x},%d,%d,%u", sp->hdr.serial, abort_code, error, why); 375 376 rxrpc_abort_conn(sp->chall.conn, NULL, abort_code, error, why); 377 return error; 378 } 379 EXPORT_SYMBOL(rxrpc_kernel_reject_challenge); 380