162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* RxRPC recvmsg() implementation
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/net.h>
1162306a36Sopenharmony_ci#include <linux/skbuff.h>
1262306a36Sopenharmony_ci#include <linux/export.h>
1362306a36Sopenharmony_ci#include <linux/sched/signal.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <net/sock.h>
1662306a36Sopenharmony_ci#include <net/af_rxrpc.h>
1762306a36Sopenharmony_ci#include "ar-internal.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/*
2062306a36Sopenharmony_ci * Post a call for attention by the socket or kernel service.  Further
2162306a36Sopenharmony_ci * notifications are suppressed by putting recvmsg_link on a dummy queue.
2262306a36Sopenharmony_ci */
2362306a36Sopenharmony_civoid rxrpc_notify_socket(struct rxrpc_call *call)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	struct rxrpc_sock *rx;
2662306a36Sopenharmony_ci	struct sock *sk;
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	_enter("%d", call->debug_id);
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	if (!list_empty(&call->recvmsg_link))
3162306a36Sopenharmony_ci		return;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	rcu_read_lock();
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	rx = rcu_dereference(call->socket);
3662306a36Sopenharmony_ci	sk = &rx->sk;
3762306a36Sopenharmony_ci	if (rx && sk->sk_state < RXRPC_CLOSE) {
3862306a36Sopenharmony_ci		if (call->notify_rx) {
3962306a36Sopenharmony_ci			spin_lock(&call->notify_lock);
4062306a36Sopenharmony_ci			call->notify_rx(sk, call, call->user_call_ID);
4162306a36Sopenharmony_ci			spin_unlock(&call->notify_lock);
4262306a36Sopenharmony_ci		} else {
4362306a36Sopenharmony_ci			spin_lock(&rx->recvmsg_lock);
4462306a36Sopenharmony_ci			if (list_empty(&call->recvmsg_link)) {
4562306a36Sopenharmony_ci				rxrpc_get_call(call, rxrpc_call_get_notify_socket);
4662306a36Sopenharmony_ci				list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
4762306a36Sopenharmony_ci			}
4862306a36Sopenharmony_ci			spin_unlock(&rx->recvmsg_lock);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci			if (!sock_flag(sk, SOCK_DEAD)) {
5162306a36Sopenharmony_ci				_debug("call %ps", sk->sk_data_ready);
5262306a36Sopenharmony_ci				sk->sk_data_ready(sk);
5362306a36Sopenharmony_ci			}
5462306a36Sopenharmony_ci		}
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	rcu_read_unlock();
5862306a36Sopenharmony_ci	_leave("");
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * Pass a call terminating message to userspace.
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_cistatic int rxrpc_recvmsg_term(struct rxrpc_call *call, struct msghdr *msg)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	u32 tmp = 0;
6762306a36Sopenharmony_ci	int ret;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	switch (call->completion) {
7062306a36Sopenharmony_ci	case RXRPC_CALL_SUCCEEDED:
7162306a36Sopenharmony_ci		ret = 0;
7262306a36Sopenharmony_ci		if (rxrpc_is_service_call(call))
7362306a36Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ACK, 0, &tmp);
7462306a36Sopenharmony_ci		break;
7562306a36Sopenharmony_ci	case RXRPC_CALL_REMOTELY_ABORTED:
7662306a36Sopenharmony_ci		tmp = call->abort_code;
7762306a36Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
7862306a36Sopenharmony_ci		break;
7962306a36Sopenharmony_ci	case RXRPC_CALL_LOCALLY_ABORTED:
8062306a36Sopenharmony_ci		tmp = call->abort_code;
8162306a36Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
8262306a36Sopenharmony_ci		break;
8362306a36Sopenharmony_ci	case RXRPC_CALL_NETWORK_ERROR:
8462306a36Sopenharmony_ci		tmp = -call->error;
8562306a36Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_NET_ERROR, 4, &tmp);
8662306a36Sopenharmony_ci		break;
8762306a36Sopenharmony_ci	case RXRPC_CALL_LOCAL_ERROR:
8862306a36Sopenharmony_ci		tmp = -call->error;
8962306a36Sopenharmony_ci		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_LOCAL_ERROR, 4, &tmp);
9062306a36Sopenharmony_ci		break;
9162306a36Sopenharmony_ci	default:
9262306a36Sopenharmony_ci		pr_err("Invalid terminal call state %u\n", call->completion);
9362306a36Sopenharmony_ci		BUG();
9462306a36Sopenharmony_ci		break;
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	trace_rxrpc_recvdata(call, rxrpc_recvmsg_terminal,
9862306a36Sopenharmony_ci			     call->ackr_window - 1,
9962306a36Sopenharmony_ci			     call->rx_pkt_offset, call->rx_pkt_len, ret);
10062306a36Sopenharmony_ci	return ret;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci/*
10462306a36Sopenharmony_ci * Discard a packet we've used up and advance the Rx window by one.
10562306a36Sopenharmony_ci */
10662306a36Sopenharmony_cistatic void rxrpc_rotate_rx_window(struct rxrpc_call *call)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp;
10962306a36Sopenharmony_ci	struct sk_buff *skb;
11062306a36Sopenharmony_ci	rxrpc_serial_t serial;
11162306a36Sopenharmony_ci	rxrpc_seq_t old_consumed = call->rx_consumed, tseq;
11262306a36Sopenharmony_ci	bool last;
11362306a36Sopenharmony_ci	int acked;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	_enter("%d", call->debug_id);
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	skb = skb_dequeue(&call->recvmsg_queue);
11862306a36Sopenharmony_ci	rxrpc_see_skb(skb, rxrpc_skb_see_rotate);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	sp = rxrpc_skb(skb);
12162306a36Sopenharmony_ci	tseq   = sp->hdr.seq;
12262306a36Sopenharmony_ci	serial = sp->hdr.serial;
12362306a36Sopenharmony_ci	last   = sp->hdr.flags & RXRPC_LAST_PACKET;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	/* Barrier against rxrpc_input_data(). */
12662306a36Sopenharmony_ci	if (after(tseq, call->rx_consumed))
12762306a36Sopenharmony_ci		smp_store_release(&call->rx_consumed, tseq);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	rxrpc_free_skb(skb, rxrpc_skb_put_rotate);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	trace_rxrpc_receive(call, last ? rxrpc_receive_rotate_last : rxrpc_receive_rotate,
13262306a36Sopenharmony_ci			    serial, call->rx_consumed);
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	if (last)
13562306a36Sopenharmony_ci		set_bit(RXRPC_CALL_RECVMSG_READ_ALL, &call->flags);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	/* Check to see if there's an ACK that needs sending. */
13862306a36Sopenharmony_ci	acked = atomic_add_return(call->rx_consumed - old_consumed,
13962306a36Sopenharmony_ci				  &call->ackr_nr_consumed);
14062306a36Sopenharmony_ci	if (acked > 8 &&
14162306a36Sopenharmony_ci	    !test_and_set_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags))
14262306a36Sopenharmony_ci		rxrpc_poke_call(call, rxrpc_call_poke_idle);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci/*
14662306a36Sopenharmony_ci * Decrypt and verify a DATA packet.
14762306a36Sopenharmony_ci */
14862306a36Sopenharmony_cistatic int rxrpc_verify_data(struct rxrpc_call *call, struct sk_buff *skb)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci	if (sp->flags & RXRPC_RX_VERIFIED)
15362306a36Sopenharmony_ci		return 0;
15462306a36Sopenharmony_ci	return call->security->verify_packet(call, skb);
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci/*
15862306a36Sopenharmony_ci * Deliver messages to a call.  This keeps processing packets until the buffer
15962306a36Sopenharmony_ci * is filled and we find either more DATA (returns 0) or the end of the DATA
16062306a36Sopenharmony_ci * (returns 1).  If more packets are required, it returns -EAGAIN and if the
16162306a36Sopenharmony_ci * call has failed it returns -EIO.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_cistatic int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
16462306a36Sopenharmony_ci			      struct msghdr *msg, struct iov_iter *iter,
16562306a36Sopenharmony_ci			      size_t len, int flags, size_t *_offset)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	struct rxrpc_skb_priv *sp;
16862306a36Sopenharmony_ci	struct sk_buff *skb;
16962306a36Sopenharmony_ci	rxrpc_seq_t seq = 0;
17062306a36Sopenharmony_ci	size_t remain;
17162306a36Sopenharmony_ci	unsigned int rx_pkt_offset, rx_pkt_len;
17262306a36Sopenharmony_ci	int copy, ret = -EAGAIN, ret2;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	rx_pkt_offset = call->rx_pkt_offset;
17562306a36Sopenharmony_ci	rx_pkt_len = call->rx_pkt_len;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	if (rxrpc_call_has_failed(call)) {
17862306a36Sopenharmony_ci		seq = call->ackr_window - 1;
17962306a36Sopenharmony_ci		ret = -EIO;
18062306a36Sopenharmony_ci		goto done;
18162306a36Sopenharmony_ci	}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_RECVMSG_READ_ALL, &call->flags)) {
18462306a36Sopenharmony_ci		seq = call->ackr_window - 1;
18562306a36Sopenharmony_ci		ret = 1;
18662306a36Sopenharmony_ci		goto done;
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	/* No one else can be removing stuff from the queue, so we shouldn't
19062306a36Sopenharmony_ci	 * need the Rx lock to walk it.
19162306a36Sopenharmony_ci	 */
19262306a36Sopenharmony_ci	skb = skb_peek(&call->recvmsg_queue);
19362306a36Sopenharmony_ci	while (skb) {
19462306a36Sopenharmony_ci		rxrpc_see_skb(skb, rxrpc_skb_see_recvmsg);
19562306a36Sopenharmony_ci		sp = rxrpc_skb(skb);
19662306a36Sopenharmony_ci		seq = sp->hdr.seq;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci		if (!(flags & MSG_PEEK))
19962306a36Sopenharmony_ci			trace_rxrpc_receive(call, rxrpc_receive_front,
20062306a36Sopenharmony_ci					    sp->hdr.serial, seq);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci		if (msg)
20362306a36Sopenharmony_ci			sock_recv_timestamp(msg, sock->sk, skb);
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci		if (rx_pkt_offset == 0) {
20662306a36Sopenharmony_ci			ret2 = rxrpc_verify_data(call, skb);
20762306a36Sopenharmony_ci			trace_rxrpc_recvdata(call, rxrpc_recvmsg_next, seq,
20862306a36Sopenharmony_ci					     sp->offset, sp->len, ret2);
20962306a36Sopenharmony_ci			if (ret2 < 0) {
21062306a36Sopenharmony_ci				kdebug("verify = %d", ret2);
21162306a36Sopenharmony_ci				ret = ret2;
21262306a36Sopenharmony_ci				goto out;
21362306a36Sopenharmony_ci			}
21462306a36Sopenharmony_ci			rx_pkt_offset = sp->offset;
21562306a36Sopenharmony_ci			rx_pkt_len = sp->len;
21662306a36Sopenharmony_ci		} else {
21762306a36Sopenharmony_ci			trace_rxrpc_recvdata(call, rxrpc_recvmsg_cont, seq,
21862306a36Sopenharmony_ci					     rx_pkt_offset, rx_pkt_len, 0);
21962306a36Sopenharmony_ci		}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		/* We have to handle short, empty and used-up DATA packets. */
22262306a36Sopenharmony_ci		remain = len - *_offset;
22362306a36Sopenharmony_ci		copy = rx_pkt_len;
22462306a36Sopenharmony_ci		if (copy > remain)
22562306a36Sopenharmony_ci			copy = remain;
22662306a36Sopenharmony_ci		if (copy > 0) {
22762306a36Sopenharmony_ci			ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter,
22862306a36Sopenharmony_ci						      copy);
22962306a36Sopenharmony_ci			if (ret2 < 0) {
23062306a36Sopenharmony_ci				ret = ret2;
23162306a36Sopenharmony_ci				goto out;
23262306a36Sopenharmony_ci			}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci			/* handle piecemeal consumption of data packets */
23562306a36Sopenharmony_ci			rx_pkt_offset += copy;
23662306a36Sopenharmony_ci			rx_pkt_len -= copy;
23762306a36Sopenharmony_ci			*_offset += copy;
23862306a36Sopenharmony_ci		}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		if (rx_pkt_len > 0) {
24162306a36Sopenharmony_ci			trace_rxrpc_recvdata(call, rxrpc_recvmsg_full, seq,
24262306a36Sopenharmony_ci					     rx_pkt_offset, rx_pkt_len, 0);
24362306a36Sopenharmony_ci			ASSERTCMP(*_offset, ==, len);
24462306a36Sopenharmony_ci			ret = 0;
24562306a36Sopenharmony_ci			break;
24662306a36Sopenharmony_ci		}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci		/* The whole packet has been transferred. */
24962306a36Sopenharmony_ci		if (sp->hdr.flags & RXRPC_LAST_PACKET)
25062306a36Sopenharmony_ci			ret = 1;
25162306a36Sopenharmony_ci		rx_pkt_offset = 0;
25262306a36Sopenharmony_ci		rx_pkt_len = 0;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		skb = skb_peek_next(skb, &call->recvmsg_queue);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci		if (!(flags & MSG_PEEK))
25762306a36Sopenharmony_ci			rxrpc_rotate_rx_window(call);
25862306a36Sopenharmony_ci	}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ciout:
26162306a36Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
26262306a36Sopenharmony_ci		call->rx_pkt_offset = rx_pkt_offset;
26362306a36Sopenharmony_ci		call->rx_pkt_len = rx_pkt_len;
26462306a36Sopenharmony_ci	}
26562306a36Sopenharmony_cidone:
26662306a36Sopenharmony_ci	trace_rxrpc_recvdata(call, rxrpc_recvmsg_data_return, seq,
26762306a36Sopenharmony_ci			     rx_pkt_offset, rx_pkt_len, ret);
26862306a36Sopenharmony_ci	if (ret == -EAGAIN)
26962306a36Sopenharmony_ci		set_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags);
27062306a36Sopenharmony_ci	return ret;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci/*
27462306a36Sopenharmony_ci * Receive a message from an RxRPC socket
27562306a36Sopenharmony_ci * - we need to be careful about two or more threads calling recvmsg
27662306a36Sopenharmony_ci *   simultaneously
27762306a36Sopenharmony_ci */
27862306a36Sopenharmony_ciint rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
27962306a36Sopenharmony_ci		  int flags)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	struct rxrpc_call *call;
28262306a36Sopenharmony_ci	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
28362306a36Sopenharmony_ci	struct list_head *l;
28462306a36Sopenharmony_ci	unsigned int call_debug_id = 0;
28562306a36Sopenharmony_ci	size_t copied = 0;
28662306a36Sopenharmony_ci	long timeo;
28762306a36Sopenharmony_ci	int ret;
28862306a36Sopenharmony_ci
28962306a36Sopenharmony_ci	DEFINE_WAIT(wait);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	trace_rxrpc_recvmsg(0, rxrpc_recvmsg_enter, 0);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (flags & (MSG_OOB | MSG_TRUNC))
29462306a36Sopenharmony_ci		return -EOPNOTSUPP;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_citry_again:
29962306a36Sopenharmony_ci	lock_sock(&rx->sk);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* Return immediately if a client socket has no outstanding calls */
30262306a36Sopenharmony_ci	if (RB_EMPTY_ROOT(&rx->calls) &&
30362306a36Sopenharmony_ci	    list_empty(&rx->recvmsg_q) &&
30462306a36Sopenharmony_ci	    rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
30562306a36Sopenharmony_ci		release_sock(&rx->sk);
30662306a36Sopenharmony_ci		return -EAGAIN;
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (list_empty(&rx->recvmsg_q)) {
31062306a36Sopenharmony_ci		ret = -EWOULDBLOCK;
31162306a36Sopenharmony_ci		if (timeo == 0) {
31262306a36Sopenharmony_ci			call = NULL;
31362306a36Sopenharmony_ci			goto error_no_call;
31462306a36Sopenharmony_ci		}
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci		release_sock(&rx->sk);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci		/* Wait for something to happen */
31962306a36Sopenharmony_ci		prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
32062306a36Sopenharmony_ci					  TASK_INTERRUPTIBLE);
32162306a36Sopenharmony_ci		ret = sock_error(&rx->sk);
32262306a36Sopenharmony_ci		if (ret)
32362306a36Sopenharmony_ci			goto wait_error;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci		if (list_empty(&rx->recvmsg_q)) {
32662306a36Sopenharmony_ci			if (signal_pending(current))
32762306a36Sopenharmony_ci				goto wait_interrupted;
32862306a36Sopenharmony_ci			trace_rxrpc_recvmsg(0, rxrpc_recvmsg_wait, 0);
32962306a36Sopenharmony_ci			timeo = schedule_timeout(timeo);
33062306a36Sopenharmony_ci		}
33162306a36Sopenharmony_ci		finish_wait(sk_sleep(&rx->sk), &wait);
33262306a36Sopenharmony_ci		goto try_again;
33362306a36Sopenharmony_ci	}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	/* Find the next call and dequeue it if we're not just peeking.  If we
33662306a36Sopenharmony_ci	 * do dequeue it, that comes with a ref that we will need to release.
33762306a36Sopenharmony_ci	 * We also want to weed out calls that got requeued whilst we were
33862306a36Sopenharmony_ci	 * shovelling data out.
33962306a36Sopenharmony_ci	 */
34062306a36Sopenharmony_ci	spin_lock(&rx->recvmsg_lock);
34162306a36Sopenharmony_ci	l = rx->recvmsg_q.next;
34262306a36Sopenharmony_ci	call = list_entry(l, struct rxrpc_call, recvmsg_link);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	if (!rxrpc_call_is_complete(call) &&
34562306a36Sopenharmony_ci	    skb_queue_empty(&call->recvmsg_queue)) {
34662306a36Sopenharmony_ci		list_del_init(&call->recvmsg_link);
34762306a36Sopenharmony_ci		spin_unlock(&rx->recvmsg_lock);
34862306a36Sopenharmony_ci		release_sock(&rx->sk);
34962306a36Sopenharmony_ci		trace_rxrpc_recvmsg(call->debug_id, rxrpc_recvmsg_unqueue, 0);
35062306a36Sopenharmony_ci		rxrpc_put_call(call, rxrpc_call_put_recvmsg);
35162306a36Sopenharmony_ci		goto try_again;
35262306a36Sopenharmony_ci	}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	if (!(flags & MSG_PEEK))
35562306a36Sopenharmony_ci		list_del_init(&call->recvmsg_link);
35662306a36Sopenharmony_ci	else
35762306a36Sopenharmony_ci		rxrpc_get_call(call, rxrpc_call_get_recvmsg);
35862306a36Sopenharmony_ci	spin_unlock(&rx->recvmsg_lock);
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	call_debug_id = call->debug_id;
36162306a36Sopenharmony_ci	trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_dequeue, 0);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	/* We're going to drop the socket lock, so we need to lock the call
36462306a36Sopenharmony_ci	 * against interference by sendmsg.
36562306a36Sopenharmony_ci	 */
36662306a36Sopenharmony_ci	if (!mutex_trylock(&call->user_mutex)) {
36762306a36Sopenharmony_ci		ret = -EWOULDBLOCK;
36862306a36Sopenharmony_ci		if (flags & MSG_DONTWAIT)
36962306a36Sopenharmony_ci			goto error_requeue_call;
37062306a36Sopenharmony_ci		ret = -ERESTARTSYS;
37162306a36Sopenharmony_ci		if (mutex_lock_interruptible(&call->user_mutex) < 0)
37262306a36Sopenharmony_ci			goto error_requeue_call;
37362306a36Sopenharmony_ci	}
37462306a36Sopenharmony_ci
37562306a36Sopenharmony_ci	release_sock(&rx->sk);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_RELEASED, &call->flags))
37862306a36Sopenharmony_ci		BUG();
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) {
38162306a36Sopenharmony_ci		if (flags & MSG_CMSG_COMPAT) {
38262306a36Sopenharmony_ci			unsigned int id32 = call->user_call_ID;
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
38562306a36Sopenharmony_ci				       sizeof(unsigned int), &id32);
38662306a36Sopenharmony_ci		} else {
38762306a36Sopenharmony_ci			unsigned long idl = call->user_call_ID;
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
39062306a36Sopenharmony_ci				       sizeof(unsigned long), &idl);
39162306a36Sopenharmony_ci		}
39262306a36Sopenharmony_ci		if (ret < 0)
39362306a36Sopenharmony_ci			goto error_unlock_call;
39462306a36Sopenharmony_ci	}
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	if (msg->msg_name && call->peer) {
39762306a36Sopenharmony_ci		size_t len = sizeof(call->dest_srx);
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci		memcpy(msg->msg_name, &call->dest_srx, len);
40062306a36Sopenharmony_ci		msg->msg_namelen = len;
40162306a36Sopenharmony_ci	}
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	ret = rxrpc_recvmsg_data(sock, call, msg, &msg->msg_iter, len,
40462306a36Sopenharmony_ci				 flags, &copied);
40562306a36Sopenharmony_ci	if (ret == -EAGAIN)
40662306a36Sopenharmony_ci		ret = 0;
40762306a36Sopenharmony_ci	if (ret == -EIO)
40862306a36Sopenharmony_ci		goto call_failed;
40962306a36Sopenharmony_ci	if (ret < 0)
41062306a36Sopenharmony_ci		goto error_unlock_call;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	if (rxrpc_call_is_complete(call) &&
41362306a36Sopenharmony_ci	    skb_queue_empty(&call->recvmsg_queue))
41462306a36Sopenharmony_ci		goto call_complete;
41562306a36Sopenharmony_ci	if (rxrpc_call_has_failed(call))
41662306a36Sopenharmony_ci		goto call_failed;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	if (!skb_queue_empty(&call->recvmsg_queue))
41962306a36Sopenharmony_ci		rxrpc_notify_socket(call);
42062306a36Sopenharmony_ci	goto not_yet_complete;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_cicall_failed:
42362306a36Sopenharmony_ci	rxrpc_purge_queue(&call->recvmsg_queue);
42462306a36Sopenharmony_cicall_complete:
42562306a36Sopenharmony_ci	ret = rxrpc_recvmsg_term(call, msg);
42662306a36Sopenharmony_ci	if (ret < 0)
42762306a36Sopenharmony_ci		goto error_unlock_call;
42862306a36Sopenharmony_ci	if (!(flags & MSG_PEEK))
42962306a36Sopenharmony_ci		rxrpc_release_call(rx, call);
43062306a36Sopenharmony_ci	msg->msg_flags |= MSG_EOR;
43162306a36Sopenharmony_ci	ret = 1;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_cinot_yet_complete:
43462306a36Sopenharmony_ci	if (ret == 0)
43562306a36Sopenharmony_ci		msg->msg_flags |= MSG_MORE;
43662306a36Sopenharmony_ci	else
43762306a36Sopenharmony_ci		msg->msg_flags &= ~MSG_MORE;
43862306a36Sopenharmony_ci	ret = copied;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cierror_unlock_call:
44162306a36Sopenharmony_ci	mutex_unlock(&call->user_mutex);
44262306a36Sopenharmony_ci	rxrpc_put_call(call, rxrpc_call_put_recvmsg);
44362306a36Sopenharmony_ci	trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_return, ret);
44462306a36Sopenharmony_ci	return ret;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cierror_requeue_call:
44762306a36Sopenharmony_ci	if (!(flags & MSG_PEEK)) {
44862306a36Sopenharmony_ci		spin_lock(&rx->recvmsg_lock);
44962306a36Sopenharmony_ci		list_add(&call->recvmsg_link, &rx->recvmsg_q);
45062306a36Sopenharmony_ci		spin_unlock(&rx->recvmsg_lock);
45162306a36Sopenharmony_ci		trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
45262306a36Sopenharmony_ci	} else {
45362306a36Sopenharmony_ci		rxrpc_put_call(call, rxrpc_call_put_recvmsg);
45462306a36Sopenharmony_ci	}
45562306a36Sopenharmony_cierror_no_call:
45662306a36Sopenharmony_ci	release_sock(&rx->sk);
45762306a36Sopenharmony_cierror_trace:
45862306a36Sopenharmony_ci	trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_return, ret);
45962306a36Sopenharmony_ci	return ret;
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ciwait_interrupted:
46262306a36Sopenharmony_ci	ret = sock_intr_errno(timeo);
46362306a36Sopenharmony_ciwait_error:
46462306a36Sopenharmony_ci	finish_wait(sk_sleep(&rx->sk), &wait);
46562306a36Sopenharmony_ci	call = NULL;
46662306a36Sopenharmony_ci	goto error_trace;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci/**
47062306a36Sopenharmony_ci * rxrpc_kernel_recv_data - Allow a kernel service to receive data/info
47162306a36Sopenharmony_ci * @sock: The socket that the call exists on
47262306a36Sopenharmony_ci * @call: The call to send data through
47362306a36Sopenharmony_ci * @iter: The buffer to receive into
47462306a36Sopenharmony_ci * @_len: The amount of data we want to receive (decreased on return)
47562306a36Sopenharmony_ci * @want_more: True if more data is expected to be read
47662306a36Sopenharmony_ci * @_abort: Where the abort code is stored if -ECONNABORTED is returned
47762306a36Sopenharmony_ci * @_service: Where to store the actual service ID (may be upgraded)
47862306a36Sopenharmony_ci *
47962306a36Sopenharmony_ci * Allow a kernel service to receive data and pick up information about the
48062306a36Sopenharmony_ci * state of a call.  Returns 0 if got what was asked for and there's more
48162306a36Sopenharmony_ci * available, 1 if we got what was asked for and we're at the end of the data
48262306a36Sopenharmony_ci * and -EAGAIN if we need more data.
48362306a36Sopenharmony_ci *
48462306a36Sopenharmony_ci * Note that we may return -EAGAIN to drain empty packets at the end of the
48562306a36Sopenharmony_ci * data, even if we've already copied over the requested data.
48662306a36Sopenharmony_ci *
48762306a36Sopenharmony_ci * *_abort should also be initialised to 0.
48862306a36Sopenharmony_ci */
48962306a36Sopenharmony_ciint rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
49062306a36Sopenharmony_ci			   struct iov_iter *iter, size_t *_len,
49162306a36Sopenharmony_ci			   bool want_more, u32 *_abort, u16 *_service)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	size_t offset = 0;
49462306a36Sopenharmony_ci	int ret;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci	_enter("{%d},%zu,%d", call->debug_id, *_len, want_more);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	mutex_lock(&call->user_mutex);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	ret = rxrpc_recvmsg_data(sock, call, NULL, iter, *_len, 0, &offset);
50162306a36Sopenharmony_ci	*_len -= offset;
50262306a36Sopenharmony_ci	if (ret == -EIO)
50362306a36Sopenharmony_ci		goto call_failed;
50462306a36Sopenharmony_ci	if (ret < 0)
50562306a36Sopenharmony_ci		goto out;
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	/* We can only reach here with a partially full buffer if we have
50862306a36Sopenharmony_ci	 * reached the end of the data.  We must otherwise have a full buffer
50962306a36Sopenharmony_ci	 * or have been given -EAGAIN.
51062306a36Sopenharmony_ci	 */
51162306a36Sopenharmony_ci	if (ret == 1) {
51262306a36Sopenharmony_ci		if (iov_iter_count(iter) > 0)
51362306a36Sopenharmony_ci			goto short_data;
51462306a36Sopenharmony_ci		if (!want_more)
51562306a36Sopenharmony_ci			goto read_phase_complete;
51662306a36Sopenharmony_ci		ret = 0;
51762306a36Sopenharmony_ci		goto out;
51862306a36Sopenharmony_ci	}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	if (!want_more)
52162306a36Sopenharmony_ci		goto excess_data;
52262306a36Sopenharmony_ci	goto out;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ciread_phase_complete:
52562306a36Sopenharmony_ci	ret = 1;
52662306a36Sopenharmony_ciout:
52762306a36Sopenharmony_ci	if (_service)
52862306a36Sopenharmony_ci		*_service = call->dest_srx.srx_service;
52962306a36Sopenharmony_ci	mutex_unlock(&call->user_mutex);
53062306a36Sopenharmony_ci	_leave(" = %d [%zu,%d]", ret, iov_iter_count(iter), *_abort);
53162306a36Sopenharmony_ci	return ret;
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cishort_data:
53462306a36Sopenharmony_ci	trace_rxrpc_abort(call->debug_id, rxrpc_recvmsg_short_data,
53562306a36Sopenharmony_ci			  call->cid, call->call_id, call->rx_consumed,
53662306a36Sopenharmony_ci			  0, -EBADMSG);
53762306a36Sopenharmony_ci	ret = -EBADMSG;
53862306a36Sopenharmony_ci	goto out;
53962306a36Sopenharmony_ciexcess_data:
54062306a36Sopenharmony_ci	trace_rxrpc_abort(call->debug_id, rxrpc_recvmsg_excess_data,
54162306a36Sopenharmony_ci			  call->cid, call->call_id, call->rx_consumed,
54262306a36Sopenharmony_ci			  0, -EMSGSIZE);
54362306a36Sopenharmony_ci	ret = -EMSGSIZE;
54462306a36Sopenharmony_ci	goto out;
54562306a36Sopenharmony_cicall_failed:
54662306a36Sopenharmony_ci	*_abort = call->abort_code;
54762306a36Sopenharmony_ci	ret = call->error;
54862306a36Sopenharmony_ci	if (call->completion == RXRPC_CALL_SUCCEEDED) {
54962306a36Sopenharmony_ci		ret = 1;
55062306a36Sopenharmony_ci		if (iov_iter_count(iter) > 0)
55162306a36Sopenharmony_ci			ret = -ECONNRESET;
55262306a36Sopenharmony_ci	}
55362306a36Sopenharmony_ci	goto out;
55462306a36Sopenharmony_ci}
55562306a36Sopenharmony_ciEXPORT_SYMBOL(rxrpc_kernel_recv_data);
556