oob.c 9.1 KB

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