Skip to content

Commit 372ee16

Browse files
dhowellsdavem330
authored andcommitted
rxrpc: Fix races between skb free, ACK generation and replying
Inside the kafs filesystem it is possible to occasionally have a call processed and terminated before we've had a chance to check whether we need to clean up the rx queue for that call because afs_send_simple_reply() ends the call when it is done, but this is done in a workqueue item that might happen to run to completion before afs_deliver_to_call() completes. Further, it is possible for rxrpc_kernel_send_data() to be called to send a reply before the last request-phase data skb is released. The rxrpc skb destructor is where the ACK processing is done and the call state is advanced upon release of the last skb. ACK generation is also deferred to a work item because it's possible that the skb destructor is not called in a context where kernel_sendmsg() can be invoked. To this end, the following changes are made: (1) kernel_rxrpc_data_consumed() is added. This should be called whenever an skb is emptied so as to crank the ACK and call states. This does not release the skb, however. kernel_rxrpc_free_skb() must now be called to achieve that. These together replace rxrpc_kernel_data_delivered(). (2) kernel_rxrpc_data_consumed() is wrapped by afs_data_consumed(). This makes afs_deliver_to_call() easier to work as the skb can simply be discarded unconditionally here without trying to work out what the return value of the ->deliver() function means. The ->deliver() functions can, via afs_data_complete(), afs_transfer_reply() and afs_extract_data() mark that an skb has been consumed (thereby cranking the state) without the need to conditionally free the skb to make sure the state is correct on an incoming call for when the call processor tries to send the reply. (3) rxrpc_recvmsg() now has to call kernel_rxrpc_data_consumed() when it has finished with a packet and MSG_PEEK isn't set. (4) rxrpc_packet_destructor() no longer calls rxrpc_hard_ACK_data(). Because of this, we no longer need to clear the destructor and put the call before we free the skb in cases where we don't want the ACK/call state to be cranked. (5) The ->deliver() call-type callbacks are made to return -EAGAIN rather than 0 if they expect more data (afs_extract_data() returns -EAGAIN to the delivery function already), and the caller is now responsible for producing an abort if that was the last packet. (6) There are many bits of unmarshalling code where: ret = afs_extract_data(call, skb, last, ...); switch (ret) { case 0: break; case -EAGAIN: return 0; default: return ret; } is to be found. As -EAGAIN can now be passed back to the caller, we now just return if ret < 0: ret = afs_extract_data(call, skb, last, ...); if (ret < 0) return ret; (7) Checks for trailing data and empty final data packets has been consolidated as afs_data_complete(). So: if (skb->len > 0) return -EBADMSG; if (!last) return 0; becomes: ret = afs_data_complete(call, skb, last); if (ret < 0) return ret; (8) afs_transfer_reply() now checks the amount of data it has against the amount of data desired and the amount of data in the skb and returns an error to induce an abort if we don't get exactly what we want. Without these changes, the following oops can occasionally be observed, particularly if some printks are inserted into the delivery path: general protection fault: 0000 [#1] SMP Modules linked in: kafs(E) af_rxrpc(E) [last unloaded: af_rxrpc] CPU: 0 PID: 1305 Comm: kworker/u8:3 Tainted: G E 4.7.0-fsdevel+ #1303 Hardware name: ASUS All Series/H97-PLUS, BIOS 2306 10/09/2014 Workqueue: kafsd afs_async_workfn [kafs] task: ffff88040be041c0 ti: ffff88040c070000 task.ti: ffff88040c070000 RIP: 0010:[<ffffffff8108fd3c>] [<ffffffff8108fd3c>] __lock_acquire+0xcf/0x15a1 RSP: 0018:ffff88040c073bc0 EFLAGS: 00010002 RAX: 6b6b6b6b6b6b6b6b RBX: 0000000000000000 RCX: ffff88040d29a710 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88040d29a710 RBP: ffff88040c073c70 R08: 0000000000000001 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 R13: 0000000000000000 R14: ffff88040be041c0 R15: ffffffff814c928f FS: 0000000000000000(0000) GS:ffff88041fa00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa4595f4750 CR3: 0000000001c14000 CR4: 00000000001406f0 Stack: 0000000000000006 000000000be04930 0000000000000000 ffff880400000000 ffff880400000000 ffffffff8108f847 ffff88040be041c0 ffffffff81050446 ffff8803fc08a920 ffff8803fc08a958 ffff88040be041c0 ffff88040c073c38 Call Trace: [<ffffffff8108f847>] ? mark_held_locks+0x5e/0x74 [<ffffffff81050446>] ? __local_bh_enable_ip+0x9b/0xa1 [<ffffffff8108f9ca>] ? trace_hardirqs_on_caller+0x16d/0x189 [<ffffffff810915f4>] lock_acquire+0x122/0x1b6 [<ffffffff810915f4>] ? lock_acquire+0x122/0x1b6 [<ffffffff814c928f>] ? skb_dequeue+0x18/0x61 [<ffffffff81609dbf>] _raw_spin_lock_irqsave+0x35/0x49 [<ffffffff814c928f>] ? skb_dequeue+0x18/0x61 [<ffffffff814c928f>] skb_dequeue+0x18/0x61 [<ffffffffa009aa92>] afs_deliver_to_call+0x344/0x39d [kafs] [<ffffffffa009ab37>] afs_process_async_call+0x4c/0xd5 [kafs] [<ffffffffa0099e9c>] afs_async_workfn+0xe/0x10 [kafs] [<ffffffff81063a3a>] process_one_work+0x29d/0x57c [<ffffffff81064ac2>] worker_thread+0x24a/0x385 [<ffffffff81064878>] ? rescuer_thread+0x2d0/0x2d0 [<ffffffff810696f5>] kthread+0xf3/0xfb [<ffffffff8160a6ff>] ret_from_fork+0x1f/0x40 [<ffffffff81069602>] ? kthread_create_on_node+0x1cf/0x1cf Signed-off-by: David Howells <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 54447f1 commit 372ee16

File tree

14 files changed

+225
-286
lines changed

14 files changed

+225
-286
lines changed

Documentation/networking/rxrpc.txt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -790,13 +790,12 @@ The kernel interface functions are as follows:
790790
Data messages can have their contents extracted with the usual bunch of
791791
socket buffer manipulation functions. A data message can be determined to
792792
be the last one in a sequence with rxrpc_kernel_is_data_last(). When a
793-
data message has been used up, rxrpc_kernel_data_delivered() should be
794-
called on it..
793+
data message has been used up, rxrpc_kernel_data_consumed() should be
794+
called on it.
795795

796-
Non-data messages should be handled to rxrpc_kernel_free_skb() to dispose
797-
of. It is possible to get extra refs on all types of message for later
798-
freeing, but this may pin the state of a call until the message is finally
799-
freed.
796+
Messages should be handled to rxrpc_kernel_free_skb() to dispose of. It
797+
is possible to get extra refs on all types of message for later freeing,
798+
but this may pin the state of a call until the message is finally freed.
800799

801800
(*) Accept an incoming call.
802801

@@ -821,12 +820,14 @@ The kernel interface functions are as follows:
821820
Other errors may be returned if the call had been aborted (-ECONNABORTED)
822821
or had timed out (-ETIME).
823822

824-
(*) Record the delivery of a data message and free it.
823+
(*) Record the delivery of a data message.
825824

826-
void rxrpc_kernel_data_delivered(struct sk_buff *skb);
825+
void rxrpc_kernel_data_consumed(struct rxrpc_call *call,
826+
struct sk_buff *skb);
827827

828-
This is used to record a data message as having been delivered and to
829-
update the ACK state for the call. The socket buffer will be freed.
828+
This is used to record a data message as having been consumed and to
829+
update the ACK state for the call. The message must still be passed to
830+
rxrpc_kernel_free_skb() for disposal by the caller.
830831

831832
(*) Free a message.
832833

fs/afs/cmservice.c

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
189189
case 1:
190190
_debug("extract FID count");
191191
ret = afs_extract_data(call, skb, last, &call->tmp, 4);
192-
switch (ret) {
193-
case 0: break;
194-
case -EAGAIN: return 0;
195-
default: return ret;
196-
}
192+
if (ret < 0)
193+
return ret;
197194

198195
call->count = ntohl(call->tmp);
199196
_debug("FID count: %u", call->count);
@@ -210,11 +207,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
210207
_debug("extract FID array");
211208
ret = afs_extract_data(call, skb, last, call->buffer,
212209
call->count * 3 * 4);
213-
switch (ret) {
214-
case 0: break;
215-
case -EAGAIN: return 0;
216-
default: return ret;
217-
}
210+
if (ret < 0)
211+
return ret;
218212

219213
_debug("unmarshall FID array");
220214
call->request = kcalloc(call->count,
@@ -239,11 +233,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
239233
case 3:
240234
_debug("extract CB count");
241235
ret = afs_extract_data(call, skb, last, &call->tmp, 4);
242-
switch (ret) {
243-
case 0: break;
244-
case -EAGAIN: return 0;
245-
default: return ret;
246-
}
236+
if (ret < 0)
237+
return ret;
247238

248239
tmp = ntohl(call->tmp);
249240
_debug("CB count: %u", tmp);
@@ -258,11 +249,8 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
258249
_debug("extract CB array");
259250
ret = afs_extract_data(call, skb, last, call->request,
260251
call->count * 3 * 4);
261-
switch (ret) {
262-
case 0: break;
263-
case -EAGAIN: return 0;
264-
default: return ret;
265-
}
252+
if (ret < 0)
253+
return ret;
266254

267255
_debug("unmarshall CB array");
268256
cb = call->request;
@@ -278,9 +266,9 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
278266
call->unmarshall++;
279267

280268
case 5:
281-
_debug("trailer");
282-
if (skb->len != 0)
283-
return -EBADMSG;
269+
ret = afs_data_complete(call, skb, last);
270+
if (ret < 0)
271+
return ret;
284272

285273
/* Record that the message was unmarshalled successfully so
286274
* that the call destructor can know do the callback breaking
@@ -294,8 +282,6 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
294282
break;
295283
}
296284

297-
if (!last)
298-
return 0;
299285

300286
call->state = AFS_CALL_REPLYING;
301287

@@ -335,13 +321,13 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
335321
{
336322
struct afs_server *server;
337323
struct in_addr addr;
324+
int ret;
338325

339326
_enter(",{%u},%d", skb->len, last);
340327

341-
if (skb->len > 0)
342-
return -EBADMSG;
343-
if (!last)
344-
return 0;
328+
ret = afs_data_complete(call, skb, last);
329+
if (ret < 0)
330+
return ret;
345331

346332
/* no unmarshalling required */
347333
call->state = AFS_CALL_REPLYING;
@@ -371,8 +357,10 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
371357

372358
_enter(",{%u},%d", skb->len, last);
373359

360+
/* There are some arguments that we ignore */
361+
afs_data_consumed(call, skb);
374362
if (!last)
375-
return 0;
363+
return -EAGAIN;
376364

377365
/* no unmarshalling required */
378366
call->state = AFS_CALL_REPLYING;
@@ -408,12 +396,13 @@ static void SRXAFSCB_Probe(struct work_struct *work)
408396
static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
409397
bool last)
410398
{
399+
int ret;
400+
411401
_enter(",{%u},%d", skb->len, last);
412402

413-
if (skb->len > 0)
414-
return -EBADMSG;
415-
if (!last)
416-
return 0;
403+
ret = afs_data_complete(call, skb, last);
404+
if (ret < 0)
405+
return ret;
417406

418407
/* no unmarshalling required */
419408
call->state = AFS_CALL_REPLYING;
@@ -460,10 +449,9 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
460449

461450
_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
462451

463-
if (skb->len > 0)
464-
return -EBADMSG;
465-
if (!last)
466-
return 0;
452+
ret = afs_data_complete(call, skb, last);
453+
if (ret < 0)
454+
return ret;
467455

468456
switch (call->unmarshall) {
469457
case 0:
@@ -509,8 +497,9 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
509497
break;
510498
}
511499

512-
if (!last)
513-
return 0;
500+
ret = afs_data_complete(call, skb, last);
501+
if (ret < 0)
502+
return ret;
514503

515504
call->state = AFS_CALL_REPLYING;
516505

@@ -588,12 +577,13 @@ static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
588577
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,
589578
struct sk_buff *skb, bool last)
590579
{
580+
int ret;
581+
591582
_enter(",{%u},%d", skb->len, last);
592583

593-
if (skb->len > 0)
594-
return -EBADMSG;
595-
if (!last)
596-
return 0;
584+
ret = afs_data_complete(call, skb, last);
585+
if (ret < 0)
586+
return ret;
597587

598588
/* no unmarshalling required */
599589
call->state = AFS_CALL_REPLYING;

0 commit comments

Comments
 (0)