Blame view

net/rxrpc/recvmsg.c 18.4 KB
17926a793   David Howells   [AF_RXRPC]: Provi...
1
2
3
4
5
6
7
8
9
10
  /* RxRPC recvmsg() implementation
   *
   * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
9b6d53985   Joe Perches   rxrpc: Use pr_<le...
11
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17926a793   David Howells   [AF_RXRPC]: Provi...
12
13
  #include <linux/net.h>
  #include <linux/skbuff.h>
bc3b2d7fb   Paul Gortmaker   net: Add export.h...
14
  #include <linux/export.h>
174cd4b1e   Ingo Molnar   sched/headers: Pr...
15
  #include <linux/sched/signal.h>
17926a793   David Howells   [AF_RXRPC]: Provi...
16
17
18
19
20
  #include <net/sock.h>
  #include <net/af_rxrpc.h>
  #include "ar-internal.h"
  
  /*
248f219cb   David Howells   rxrpc: Rewrite th...
21
22
   * Post a call for attention by the socket or kernel service.  Further
   * notifications are suppressed by putting recvmsg_link on a dummy queue.
17926a793   David Howells   [AF_RXRPC]: Provi...
23
   */
248f219cb   David Howells   rxrpc: Rewrite th...
24
  void rxrpc_notify_socket(struct rxrpc_call *call)
17926a793   David Howells   [AF_RXRPC]: Provi...
25
  {
248f219cb   David Howells   rxrpc: Rewrite th...
26
27
  	struct rxrpc_sock *rx;
  	struct sock *sk;
17926a793   David Howells   [AF_RXRPC]: Provi...
28

248f219cb   David Howells   rxrpc: Rewrite th...
29
  	_enter("%d", call->debug_id);
17926a793   David Howells   [AF_RXRPC]: Provi...
30

248f219cb   David Howells   rxrpc: Rewrite th...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
  	if (!list_empty(&call->recvmsg_link))
  		return;
  
  	rcu_read_lock();
  
  	rx = rcu_dereference(call->socket);
  	sk = &rx->sk;
  	if (rx && sk->sk_state < RXRPC_CLOSE) {
  		if (call->notify_rx) {
  			call->notify_rx(sk, call, call->user_call_ID);
  		} else {
  			write_lock_bh(&rx->recvmsg_lock);
  			if (list_empty(&call->recvmsg_link)) {
  				rxrpc_get_call(call, rxrpc_call_got);
  				list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
  			}
  			write_unlock_bh(&rx->recvmsg_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
48

248f219cb   David Howells   rxrpc: Rewrite th...
49
50
51
52
53
54
  			if (!sock_flag(sk, SOCK_DEAD)) {
  				_debug("call %ps", sk->sk_data_ready);
  				sk->sk_data_ready(sk);
  			}
  		}
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
55

248f219cb   David Howells   rxrpc: Rewrite th...
56
57
58
  	rcu_read_unlock();
  	_leave("");
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
59

248f219cb   David Howells   rxrpc: Rewrite th...
60
61
62
63
64
65
66
  /*
   * Pass a call terminating message to userspace.
   */
  static int rxrpc_recvmsg_term(struct rxrpc_call *call, struct msghdr *msg)
  {
  	u32 tmp = 0;
  	int ret;
17926a793   David Howells   [AF_RXRPC]: Provi...
67

248f219cb   David Howells   rxrpc: Rewrite th...
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  	switch (call->completion) {
  	case RXRPC_CALL_SUCCEEDED:
  		ret = 0;
  		if (rxrpc_is_service_call(call))
  			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ACK, 0, &tmp);
  		break;
  	case RXRPC_CALL_REMOTELY_ABORTED:
  		tmp = call->abort_code;
  		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
  		break;
  	case RXRPC_CALL_LOCALLY_ABORTED:
  		tmp = call->abort_code;
  		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_ABORT, 4, &tmp);
  		break;
  	case RXRPC_CALL_NETWORK_ERROR:
3a92789af   David Howells   rxrpc: Use negati...
83
  		tmp = -call->error;
248f219cb   David Howells   rxrpc: Rewrite th...
84
85
86
  		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_NET_ERROR, 4, &tmp);
  		break;
  	case RXRPC_CALL_LOCAL_ERROR:
3a92789af   David Howells   rxrpc: Use negati...
87
  		tmp = -call->error;
248f219cb   David Howells   rxrpc: Rewrite th...
88
89
90
91
92
93
94
95
  		ret = put_cmsg(msg, SOL_RXRPC, RXRPC_LOCAL_ERROR, 4, &tmp);
  		break;
  	default:
  		pr_err("Invalid terminal call state %u
  ", call->state);
  		BUG();
  		break;
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
96

849979051   David Howells   rxrpc: Add a trac...
97
98
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_terminal, call->rx_hard_ack,
  			    call->rx_pkt_offset, call->rx_pkt_len, ret);
248f219cb   David Howells   rxrpc: Rewrite th...
99
100
  	return ret;
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
101

248f219cb   David Howells   rxrpc: Rewrite th...
102
103
104
105
106
107
108
109
110
111
112
113
  /*
   * Pass back notification of a new call.  The call is added to the
   * to-be-accepted list.  This means that the next call to be accepted might not
   * be the last call seen awaiting acceptance, but unless we leave this on the
   * front of the queue and block all other messages until someone gives us a
   * user_ID for it, there's not a lot we can do.
   */
  static int rxrpc_recvmsg_new_call(struct rxrpc_sock *rx,
  				  struct rxrpc_call *call,
  				  struct msghdr *msg, int flags)
  {
  	int tmp = 0, ret;
17926a793   David Howells   [AF_RXRPC]: Provi...
114

248f219cb   David Howells   rxrpc: Rewrite th...
115
  	ret = put_cmsg(msg, SOL_RXRPC, RXRPC_NEW_CALL, 0, &tmp);
17926a793   David Howells   [AF_RXRPC]: Provi...
116

248f219cb   David Howells   rxrpc: Rewrite th...
117
118
119
120
121
  	if (ret == 0 && !(flags & MSG_PEEK)) {
  		_debug("to be accepted");
  		write_lock_bh(&rx->recvmsg_lock);
  		list_del_init(&call->recvmsg_link);
  		write_unlock_bh(&rx->recvmsg_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
122

3432a757b   David Howells   rxrpc: Fix preall...
123
  		rxrpc_get_call(call, rxrpc_call_got);
248f219cb   David Howells   rxrpc: Rewrite th...
124
125
126
127
  		write_lock(&rx->call_lock);
  		list_add_tail(&call->accept_link, &rx->to_be_accepted);
  		write_unlock(&rx->call_lock);
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
128

849979051   David Howells   rxrpc: Add a trac...
129
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_to_be_accepted, 1, 0, 0, ret);
248f219cb   David Howells   rxrpc: Rewrite th...
130
131
  	return ret;
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
132

248f219cb   David Howells   rxrpc: Rewrite th...
133
134
135
  /*
   * End the packet reception phase.
   */
b69d94d79   David Howells   rxrpc: Include th...
136
  static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial)
248f219cb   David Howells   rxrpc: Rewrite th...
137
138
  {
  	_enter("%d,%s", call->debug_id, rxrpc_call_states[call->state]);
17926a793   David Howells   [AF_RXRPC]: Provi...
139

58dc63c99   David Howells   rxrpc: Add a trac...
140
  	trace_rxrpc_receive(call, rxrpc_receive_end, 0, call->rx_top);
816c9fce1   David Howells   rxrpc: Fix handli...
141
  	ASSERTCMP(call->rx_hard_ack, ==, call->rx_top);
248f219cb   David Howells   rxrpc: Rewrite th...
142
  	if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) {
b69d94d79   David Howells   rxrpc: Include th...
143
  		rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, true, false,
9c7ad4344   David Howells   rxrpc: Add tracep...
144
  				  rxrpc_propose_ack_terminal_ack);
a5af7e1fc   David Howells   rxrpc: Fix loss o...
145
  		rxrpc_send_ack_packet(call, false);
248f219cb   David Howells   rxrpc: Rewrite th...
146
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
147

248f219cb   David Howells   rxrpc: Rewrite th...
148
  	write_lock_bh(&call->state_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
149

248f219cb   David Howells   rxrpc: Rewrite th...
150
151
152
  	switch (call->state) {
  	case RXRPC_CALL_CLIENT_RECV_REPLY:
  		__rxrpc_call_completed(call);
9749fd2be   David Howells   rxrpc: Need to pr...
153
  		write_unlock_bh(&call->state_lock);
248f219cb   David Howells   rxrpc: Rewrite th...
154
  		break;
17926a793   David Howells   [AF_RXRPC]: Provi...
155

248f219cb   David Howells   rxrpc: Rewrite th...
156
  	case RXRPC_CALL_SERVER_RECV_REQUEST:
71f3ca408   David Howells   rxrpc: Improve sk...
157
  		call->tx_phase = true;
248f219cb   David Howells   rxrpc: Rewrite th...
158
  		call->state = RXRPC_CALL_SERVER_ACK_REQUEST;
9749fd2be   David Howells   rxrpc: Need to pr...
159
160
161
162
  		call->ack_at = call->expire_at;
  		write_unlock_bh(&call->state_lock);
  		rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true,
  				  rxrpc_propose_ack_processing_op);
248f219cb   David Howells   rxrpc: Rewrite th...
163
164
  		break;
  	default:
9749fd2be   David Howells   rxrpc: Need to pr...
165
  		write_unlock_bh(&call->state_lock);
248f219cb   David Howells   rxrpc: Rewrite th...
166
167
  		break;
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
168
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
169

248f219cb   David Howells   rxrpc: Rewrite th...
170
171
172
173
174
  /*
   * Discard a packet we've used up and advance the Rx window by one.
   */
  static void rxrpc_rotate_rx_window(struct rxrpc_call *call)
  {
816c9fce1   David Howells   rxrpc: Fix handli...
175
  	struct rxrpc_skb_priv *sp;
248f219cb   David Howells   rxrpc: Rewrite th...
176
  	struct sk_buff *skb;
58dc63c99   David Howells   rxrpc: Add a trac...
177
  	rxrpc_serial_t serial;
248f219cb   David Howells   rxrpc: Rewrite th...
178
  	rxrpc_seq_t hard_ack, top;
816c9fce1   David Howells   rxrpc: Fix handli...
179
  	u8 flags;
248f219cb   David Howells   rxrpc: Rewrite th...
180
181
182
183
184
185
186
187
188
189
190
  	int ix;
  
  	_enter("%d", call->debug_id);
  
  	hard_ack = call->rx_hard_ack;
  	top = smp_load_acquire(&call->rx_top);
  	ASSERT(before(hard_ack, top));
  
  	hard_ack++;
  	ix = hard_ack & RXRPC_RXTX_BUFF_MASK;
  	skb = call->rxtx_buffer[ix];
71f3ca408   David Howells   rxrpc: Improve sk...
191
  	rxrpc_see_skb(skb, rxrpc_skb_rx_rotated);
816c9fce1   David Howells   rxrpc: Fix handli...
192
193
  	sp = rxrpc_skb(skb);
  	flags = sp->hdr.flags;
58dc63c99   David Howells   rxrpc: Add a trac...
194
195
196
  	serial = sp->hdr.serial;
  	if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO)
  		serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1;
248f219cb   David Howells   rxrpc: Rewrite th...
197
198
199
200
  	call->rxtx_buffer[ix] = NULL;
  	call->rxtx_annotations[ix] = 0;
  	/* Barrier against rxrpc_input_data(). */
  	smp_store_release(&call->rx_hard_ack, hard_ack);
17926a793   David Howells   [AF_RXRPC]: Provi...
201

71f3ca408   David Howells   rxrpc: Improve sk...
202
  	rxrpc_free_skb(skb, rxrpc_skb_rx_freed);
17926a793   David Howells   [AF_RXRPC]: Provi...
203

816c9fce1   David Howells   rxrpc: Fix handli...
204
  	_debug("%u,%u,%02x", hard_ack, top, flags);
58dc63c99   David Howells   rxrpc: Add a trac...
205
  	trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack);
805b21b92   David Howells   rxrpc: Send an AC...
206
  	if (flags & RXRPC_LAST_PACKET) {
b69d94d79   David Howells   rxrpc: Include th...
207
  		rxrpc_end_rx_phase(call, serial);
805b21b92   David Howells   rxrpc: Send an AC...
208
209
210
211
212
213
214
215
216
  	} else {
  		/* Check to see if there's an ACK that needs sending. */
  		if (after_eq(hard_ack, call->ackr_consumed + 2) ||
  		    after_eq(top, call->ackr_seen + 2) ||
  		    (hard_ack == top && after(hard_ack, call->ackr_consumed)))
  			rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial,
  					  true, false,
  					  rxrpc_propose_ack_rotate_rx);
  		if (call->ackr_reason)
a5af7e1fc   David Howells   rxrpc: Fix loss o...
217
  			rxrpc_send_ack_packet(call, false);
805b21b92   David Howells   rxrpc: Send an AC...
218
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
  }
  
  /*
   * Decrypt and verify a (sub)packet.  The packet's length may be changed due to
   * padding, but if this is the case, the packet length will be resident in the
   * socket buffer.  Note that we can't modify the master skb info as the skb may
   * be the home to multiple subpackets.
   */
  static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
  			       u8 annotation,
  			       unsigned int offset, unsigned int len)
  {
  	struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
  	rxrpc_seq_t seq = sp->hdr.seq;
  	u16 cksum = sp->hdr.cksum;
  
  	_enter("");
  
  	/* For all but the head jumbo subpacket, the security checksum is in a
  	 * jumbo header immediately prior to the data.
  	 */
  	if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) {
  		__be16 tmp;
  		if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0)
  			BUG();
  		cksum = ntohs(tmp);
  		seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1;
  	}
  
  	return call->conn->security->verify_packet(call, skb, offset, len,
  						   seq, cksum);
  }
  
  /*
   * Locate the data within a packet.  This is complicated by:
   *
   * (1) An skb may contain a jumbo packet - so we have to find the appropriate
   *     subpacket.
   *
   * (2) The (sub)packets may be encrypted and, if so, the encrypted portion
   *     contains an extra header which includes the true length of the data,
   *     excluding any encrypted padding.
   */
  static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb,
  			     u8 *_annotation,
  			     unsigned int *_offset, unsigned int *_len)
  {
775e5b71d   David Howells   rxrpc: The offset...
266
  	unsigned int offset = sizeof(struct rxrpc_wire_header);
248f219cb   David Howells   rxrpc: Rewrite th...
267
268
269
  	unsigned int len = *_len;
  	int ret;
  	u8 annotation = *_annotation;
248f219cb   David Howells   rxrpc: Rewrite th...
270
  	/* Locate the subpacket */
775e5b71d   David Howells   rxrpc: The offset...
271
  	len = skb->len - offset;
248f219cb   David Howells   rxrpc: Rewrite th...
272
273
274
275
276
277
278
279
280
  	if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) {
  		offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) *
  			   RXRPC_JUMBO_SUBPKTLEN);
  		len = (annotation & RXRPC_RX_ANNO_JLAST) ?
  			skb->len - offset : RXRPC_JUMBO_SUBPKTLEN;
  	}
  
  	if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) {
  		ret = rxrpc_verify_packet(call, skb, annotation, offset, len);
17926a793   David Howells   [AF_RXRPC]: Provi...
281
  		if (ret < 0)
248f219cb   David Howells   rxrpc: Rewrite th...
282
283
284
  			return ret;
  		*_annotation |= RXRPC_RX_ANNO_VERIFIED;
  	}
17926a793   David Howells   [AF_RXRPC]: Provi...
285

248f219cb   David Howells   rxrpc: Rewrite th...
286
287
288
289
290
  	*_offset = offset;
  	*_len = len;
  	call->conn->security->locate_data(call, skb, _offset, _len);
  	return 0;
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
291

248f219cb   David Howells   rxrpc: Rewrite th...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  /*
   * Deliver messages to a call.  This keeps processing packets until the buffer
   * is filled and we find either more DATA (returns 0) or the end of the DATA
   * (returns 1).  If more packets are required, it returns -EAGAIN.
   */
  static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call,
  			      struct msghdr *msg, struct iov_iter *iter,
  			      size_t len, int flags, size_t *_offset)
  {
  	struct rxrpc_skb_priv *sp;
  	struct sk_buff *skb;
  	rxrpc_seq_t hard_ack, top, seq;
  	size_t remain;
  	bool last;
  	unsigned int rx_pkt_offset, rx_pkt_len;
816c9fce1   David Howells   rxrpc: Fix handli...
307
  	int ix, copy, ret = -EAGAIN, ret2;
248f219cb   David Howells   rxrpc: Rewrite th...
308

248f219cb   David Howells   rxrpc: Rewrite th...
309
310
  	rx_pkt_offset = call->rx_pkt_offset;
  	rx_pkt_len = call->rx_pkt_len;
816c9fce1   David Howells   rxrpc: Fix handli...
311
312
313
314
315
  	if (call->state >= RXRPC_CALL_SERVER_ACK_REQUEST) {
  		seq = call->rx_hard_ack;
  		ret = 1;
  		goto done;
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
316
317
  	/* Barriers against rxrpc_input_data(). */
  	hard_ack = call->rx_hard_ack;
d7e15835a   David Howells   rxrpc: Kernel cal...
318
319
320
321
  	seq = hard_ack + 1;
  	while (top = smp_load_acquire(&call->rx_top),
  	       before_eq(seq, top)
  	       ) {
248f219cb   David Howells   rxrpc: Rewrite th...
322
323
  		ix = seq & RXRPC_RXTX_BUFF_MASK;
  		skb = call->rxtx_buffer[ix];
849979051   David Howells   rxrpc: Add a trac...
324
325
326
  		if (!skb) {
  			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_hole, seq,
  					    rx_pkt_offset, rx_pkt_len, 0);
248f219cb   David Howells   rxrpc: Rewrite th...
327
  			break;
849979051   David Howells   rxrpc: Add a trac...
328
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
329
  		smp_rmb();
71f3ca408   David Howells   rxrpc: Improve sk...
330
  		rxrpc_see_skb(skb, rxrpc_skb_rx_seen);
248f219cb   David Howells   rxrpc: Rewrite th...
331
  		sp = rxrpc_skb(skb);
17926a793   David Howells   [AF_RXRPC]: Provi...
332

58dc63c99   David Howells   rxrpc: Add a trac...
333
334
335
  		if (!(flags & MSG_PEEK))
  			trace_rxrpc_receive(call, rxrpc_receive_front,
  					    sp->hdr.serial, seq);
248f219cb   David Howells   rxrpc: Rewrite th...
336
337
  		if (msg)
  			sock_recv_timestamp(msg, sock->sk, skb);
2e2ea51de   David Howells   rxrpc: Check the ...
338
  		if (rx_pkt_offset == 0) {
816c9fce1   David Howells   rxrpc: Fix handli...
339
340
341
  			ret2 = rxrpc_locate_data(call, skb,
  						 &call->rxtx_annotations[ix],
  						 &rx_pkt_offset, &rx_pkt_len);
849979051   David Howells   rxrpc: Add a trac...
342
343
  			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_next, seq,
  					    rx_pkt_offset, rx_pkt_len, ret2);
816c9fce1   David Howells   rxrpc: Fix handli...
344
345
  			if (ret2 < 0) {
  				ret = ret2;
2e2ea51de   David Howells   rxrpc: Check the ...
346
  				goto out;
816c9fce1   David Howells   rxrpc: Fix handli...
347
  			}
849979051   David Howells   rxrpc: Add a trac...
348
349
350
  		} else {
  			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_cont, seq,
  					    rx_pkt_offset, rx_pkt_len, 0);
2e2ea51de   David Howells   rxrpc: Check the ...
351
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
352
353
354
355
356
357
358
  
  		/* We have to handle short, empty and used-up DATA packets. */
  		remain = len - *_offset;
  		copy = rx_pkt_len;
  		if (copy > remain)
  			copy = remain;
  		if (copy > 0) {
816c9fce1   David Howells   rxrpc: Fix handli...
359
360
361
362
  			ret2 = skb_copy_datagram_iter(skb, rx_pkt_offset, iter,
  						      copy);
  			if (ret2 < 0) {
  				ret = ret2;
248f219cb   David Howells   rxrpc: Rewrite th...
363
  				goto out;
816c9fce1   David Howells   rxrpc: Fix handli...
364
  			}
248f219cb   David Howells   rxrpc: Rewrite th...
365
366
  
  			/* handle piecemeal consumption of data packets */
248f219cb   David Howells   rxrpc: Rewrite th...
367
368
369
370
  			rx_pkt_offset += copy;
  			rx_pkt_len -= copy;
  			*_offset += copy;
  		}
17926a793   David Howells   [AF_RXRPC]: Provi...
371

248f219cb   David Howells   rxrpc: Rewrite th...
372
  		if (rx_pkt_len > 0) {
849979051   David Howells   rxrpc: Add a trac...
373
374
  			trace_rxrpc_recvmsg(call, rxrpc_recvmsg_full, seq,
  					    rx_pkt_offset, rx_pkt_len, 0);
248f219cb   David Howells   rxrpc: Rewrite th...
375
  			ASSERTCMP(*_offset, ==, len);
816c9fce1   David Howells   rxrpc: Fix handli...
376
  			ret = 0;
17926a793   David Howells   [AF_RXRPC]: Provi...
377
378
  			break;
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
379
380
  		/* The whole packet has been transferred. */
  		last = sp->hdr.flags & RXRPC_LAST_PACKET;
372ee1638   David Howells   rxrpc: Fix races ...
381
  		if (!(flags & MSG_PEEK))
248f219cb   David Howells   rxrpc: Rewrite th...
382
383
384
  			rxrpc_rotate_rx_window(call);
  		rx_pkt_offset = 0;
  		rx_pkt_len = 0;
17926a793   David Howells   [AF_RXRPC]: Provi...
385

816c9fce1   David Howells   rxrpc: Fix handli...
386
387
  		if (last) {
  			ASSERTCMP(seq, ==, READ_ONCE(call->rx_top));
248f219cb   David Howells   rxrpc: Rewrite th...
388
  			ret = 1;
816c9fce1   David Howells   rxrpc: Fix handli...
389
390
  			goto out;
  		}
d7e15835a   David Howells   rxrpc: Kernel cal...
391
392
  
  		seq++;
248f219cb   David Howells   rxrpc: Rewrite th...
393
  	}
816c9fce1   David Howells   rxrpc: Fix handli...
394

248f219cb   David Howells   rxrpc: Rewrite th...
395
396
397
398
399
  out:
  	if (!(flags & MSG_PEEK)) {
  		call->rx_pkt_offset = rx_pkt_offset;
  		call->rx_pkt_len = rx_pkt_len;
  	}
816c9fce1   David Howells   rxrpc: Fix handli...
400
  done:
849979051   David Howells   rxrpc: Add a trac...
401
402
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_data_return, seq,
  			    rx_pkt_offset, rx_pkt_len, ret);
248f219cb   David Howells   rxrpc: Rewrite th...
403
404
  	return ret;
  }
17926a793   David Howells   [AF_RXRPC]: Provi...
405

248f219cb   David Howells   rxrpc: Rewrite th...
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  /*
   * Receive a message from an RxRPC socket
   * - we need to be careful about two or more threads calling recvmsg
   *   simultaneously
   */
  int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
  		  int flags)
  {
  	struct rxrpc_call *call;
  	struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
  	struct list_head *l;
  	size_t copied = 0;
  	long timeo;
  	int ret;
  
  	DEFINE_WAIT(wait);
849979051   David Howells   rxrpc: Add a trac...
422
  	trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_enter, 0, 0, 0, 0);
248f219cb   David Howells   rxrpc: Rewrite th...
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
  
  	if (flags & (MSG_OOB | MSG_TRUNC))
  		return -EOPNOTSUPP;
  
  	timeo = sock_rcvtimeo(&rx->sk, flags & MSG_DONTWAIT);
  
  try_again:
  	lock_sock(&rx->sk);
  
  	/* Return immediately if a client socket has no outstanding calls */
  	if (RB_EMPTY_ROOT(&rx->calls) &&
  	    list_empty(&rx->recvmsg_q) &&
  	    rx->sk.sk_state != RXRPC_SERVER_LISTENING) {
  		release_sock(&rx->sk);
  		return -ENODATA;
17926a793   David Howells   [AF_RXRPC]: Provi...
438
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
439
440
  	if (list_empty(&rx->recvmsg_q)) {
  		ret = -EWOULDBLOCK;
849979051   David Howells   rxrpc: Add a trac...
441
442
  		if (timeo == 0) {
  			call = NULL;
248f219cb   David Howells   rxrpc: Rewrite th...
443
  			goto error_no_call;
849979051   David Howells   rxrpc: Add a trac...
444
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
445
446
447
448
449
450
451
452
453
454
455
456
457
  
  		release_sock(&rx->sk);
  
  		/* Wait for something to happen */
  		prepare_to_wait_exclusive(sk_sleep(&rx->sk), &wait,
  					  TASK_INTERRUPTIBLE);
  		ret = sock_error(&rx->sk);
  		if (ret)
  			goto wait_error;
  
  		if (list_empty(&rx->recvmsg_q)) {
  			if (signal_pending(current))
  				goto wait_interrupted;
849979051   David Howells   rxrpc: Add a trac...
458
459
  			trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_wait,
  					    0, 0, 0, 0);
248f219cb   David Howells   rxrpc: Rewrite th...
460
  			timeo = schedule_timeout(timeo);
17926a793   David Howells   [AF_RXRPC]: Provi...
461
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
462
463
  		finish_wait(sk_sleep(&rx->sk), &wait);
  		goto try_again;
17926a793   David Howells   [AF_RXRPC]: Provi...
464
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
465
466
467
468
469
470
471
472
473
474
475
  	/* Find the next call and dequeue it if we're not just peeking.  If we
  	 * do dequeue it, that comes with a ref that we will need to release.
  	 */
  	write_lock_bh(&rx->recvmsg_lock);
  	l = rx->recvmsg_q.next;
  	call = list_entry(l, struct rxrpc_call, recvmsg_link);
  	if (!(flags & MSG_PEEK))
  		list_del_init(&call->recvmsg_link);
  	else
  		rxrpc_get_call(call, rxrpc_call_got);
  	write_unlock_bh(&rx->recvmsg_lock);
17926a793   David Howells   [AF_RXRPC]: Provi...
476

849979051   David Howells   rxrpc: Add a trac...
477
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_dequeue, 0, 0, 0, 0);
248f219cb   David Howells   rxrpc: Rewrite th...
478

540b1c48c   David Howells   rxrpc: Fix deadlo...
479
480
481
482
483
484
485
486
487
488
489
490
491
  	/* We're going to drop the socket lock, so we need to lock the call
  	 * against interference by sendmsg.
  	 */
  	if (!mutex_trylock(&call->user_mutex)) {
  		ret = -EWOULDBLOCK;
  		if (flags & MSG_DONTWAIT)
  			goto error_requeue_call;
  		ret = -ERESTARTSYS;
  		if (mutex_lock_interruptible(&call->user_mutex) < 0)
  			goto error_requeue_call;
  	}
  
  	release_sock(&rx->sk);
248f219cb   David Howells   rxrpc: Rewrite th...
492
  	if (test_bit(RXRPC_CALL_RELEASED, &call->flags))
17926a793   David Howells   [AF_RXRPC]: Provi...
493
  		BUG();
248f219cb   David Howells   rxrpc: Rewrite th...
494
495
496
497
498
499
500
501
  
  	if (test_bit(RXRPC_CALL_HAS_USERID, &call->flags)) {
  		if (flags & MSG_CMSG_COMPAT) {
  			unsigned int id32 = call->user_call_ID;
  
  			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
  				       sizeof(unsigned int), &id32);
  		} else {
f146c6e65   David Howells   rxrpc: Work aroun...
502
  			unsigned long idl = call->user_call_ID;
248f219cb   David Howells   rxrpc: Rewrite th...
503
  			ret = put_cmsg(msg, SOL_RXRPC, RXRPC_USER_CALL_ID,
f146c6e65   David Howells   rxrpc: Work aroun...
504
  				       sizeof(unsigned long), &idl);
f5c17aaeb   David Howells   rxrpc: Calls shou...
505
  		}
248f219cb   David Howells   rxrpc: Rewrite th...
506
  		if (ret < 0)
540b1c48c   David Howells   rxrpc: Fix deadlo...
507
  			goto error_unlock_call;
248f219cb   David Howells   rxrpc: Rewrite th...
508
509
510
  	}
  
  	if (msg->msg_name) {
68d6d1ae5   David Howells   rxrpc: Separate t...
511
512
513
514
515
  		struct sockaddr_rxrpc *srx = msg->msg_name;
  		size_t len = sizeof(call->peer->srx);
  
  		memcpy(msg->msg_name, &call->peer->srx, len);
  		srx->srx_service = call->service_id;
248f219cb   David Howells   rxrpc: Rewrite th...
516
517
  		msg->msg_namelen = len;
  	}
146d8fef9   David Howells   rxrpc: Call state...
518
  	switch (READ_ONCE(call->state)) {
248f219cb   David Howells   rxrpc: Rewrite th...
519
520
  	case RXRPC_CALL_SERVER_ACCEPTING:
  		ret = rxrpc_recvmsg_new_call(rx, call, msg, flags);
17926a793   David Howells   [AF_RXRPC]: Provi...
521
  		break;
248f219cb   David Howells   rxrpc: Rewrite th...
522
523
524
525
526
527
528
  	case RXRPC_CALL_CLIENT_RECV_REPLY:
  	case RXRPC_CALL_SERVER_RECV_REQUEST:
  	case RXRPC_CALL_SERVER_ACK_REQUEST:
  		ret = rxrpc_recvmsg_data(sock, call, msg, &msg->msg_iter, len,
  					 flags, &copied);
  		if (ret == -EAGAIN)
  			ret = 0;
33b603fda   David Howells   rxrpc: Requeue ca...
529
530
531
532
  
  		if (after(call->rx_top, call->rx_hard_ack) &&
  		    call->rxtx_buffer[(call->rx_hard_ack + 1) & RXRPC_RXTX_BUFF_MASK])
  			rxrpc_notify_socket(call);
17926a793   David Howells   [AF_RXRPC]: Provi...
533
534
  		break;
  	default:
248f219cb   David Howells   rxrpc: Rewrite th...
535
  		ret = 0;
17926a793   David Howells   [AF_RXRPC]: Provi...
536
537
538
539
  		break;
  	}
  
  	if (ret < 0)
540b1c48c   David Howells   rxrpc: Fix deadlo...
540
  		goto error_unlock_call;
17926a793   David Howells   [AF_RXRPC]: Provi...
541

248f219cb   David Howells   rxrpc: Rewrite th...
542
543
544
  	if (call->state == RXRPC_CALL_COMPLETE) {
  		ret = rxrpc_recvmsg_term(call, msg);
  		if (ret < 0)
540b1c48c   David Howells   rxrpc: Fix deadlo...
545
  			goto error_unlock_call;
248f219cb   David Howells   rxrpc: Rewrite th...
546
547
548
549
  		if (!(flags & MSG_PEEK))
  			rxrpc_release_call(rx, call);
  		msg->msg_flags |= MSG_EOR;
  		ret = 1;
17926a793   David Howells   [AF_RXRPC]: Provi...
550
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
551
552
553
554
555
  	if (ret == 0)
  		msg->msg_flags |= MSG_MORE;
  	else
  		msg->msg_flags &= ~MSG_MORE;
  	ret = copied;
17926a793   David Howells   [AF_RXRPC]: Provi...
556

540b1c48c   David Howells   rxrpc: Fix deadlo...
557
558
  error_unlock_call:
  	mutex_unlock(&call->user_mutex);
fff72429c   David Howells   rxrpc: Improve th...
559
  	rxrpc_put_call(call, rxrpc_call_put);
540b1c48c   David Howells   rxrpc: Fix deadlo...
560
561
562
563
564
565
566
567
568
569
570
571
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
  	return ret;
  
  error_requeue_call:
  	if (!(flags & MSG_PEEK)) {
  		write_lock_bh(&rx->recvmsg_lock);
  		list_add(&call->recvmsg_link, &rx->recvmsg_q);
  		write_unlock_bh(&rx->recvmsg_lock);
  		trace_rxrpc_recvmsg(call, rxrpc_recvmsg_requeue, 0, 0, 0, 0);
  	} else {
  		rxrpc_put_call(call, rxrpc_call_put);
  	}
248f219cb   David Howells   rxrpc: Rewrite th...
572
573
  error_no_call:
  	release_sock(&rx->sk);
849979051   David Howells   rxrpc: Add a trac...
574
  	trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
17926a793   David Howells   [AF_RXRPC]: Provi...
575
  	return ret;
17926a793   David Howells   [AF_RXRPC]: Provi...
576
577
578
  wait_interrupted:
  	ret = sock_intr_errno(timeo);
  wait_error:
4a4771a58   Eric Dumazet   net: use sk_sleep()
579
  	finish_wait(sk_sleep(&rx->sk), &wait);
849979051   David Howells   rxrpc: Add a trac...
580
581
  	call = NULL;
  	goto error_no_call;
d001648ec   David Howells   rxrpc: Don't expo...
582
  }
651350d10   David Howells   [AF_RXRPC]: Add a...
583
584
  
  /**
d001648ec   David Howells   rxrpc: Don't expo...
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
   * rxrpc_kernel_recv_data - Allow a kernel service to receive data/info
   * @sock: The socket that the call exists on
   * @call: The call to send data through
   * @buf: The buffer to receive into
   * @size: The size of the buffer, including data already read
   * @_offset: The running offset into the buffer.
   * @want_more: True if more data is expected to be read
   * @_abort: Where the abort code is stored if -ECONNABORTED is returned
   *
   * Allow a kernel service to receive data and pick up information about the
   * state of a call.  Returns 0 if got what was asked for and there's more
   * available, 1 if we got what was asked for and we're at the end of the data
   * and -EAGAIN if we need more data.
   *
   * Note that we may return -EAGAIN to drain empty packets at the end of the
   * data, even if we've already copied over the requested data.
651350d10   David Howells   [AF_RXRPC]: Add a...
601
   *
d001648ec   David Howells   rxrpc: Don't expo...
602
603
604
605
606
   * This function adds the amount it transfers to *_offset, so this should be
   * precleared as appropriate.  Note that the amount remaining in the buffer is
   * taken to be size - *_offset.
   *
   * *_abort should also be initialised to 0.
651350d10   David Howells   [AF_RXRPC]: Add a...
607
   */
d001648ec   David Howells   rxrpc: Don't expo...
608
609
610
  int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
  			   void *buf, size_t size, size_t *_offset,
  			   bool want_more, u32 *_abort)
651350d10   David Howells   [AF_RXRPC]: Add a...
611
  {
d001648ec   David Howells   rxrpc: Don't expo...
612
613
614
  	struct iov_iter iter;
  	struct kvec iov;
  	int ret;
651350d10   David Howells   [AF_RXRPC]: Add a...
615

248f219cb   David Howells   rxrpc: Rewrite th...
616
617
618
  	_enter("{%d,%s},%zu/%zu,%d",
  	       call->debug_id, rxrpc_call_states[call->state],
  	       *_offset, size, want_more);
d001648ec   David Howells   rxrpc: Don't expo...
619
620
621
  
  	ASSERTCMP(*_offset, <=, size);
  	ASSERTCMP(call->state, !=, RXRPC_CALL_SERVER_ACCEPTING);
651350d10   David Howells   [AF_RXRPC]: Add a...
622

d001648ec   David Howells   rxrpc: Don't expo...
623
624
625
  	iov.iov_base = buf + *_offset;
  	iov.iov_len = size - *_offset;
  	iov_iter_kvec(&iter, ITER_KVEC | READ, &iov, 1, size - *_offset);
540b1c48c   David Howells   rxrpc: Fix deadlo...
626
  	mutex_lock(&call->user_mutex);
d001648ec   David Howells   rxrpc: Don't expo...
627

146d8fef9   David Howells   rxrpc: Call state...
628
  	switch (READ_ONCE(call->state)) {
d001648ec   David Howells   rxrpc: Don't expo...
629
630
631
  	case RXRPC_CALL_CLIENT_RECV_REPLY:
  	case RXRPC_CALL_SERVER_RECV_REQUEST:
  	case RXRPC_CALL_SERVER_ACK_REQUEST:
248f219cb   David Howells   rxrpc: Rewrite th...
632
633
  		ret = rxrpc_recvmsg_data(sock, call, NULL, &iter, size, 0,
  					 _offset);
d001648ec   David Howells   rxrpc: Don't expo...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
  		if (ret < 0)
  			goto out;
  
  		/* We can only reach here with a partially full buffer if we
  		 * have reached the end of the data.  We must otherwise have a
  		 * full buffer or have been given -EAGAIN.
  		 */
  		if (ret == 1) {
  			if (*_offset < size)
  				goto short_data;
  			if (!want_more)
  				goto read_phase_complete;
  			ret = 0;
  			goto out;
  		}
  
  		if (!want_more)
  			goto excess_data;
  		goto out;
  
  	case RXRPC_CALL_COMPLETE:
  		goto call_complete;
  
  	default:
d001648ec   David Howells   rxrpc: Don't expo...
658
659
660
661
662
663
664
  		ret = -EINPROGRESS;
  		goto out;
  	}
  
  read_phase_complete:
  	ret = 1;
  out:
540b1c48c   David Howells   rxrpc: Fix deadlo...
665
  	mutex_unlock(&call->user_mutex);
d001648ec   David Howells   rxrpc: Don't expo...
666
667
668
669
  	_leave(" = %d [%zu,%d]", ret, *_offset, *_abort);
  	return ret;
  
  short_data:
fb46f6ee1   David Howells   rxrpc: Trace prot...
670
  	trace_rxrpc_rx_eproto(call, 0, tracepoint_string("short_data"));
d001648ec   David Howells   rxrpc: Don't expo...
671
672
673
  	ret = -EBADMSG;
  	goto out;
  excess_data:
fb46f6ee1   David Howells   rxrpc: Trace prot...
674
  	trace_rxrpc_rx_eproto(call, 0, tracepoint_string("excess_data"));
d001648ec   David Howells   rxrpc: Don't expo...
675
676
677
678
  	ret = -EMSGSIZE;
  	goto out;
  call_complete:
  	*_abort = call->abort_code;
3a92789af   David Howells   rxrpc: Use negati...
679
  	ret = call->error;
d001648ec   David Howells   rxrpc: Don't expo...
680
681
682
683
684
685
686
687
  	if (call->completion == RXRPC_CALL_SUCCEEDED) {
  		ret = 1;
  		if (size > 0)
  			ret = -ECONNRESET;
  	}
  	goto out;
  }
  EXPORT_SYMBOL(rxrpc_kernel_recv_data);