Skip to content

Commit 0e50d99

Browse files
dhowellsdavem330
authored andcommitted
rxrpc: Fix a couple of potential use-after-frees
At the end of rxrpc_recvmsg(), if a call is found, the call is put and then a trace line is emitted referencing that call in a couple of places - but the call may have been deallocated by the time those traces happen. Fix this by stashing the call debug_id in a variable and passing that to the tracepoint rather than the call pointer. Fixes: 8499790 ("rxrpc: Add a tracepoint to follow what recvmsg does") Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected] Signed-off-by: David S. Miller <[email protected]>
1 parent d380569 commit 0e50d99

File tree

2 files changed

+11
-9
lines changed

2 files changed

+11
-9
lines changed

include/trace/events/rxrpc.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,10 +1062,10 @@ TRACE_EVENT(rxrpc_receive,
10621062
);
10631063

10641064
TRACE_EVENT(rxrpc_recvmsg,
1065-
TP_PROTO(struct rxrpc_call *call, enum rxrpc_recvmsg_trace why,
1065+
TP_PROTO(unsigned int call_debug_id, enum rxrpc_recvmsg_trace why,
10661066
int ret),
10671067

1068-
TP_ARGS(call, why, ret),
1068+
TP_ARGS(call_debug_id, why, ret),
10691069

10701070
TP_STRUCT__entry(
10711071
__field(unsigned int, call )
@@ -1074,7 +1074,7 @@ TRACE_EVENT(rxrpc_recvmsg,
10741074
),
10751075

10761076
TP_fast_assign(
1077-
__entry->call = call ? call->debug_id : 0;
1077+
__entry->call = call_debug_id;
10781078
__entry->why = why;
10791079
__entry->ret = ret;
10801080
),

net/rxrpc/recvmsg.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -388,13 +388,14 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
388388
struct rxrpc_call *call;
389389
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
390390
struct list_head *l;
391+
unsigned int call_debug_id = 0;
391392
size_t copied = 0;
392393
long timeo;
393394
int ret;
394395

395396
DEFINE_WAIT(wait);
396397

397-
trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_enter, 0);
398+
trace_rxrpc_recvmsg(0, rxrpc_recvmsg_enter, 0);
398399

399400
if (flags & (MSG_OOB | MSG_TRUNC))
400401
return -EOPNOTSUPP;
@@ -431,7 +432,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
431432
if (list_empty(&rx->recvmsg_q)) {
432433
if (signal_pending(current))
433434
goto wait_interrupted;
434-
trace_rxrpc_recvmsg(NULL, rxrpc_recvmsg_wait, 0);
435+
trace_rxrpc_recvmsg(0, rxrpc_recvmsg_wait, 0);
435436
timeo = schedule_timeout(timeo);
436437
}
437438
finish_wait(sk_sleep(&rx->sk), &wait);
@@ -450,7 +451,8 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
450451
rxrpc_get_call(call, rxrpc_call_get_recvmsg);
451452
write_unlock(&rx->recvmsg_lock);
452453

453-
trace_rxrpc_recvmsg(call, rxrpc_recvmsg_dequeue, 0);
454+
call_debug_id = call->debug_id;
455+
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_dequeue, 0);
454456

455457
/* We're going to drop the socket lock, so we need to lock the call
456458
* against interference by sendmsg.
@@ -531,22 +533,22 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
531533
error_unlock_call:
532534
mutex_unlock(&call->user_mutex);
533535
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
534-
trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, ret);
536+
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_return, ret);
535537
return ret;
536538

537539
error_requeue_call:
538540
if (!(flags & MSG_PEEK)) {
539541
write_lock(&rx->recvmsg_lock);
540542
list_add(&call->recvmsg_link, &rx->recvmsg_q);
541543
write_unlock(&rx->recvmsg_lock);
542-
trace_rxrpc_recvmsg(call, rxrpc_recvmsg_requeue, 0);
544+
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
543545
} else {
544546
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
545547
}
546548
error_no_call:
547549
release_sock(&rx->sk);
548550
error_trace:
549-
trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, ret);
551+
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_return, ret);
550552
return ret;
551553

552554
wait_interrupted:

0 commit comments

Comments
 (0)