Skip to content

Commit b0f571e

Browse files
dhowellskuba-moo
authored andcommitted
rxrpc: Fix locking in rxrpc's sendmsg
Fix three bugs in the rxrpc's sendmsg implementation: (1) rxrpc_new_client_call() should release the socket lock when returning an error from rxrpc_get_call_slot(). (2) rxrpc_wait_for_tx_window_intr() will return without the call mutex held in the event that we're interrupted by a signal whilst waiting for tx space on the socket or relocking the call mutex afterwards. Fix this by: (a) moving the unlock/lock of the call mutex up to rxrpc_send_data() such that the lock is not held around all of rxrpc_wait_for_tx_window*() and (b) indicating to higher callers whether we're return with the lock dropped. Note that this means recvmsg() will not block on this call whilst we're waiting. (3) After dropping and regaining the call mutex, rxrpc_send_data() needs to go and recheck the state of the tx_pending buffer and the tx_total_len check in case we raced with another sendmsg() on the same call. Thinking on this some more, it might make sense to have different locks for sendmsg() and recvmsg(). There's probably no need to make recvmsg() wait for sendmsg(). It does mean that recvmsg() can return MSG_EOR indicating that a call is dead before a sendmsg() to that call returns - but that can currently happen anyway. Without fix (2), something like the following can be induced: WARNING: bad unlock balance detected! 5.16.0-rc6-syzkaller #0 Not tainted ------------------------------------- syz-executor011/3597 is trying to release lock (&call->user_mutex) at: [<ffffffff885163a3>] rxrpc_do_sendmsg+0xc13/0x1350 net/rxrpc/sendmsg.c:748 but there are no more locks to release! other info that might help us debug this: no locks held by syz-executor011/3597. ... Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106 print_unlock_imbalance_bug include/trace/events/lock.h:58 [inline] __lock_release kernel/locking/lockdep.c:5306 [inline] lock_release.cold+0x49/0x4e kernel/locking/lockdep.c:5657 __mutex_unlock_slowpath+0x99/0x5e0 kernel/locking/mutex.c:900 rxrpc_do_sendmsg+0xc13/0x1350 net/rxrpc/sendmsg.c:748 rxrpc_sendmsg+0x420/0x630 net/rxrpc/af_rxrpc.c:561 sock_sendmsg_nosec net/socket.c:704 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:724 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2409 ___sys_sendmsg+0xf3/0x170 net/socket.c:2463 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2492 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x35/0xb0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x44/0xae [Thanks to Hawkins Jiawei and Khalid Masum for their attempts to fix this] Fixes: bc5e3a5 ("rxrpc: Use MSG_WAITALL to tell sendmsg() to temporarily ignore signals") Reported-by: [email protected] Signed-off-by: David Howells <[email protected]> Reviewed-by: Marc Dionne <[email protected]> Tested-by: [email protected] cc: Hawkins Jiawei <[email protected]> cc: Khalid Masum <[email protected]> cc: Dan Carpenter <[email protected]> cc: [email protected] Link: https://lore.kernel.org/r/166135894583.600315.7170979436768124075.stgit@warthog.procyon.org.uk Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 0cf731f commit b0f571e

File tree

2 files changed

+57
-39
lines changed

2 files changed

+57
-39
lines changed

net/rxrpc/call_object.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,10 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
285285
_enter("%p,%lx", rx, p->user_call_ID);
286286

287287
limiter = rxrpc_get_call_slot(p, gfp);
288-
if (!limiter)
288+
if (!limiter) {
289+
release_sock(&rx->sk);
289290
return ERR_PTR(-ERESTARTSYS);
291+
}
290292

291293
call = rxrpc_alloc_client_call(rx, srx, gfp, debug_id);
292294
if (IS_ERR(call)) {

net/rxrpc/sendmsg.c

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,7 @@ static int rxrpc_wait_for_tx_window_intr(struct rxrpc_sock *rx,
5151
return sock_intr_errno(*timeo);
5252

5353
trace_rxrpc_transmit(call, rxrpc_transmit_wait);
54-
mutex_unlock(&call->user_mutex);
5554
*timeo = schedule_timeout(*timeo);
56-
if (mutex_lock_interruptible(&call->user_mutex) < 0)
57-
return sock_intr_errno(*timeo);
5855
}
5956
}
6057

@@ -290,37 +287,48 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
290287
static int rxrpc_send_data(struct rxrpc_sock *rx,
291288
struct rxrpc_call *call,
292289
struct msghdr *msg, size_t len,
293-
rxrpc_notify_end_tx_t notify_end_tx)
290+
rxrpc_notify_end_tx_t notify_end_tx,
291+
bool *_dropped_lock)
294292
{
295293
struct rxrpc_skb_priv *sp;
296294
struct sk_buff *skb;
297295
struct sock *sk = &rx->sk;
296+
enum rxrpc_call_state state;
298297
long timeo;
299-
bool more;
300-
int ret, copied;
298+
bool more = msg->msg_flags & MSG_MORE;
299+
int ret, copied = 0;
301300

302301
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
303302

304303
/* this should be in poll */
305304
sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
306305

306+
reload:
307+
ret = -EPIPE;
307308
if (sk->sk_shutdown & SEND_SHUTDOWN)
308-
return -EPIPE;
309-
310-
more = msg->msg_flags & MSG_MORE;
311-
309+
goto maybe_error;
310+
state = READ_ONCE(call->state);
311+
ret = -ESHUTDOWN;
312+
if (state >= RXRPC_CALL_COMPLETE)
313+
goto maybe_error;
314+
ret = -EPROTO;
315+
if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
316+
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
317+
state != RXRPC_CALL_SERVER_SEND_REPLY)
318+
goto maybe_error;
319+
320+
ret = -EMSGSIZE;
312321
if (call->tx_total_len != -1) {
313-
if (len > call->tx_total_len)
314-
return -EMSGSIZE;
315-
if (!more && len != call->tx_total_len)
316-
return -EMSGSIZE;
322+
if (len - copied > call->tx_total_len)
323+
goto maybe_error;
324+
if (!more && len - copied != call->tx_total_len)
325+
goto maybe_error;
317326
}
318327

319328
skb = call->tx_pending;
320329
call->tx_pending = NULL;
321330
rxrpc_see_skb(skb, rxrpc_skb_seen);
322331

323-
copied = 0;
324332
do {
325333
/* Check to see if there's a ping ACK to reply to. */
326334
if (call->ackr_reason == RXRPC_ACK_PING_RESPONSE)
@@ -331,16 +339,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
331339

332340
_debug("alloc");
333341

334-
if (!rxrpc_check_tx_space(call, NULL)) {
335-
ret = -EAGAIN;
336-
if (msg->msg_flags & MSG_DONTWAIT)
337-
goto maybe_error;
338-
ret = rxrpc_wait_for_tx_window(rx, call,
339-
&timeo,
340-
msg->msg_flags & MSG_WAITALL);
341-
if (ret < 0)
342-
goto maybe_error;
343-
}
342+
if (!rxrpc_check_tx_space(call, NULL))
343+
goto wait_for_space;
344344

345345
/* Work out the maximum size of a packet. Assume that
346346
* the security header is going to be in the padded
@@ -468,6 +468,27 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
468468
efault:
469469
ret = -EFAULT;
470470
goto out;
471+
472+
wait_for_space:
473+
ret = -EAGAIN;
474+
if (msg->msg_flags & MSG_DONTWAIT)
475+
goto maybe_error;
476+
mutex_unlock(&call->user_mutex);
477+
*_dropped_lock = true;
478+
ret = rxrpc_wait_for_tx_window(rx, call, &timeo,
479+
msg->msg_flags & MSG_WAITALL);
480+
if (ret < 0)
481+
goto maybe_error;
482+
if (call->interruptibility == RXRPC_INTERRUPTIBLE) {
483+
if (mutex_lock_interruptible(&call->user_mutex) < 0) {
484+
ret = sock_intr_errno(timeo);
485+
goto maybe_error;
486+
}
487+
} else {
488+
mutex_lock(&call->user_mutex);
489+
}
490+
*_dropped_lock = false;
491+
goto reload;
471492
}
472493

473494
/*
@@ -629,6 +650,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
629650
enum rxrpc_call_state state;
630651
struct rxrpc_call *call;
631652
unsigned long now, j;
653+
bool dropped_lock = false;
632654
int ret;
633655

634656
struct rxrpc_send_params p = {
@@ -737,21 +759,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
737759
ret = rxrpc_send_abort_packet(call);
738760
} else if (p.command != RXRPC_CMD_SEND_DATA) {
739761
ret = -EINVAL;
740-
} else if (rxrpc_is_client_call(call) &&
741-
state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
742-
/* request phase complete for this client call */
743-
ret = -EPROTO;
744-
} else if (rxrpc_is_service_call(call) &&
745-
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
746-
state != RXRPC_CALL_SERVER_SEND_REPLY) {
747-
/* Reply phase not begun or not complete for service call. */
748-
ret = -EPROTO;
749762
} else {
750-
ret = rxrpc_send_data(rx, call, msg, len, NULL);
763+
ret = rxrpc_send_data(rx, call, msg, len, NULL, &dropped_lock);
751764
}
752765

753766
out_put_unlock:
754-
mutex_unlock(&call->user_mutex);
767+
if (!dropped_lock)
768+
mutex_unlock(&call->user_mutex);
755769
error_put:
756770
rxrpc_put_call(call, rxrpc_call_put);
757771
_leave(" = %d", ret);
@@ -779,6 +793,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
779793
struct msghdr *msg, size_t len,
780794
rxrpc_notify_end_tx_t notify_end_tx)
781795
{
796+
bool dropped_lock = false;
782797
int ret;
783798

784799
_enter("{%d,%s},", call->debug_id, rxrpc_call_states[call->state]);
@@ -796,7 +811,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
796811
case RXRPC_CALL_SERVER_ACK_REQUEST:
797812
case RXRPC_CALL_SERVER_SEND_REPLY:
798813
ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
799-
notify_end_tx);
814+
notify_end_tx, &dropped_lock);
800815
break;
801816
case RXRPC_CALL_COMPLETE:
802817
read_lock_bh(&call->state_lock);
@@ -810,7 +825,8 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
810825
break;
811826
}
812827

813-
mutex_unlock(&call->user_mutex);
828+
if (!dropped_lock)
829+
mutex_unlock(&call->user_mutex);
814830
_leave(" = %d", ret);
815831
return ret;
816832
}

0 commit comments

Comments
 (0)