summaryrefslogtreecommitdiffstats
path: root/fs/afs/cmservice.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-30 15:42:14 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-01 19:43:27 -0400
commitd001648ec7cf8b21ae9eec8b9ba4a18295adfb14 (patch)
tree830a6ec7dbc683675ba088750caeb5eafb4c8012 /fs/afs/cmservice.c
parent95ac3994514015823634ef1f7116dce24f26aa97 (diff)
rxrpc: Don't expose skbs to in-kernel users [ver #2]
Don't expose skbs to in-kernel users, such as the AFS filesystem, but instead provide a notification hook the indicates that a call needs attention and another that indicates that there's a new call to be collected. This makes the following possibilities more achievable: (1) Call refcounting can be made simpler if skbs don't hold refs to calls. (2) skbs referring to non-data events will be able to be freed much sooner rather than being queued for AFS to pick up as rxrpc_kernel_recv_data will be able to consult the call state. (3) We can shortcut the receive phase when a call is remotely aborted because we don't have to go through all the packets to get to the one cancelling the operation. (4) It makes it easier to do encryption/decryption directly between AFS's buffers and sk_buffs. (5) Encryption/decryption can more easily be done in the AFS's thread contexts - usually that of the userspace process that issued a syscall - rather than in one of rxrpc's background threads on a workqueue. (6) AFS will be able to wait synchronously on a call inside AF_RXRPC. To make this work, the following interface function has been added: int rxrpc_kernel_recv_data( struct socket *sock, struct rxrpc_call *call, void *buffer, size_t bufsize, size_t *_offset, bool want_more, u32 *_abort_code); This is the recvmsg equivalent. It allows the caller to find out about the state of a specific call and to transfer received data into a buffer piecemeal. afs_extract_data() and rxrpc_kernel_recv_data() now do all the extraction logic between them. They don't wait synchronously yet because the socket lock needs to be dealt with. Five interface functions have been removed: rxrpc_kernel_is_data_last() rxrpc_kernel_get_abort_code() rxrpc_kernel_get_error_number() rxrpc_kernel_free_skb() rxrpc_kernel_data_consumed() As a temporary hack, sk_buffs going to an in-kernel call are queued on the rxrpc_call struct (->knlrecv_queue) rather than being handed over to the in-kernel user. To process the queue internally, a temporary function, temp_deliver_data() has been added. This will be replaced with common code between the rxrpc_recvmsg() path and the kernel_rxrpc_recv_data() path in a future patch. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/cmservice.c')
-rw-r--r--fs/afs/cmservice.c142
1 files changed, 77 insertions, 65 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c
index 77ee481059ac..2037e7a77a37 100644
--- a/fs/afs/cmservice.c
+++ b/fs/afs/cmservice.c
@@ -17,15 +17,12 @@
17#include "internal.h" 17#include "internal.h"
18#include "afs_cm.h" 18#include "afs_cm.h"
19 19
20static int afs_deliver_cb_init_call_back_state(struct afs_call *, 20static int afs_deliver_cb_init_call_back_state(struct afs_call *);
21 struct sk_buff *, bool); 21static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
22static int afs_deliver_cb_init_call_back_state3(struct afs_call *, 22static int afs_deliver_cb_probe(struct afs_call *);
23 struct sk_buff *, bool); 23static int afs_deliver_cb_callback(struct afs_call *);
24static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool); 24static int afs_deliver_cb_probe_uuid(struct afs_call *);
25static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool); 25static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *);
26static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
27static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
28 struct sk_buff *, bool);
29static void afs_cm_destructor(struct afs_call *); 26static void afs_cm_destructor(struct afs_call *);
30 27
31/* 28/*
@@ -130,7 +127,7 @@ static void afs_cm_destructor(struct afs_call *call)
130 * received. The step number here must match the final number in 127 * received. The step number here must match the final number in
131 * afs_deliver_cb_callback(). 128 * afs_deliver_cb_callback().
132 */ 129 */
133 if (call->unmarshall == 6) { 130 if (call->unmarshall == 5) {
134 ASSERT(call->server && call->count && call->request); 131 ASSERT(call->server && call->count && call->request);
135 afs_break_callbacks(call->server, call->count, call->request); 132 afs_break_callbacks(call->server, call->count, call->request);
136 } 133 }
@@ -164,8 +161,7 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
164/* 161/*
165 * deliver request data to a CB.CallBack call 162 * deliver request data to a CB.CallBack call
166 */ 163 */
167static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, 164static int afs_deliver_cb_callback(struct afs_call *call)
168 bool last)
169{ 165{
170 struct sockaddr_rxrpc srx; 166 struct sockaddr_rxrpc srx;
171 struct afs_callback *cb; 167 struct afs_callback *cb;
@@ -174,7 +170,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
174 u32 tmp; 170 u32 tmp;
175 int ret, loop; 171 int ret, loop;
176 172
177 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 173 _enter("{%u}", call->unmarshall);
178 174
179 switch (call->unmarshall) { 175 switch (call->unmarshall) {
180 case 0: 176 case 0:
@@ -185,7 +181,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
185 /* extract the FID array and its count in two steps */ 181 /* extract the FID array and its count in two steps */
186 case 1: 182 case 1:
187 _debug("extract FID count"); 183 _debug("extract FID count");
188 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 184 ret = afs_extract_data(call, &call->tmp, 4, true);
189 if (ret < 0) 185 if (ret < 0)
190 return ret; 186 return ret;
191 187
@@ -202,8 +198,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
202 198
203 case 2: 199 case 2:
204 _debug("extract FID array"); 200 _debug("extract FID array");
205 ret = afs_extract_data(call, skb, last, call->buffer, 201 ret = afs_extract_data(call, call->buffer,
206 call->count * 3 * 4); 202 call->count * 3 * 4, true);
207 if (ret < 0) 203 if (ret < 0)
208 return ret; 204 return ret;
209 205
@@ -229,7 +225,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
229 /* extract the callback array and its count in two steps */ 225 /* extract the callback array and its count in two steps */
230 case 3: 226 case 3:
231 _debug("extract CB count"); 227 _debug("extract CB count");
232 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 228 ret = afs_extract_data(call, &call->tmp, 4, true);
233 if (ret < 0) 229 if (ret < 0)
234 return ret; 230 return ret;
235 231
@@ -239,13 +235,11 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
239 return -EBADMSG; 235 return -EBADMSG;
240 call->offset = 0; 236 call->offset = 0;
241 call->unmarshall++; 237 call->unmarshall++;
242 if (tmp == 0)
243 goto empty_cb_array;
244 238
245 case 4: 239 case 4:
246 _debug("extract CB array"); 240 _debug("extract CB array");
247 ret = afs_extract_data(call, skb, last, call->request, 241 ret = afs_extract_data(call, call->buffer,
248 call->count * 3 * 4); 242 call->count * 3 * 4, false);
249 if (ret < 0) 243 if (ret < 0)
250 return ret; 244 return ret;
251 245
@@ -258,15 +252,9 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
258 cb->type = ntohl(*bp++); 252 cb->type = ntohl(*bp++);
259 } 253 }
260 254
261 empty_cb_array:
262 call->offset = 0; 255 call->offset = 0;
263 call->unmarshall++; 256 call->unmarshall++;
264 257
265 case 5:
266 ret = afs_data_complete(call, skb, last);
267 if (ret < 0)
268 return ret;
269
270 /* Record that the message was unmarshalled successfully so 258 /* Record that the message was unmarshalled successfully so
271 * that the call destructor can know do the callback breaking 259 * that the call destructor can know do the callback breaking
272 * work, even if the final ACK isn't received. 260 * work, even if the final ACK isn't received.
@@ -275,7 +263,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
275 * updated also. 263 * updated also.
276 */ 264 */
277 call->unmarshall++; 265 call->unmarshall++;
278 case 6: 266 case 5:
279 break; 267 break;
280 } 268 }
281 269
@@ -310,19 +298,17 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work)
310/* 298/*
311 * deliver request data to a CB.InitCallBackState call 299 * deliver request data to a CB.InitCallBackState call
312 */ 300 */
313static int afs_deliver_cb_init_call_back_state(struct afs_call *call, 301static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
314 struct sk_buff *skb,
315 bool last)
316{ 302{
317 struct sockaddr_rxrpc srx; 303 struct sockaddr_rxrpc srx;
318 struct afs_server *server; 304 struct afs_server *server;
319 int ret; 305 int ret;
320 306
321 _enter(",{%u},%d", skb->len, last); 307 _enter("");
322 308
323 rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx); 309 rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
324 310
325 ret = afs_data_complete(call, skb, last); 311 ret = afs_extract_data(call, NULL, 0, false);
326 if (ret < 0) 312 if (ret < 0)
327 return ret; 313 return ret;
328 314
@@ -344,21 +330,61 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
344/* 330/*
345 * deliver request data to a CB.InitCallBackState3 call 331 * deliver request data to a CB.InitCallBackState3 call
346 */ 332 */
347static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, 333static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
348 struct sk_buff *skb,
349 bool last)
350{ 334{
351 struct sockaddr_rxrpc srx; 335 struct sockaddr_rxrpc srx;
352 struct afs_server *server; 336 struct afs_server *server;
337 struct afs_uuid *r;
338 unsigned loop;
339 __be32 *b;
340 int ret;
353 341
354 _enter(",{%u},%d", skb->len, last); 342 _enter("");
355 343
356 rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx); 344 rxrpc_kernel_get_peer(afs_socket, call->rxcall, &srx);
357 345
358 /* There are some arguments that we ignore */ 346 _enter("{%u}", call->unmarshall);
359 afs_data_consumed(call, skb); 347
360 if (!last) 348 switch (call->unmarshall) {
361 return -EAGAIN; 349 case 0:
350 call->offset = 0;
351 call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
352 if (!call->buffer)
353 return -ENOMEM;
354 call->unmarshall++;
355
356 case 1:
357 _debug("extract UUID");
358 ret = afs_extract_data(call, call->buffer,
359 11 * sizeof(__be32), false);
360 switch (ret) {
361 case 0: break;
362 case -EAGAIN: return 0;
363 default: return ret;
364 }
365
366 _debug("unmarshall UUID");
367 call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
368 if (!call->request)
369 return -ENOMEM;
370
371 b = call->buffer;
372 r = call->request;
373 r->time_low = ntohl(b[0]);
374 r->time_mid = ntohl(b[1]);
375 r->time_hi_and_version = ntohl(b[2]);
376 r->clock_seq_hi_and_reserved = ntohl(b[3]);
377 r->clock_seq_low = ntohl(b[4]);
378
379 for (loop = 0; loop < 6; loop++)
380 r->node[loop] = ntohl(b[loop + 5]);
381
382 call->offset = 0;
383 call->unmarshall++;
384
385 case 2:
386 break;
387 }
362 388
363 /* no unmarshalling required */ 389 /* no unmarshalling required */
364 call->state = AFS_CALL_REPLYING; 390 call->state = AFS_CALL_REPLYING;
@@ -390,14 +416,13 @@ static void SRXAFSCB_Probe(struct work_struct *work)
390/* 416/*
391 * deliver request data to a CB.Probe call 417 * deliver request data to a CB.Probe call
392 */ 418 */
393static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb, 419static int afs_deliver_cb_probe(struct afs_call *call)
394 bool last)
395{ 420{
396 int ret; 421 int ret;
397 422
398 _enter(",{%u},%d", skb->len, last); 423 _enter("");
399 424
400 ret = afs_data_complete(call, skb, last); 425 ret = afs_extract_data(call, NULL, 0, false);
401 if (ret < 0) 426 if (ret < 0)
402 return ret; 427 return ret;
403 428
@@ -435,19 +460,14 @@ static void SRXAFSCB_ProbeUuid(struct work_struct *work)
435/* 460/*
436 * deliver request data to a CB.ProbeUuid call 461 * deliver request data to a CB.ProbeUuid call
437 */ 462 */
438static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, 463static int afs_deliver_cb_probe_uuid(struct afs_call *call)
439 bool last)
440{ 464{
441 struct afs_uuid *r; 465 struct afs_uuid *r;
442 unsigned loop; 466 unsigned loop;
443 __be32 *b; 467 __be32 *b;
444 int ret; 468 int ret;
445 469
446 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 470 _enter("{%u}", call->unmarshall);
447
448 ret = afs_data_complete(call, skb, last);
449 if (ret < 0)
450 return ret;
451 471
452 switch (call->unmarshall) { 472 switch (call->unmarshall) {
453 case 0: 473 case 0:
@@ -459,8 +479,8 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
459 479
460 case 1: 480 case 1:
461 _debug("extract UUID"); 481 _debug("extract UUID");
462 ret = afs_extract_data(call, skb, last, call->buffer, 482 ret = afs_extract_data(call, call->buffer,
463 11 * sizeof(__be32)); 483 11 * sizeof(__be32), false);
464 switch (ret) { 484 switch (ret) {
465 case 0: break; 485 case 0: break;
466 case -EAGAIN: return 0; 486 case -EAGAIN: return 0;
@@ -487,16 +507,9 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
487 call->unmarshall++; 507 call->unmarshall++;
488 508
489 case 2: 509 case 2:
490 _debug("trailer");
491 if (skb->len != 0)
492 return -EBADMSG;
493 break; 510 break;
494 } 511 }
495 512
496 ret = afs_data_complete(call, skb, last);
497 if (ret < 0)
498 return ret;
499
500 call->state = AFS_CALL_REPLYING; 513 call->state = AFS_CALL_REPLYING;
501 514
502 INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); 515 INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
@@ -570,14 +583,13 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
570/* 583/*
571 * deliver request data to a CB.TellMeAboutYourself call 584 * deliver request data to a CB.TellMeAboutYourself call
572 */ 585 */
573static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call, 586static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
574 struct sk_buff *skb, bool last)
575{ 587{
576 int ret; 588 int ret;
577 589
578 _enter(",{%u},%d", skb->len, last); 590 _enter("");
579 591
580 ret = afs_data_complete(call, skb, last); 592 ret = afs_extract_data(call, NULL, 0, false);
581 if (ret < 0) 593 if (ret < 0)
582 return ret; 594 return ret;
583 595