mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
Merge branch 'rxrpc-miscellaneous-fixes'
David Howells says:
====================
rxrpc: Miscellaneous fixes
Here are some miscellaneous AF_RXRPC fixes for more stuff found by Sashiko[1][2]:
(1) Fix ACKALL handling by adding two more call states to simplify when
ACKs are valid.
(2) Fix connection leak from AF_RXRPC recvmsg userspace OOB handling.
(3) Fix double unlock in AF_RXRPC recvmsg userspace OOB handling.
(4) Fix AFS preallocate charge to flush the waitqueue after unlistening
the socket so that any charging thread that does manage to get started
will be waited for before socket destruction.
(5) Fix AFS OOB notify handling to cancel in-progress OOB notification
handling and then to flush the workqueue it's on.
(6) Fix handling of apparent reply reception before initial transmission
starts in client call.
(7) Fix OOB challenge leak in cleanup on notification failure.
(8) Fix infinite loop in recvmsg if OOB packet available, but no calls.
(9) Fix notify vs recvmsg race where notify thinks the call is already
queued.
(10) Fix MSG_PEEK call leak for calls with no content.
(11) Fix rxrpc_rotate_tx_window() to check that there's something in the Tx
buffer before attempting to rotate it.
====================
Link: https://patch.msgid.link/20260624163819.3017002-1-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
2c0f1b651d
|
|
@ -101,7 +101,8 @@ void afs_process_oob_queue(struct work_struct *work)
|
|||
struct sk_buff *oob;
|
||||
enum rxrpc_oob_type type;
|
||||
|
||||
while ((oob = rxrpc_kernel_dequeue_oob(net->socket, &type))) {
|
||||
while (READ_ONCE(net->live) &&
|
||||
(oob = rxrpc_kernel_dequeue_oob(net->socket, &type))) {
|
||||
switch (type) {
|
||||
case RXRPC_OOB_CHALLENGE:
|
||||
afs_respond_to_challenge(oob);
|
||||
|
|
|
|||
|
|
@ -128,8 +128,14 @@ void afs_close_socket(struct afs_net *net)
|
|||
_enter("");
|
||||
|
||||
cancel_work_sync(&net->charge_preallocation_work);
|
||||
cancel_work_sync(&net->rx_oob_work);
|
||||
/* Future work items should now see ->live is false. */
|
||||
|
||||
kernel_listen(net->socket, 0);
|
||||
|
||||
/* Make sure work items are no longer running. */
|
||||
flush_workqueue(afs_async_calls);
|
||||
cancel_work_sync(&net->charge_preallocation_work);
|
||||
|
||||
if (net->spare_incoming_call) {
|
||||
afs_put_call(net->spare_incoming_call);
|
||||
|
|
@ -143,6 +149,7 @@ void afs_close_socket(struct afs_net *net)
|
|||
|
||||
kernel_sock_shutdown(net->socket, SHUT_RDWR);
|
||||
flush_workqueue(afs_async_calls);
|
||||
cancel_work_sync(&net->rx_oob_work);
|
||||
net->socket->sk->sk_user_data = NULL;
|
||||
sock_release(net->socket);
|
||||
key_put(net->fs_cm_token_key);
|
||||
|
|
@ -984,5 +991,6 @@ static void afs_rx_notify_oob(struct sock *sk, struct sk_buff *oob)
|
|||
{
|
||||
struct afs_net *net = sk->sk_user_data;
|
||||
|
||||
schedule_work(&net->rx_oob_work);
|
||||
if (READ_ONCE(net->live))
|
||||
queue_work(afs_wq, &net->rx_oob_work);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -669,7 +669,9 @@ enum rxrpc_call_event {
|
|||
enum rxrpc_call_state {
|
||||
RXRPC_CALL_UNINITIALISED,
|
||||
RXRPC_CALL_CLIENT_AWAIT_CONN, /* - client waiting for connection to become available */
|
||||
RXRPC_CALL_CLIENT_PRE_SEND, /* - client is connected, but hasn't sent anything yet */
|
||||
RXRPC_CALL_CLIENT_SEND_REQUEST, /* - client sending request phase */
|
||||
RXRPC_CALL_CLIENT_AWAIT_ACK, /* - client awaiting ACKs of request */
|
||||
RXRPC_CALL_CLIENT_AWAIT_REPLY, /* - client awaiting reply */
|
||||
RXRPC_CALL_CLIENT_RECV_REPLY, /* - client receiving reply phase */
|
||||
RXRPC_CALL_SERVER_PREALLOC, /* - service preallocation */
|
||||
|
|
@ -1374,9 +1376,9 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
|
|||
}
|
||||
|
||||
/*
|
||||
* out_of_band.c
|
||||
* oob.c
|
||||
*/
|
||||
void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb);
|
||||
bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb);
|
||||
void rxrpc_add_pending_oob(struct rxrpc_sock *rx, struct sk_buff *skb);
|
||||
int rxrpc_sendmsg_oob(struct rxrpc_sock *rx, struct msghdr *msg, size_t len);
|
||||
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ static void rxrpc_close_tx_phase(struct rxrpc_call *call)
|
|||
|
||||
switch (__rxrpc_call_state(call)) {
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_REPLY);
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_AWAIT_ACK);
|
||||
break;
|
||||
case RXRPC_CALL_SERVER_SEND_REPLY:
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_SERVER_AWAIT_ACK);
|
||||
|
|
@ -244,6 +244,8 @@ static void rxrpc_transmit_fresh_data(struct rxrpc_call *call, unsigned int limi
|
|||
break;
|
||||
} while (req.n < limit && before(seq, send_top));
|
||||
|
||||
if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_PRE_SEND)
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_SEND_REQUEST);
|
||||
if (txb->flags & RXRPC_LAST_PACKET) {
|
||||
rxrpc_close_tx_phase(call);
|
||||
tq = NULL;
|
||||
|
|
@ -267,6 +269,7 @@ void rxrpc_transmit_some_data(struct rxrpc_call *call, unsigned int limit,
|
|||
fallthrough;
|
||||
|
||||
case RXRPC_CALL_SERVER_SEND_REPLY:
|
||||
case RXRPC_CALL_CLIENT_PRE_SEND:
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
if (!rxrpc_tx_window_space(call))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@
|
|||
const char *const rxrpc_call_states[NR__RXRPC_CALL_STATES] = {
|
||||
[RXRPC_CALL_UNINITIALISED] = "Uninit ",
|
||||
[RXRPC_CALL_CLIENT_AWAIT_CONN] = "ClWtConn",
|
||||
[RXRPC_CALL_CLIENT_PRE_SEND] = "ClPreSnd",
|
||||
[RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq",
|
||||
[RXRPC_CALL_CLIENT_AWAIT_ACK] = "ClAwtAck",
|
||||
[RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl",
|
||||
[RXRPC_CALL_CLIENT_RECV_REPLY] = "ClRcvRpl",
|
||||
[RXRPC_CALL_SERVER_PREALLOC] = "SvPrealc",
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
|
|||
trace_rxrpc_connect_call(call);
|
||||
call->tx_last_sent = ktime_get_real();
|
||||
rxrpc_start_call_timer(call);
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_SEND_REQUEST);
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_PRE_SEND);
|
||||
wake_up(&call->waitq);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -436,7 +436,7 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
|
|||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||
struct rxrpc_call *call = NULL;
|
||||
struct rxrpc_sock *rx;
|
||||
bool respond = false;
|
||||
bool respond = false, queued = false;
|
||||
|
||||
sp->chall.conn =
|
||||
rxrpc_get_connection(conn, rxrpc_conn_get_challenge_input);
|
||||
|
|
@ -472,8 +472,13 @@ static bool rxrpc_post_challenge(struct rxrpc_connection *conn,
|
|||
}
|
||||
|
||||
if (call)
|
||||
rxrpc_notify_socket_oob(call, skb);
|
||||
queued = rxrpc_notify_socket_oob(call, skb);
|
||||
rcu_read_unlock();
|
||||
if (call && !queued) {
|
||||
rxrpc_put_connection(conn, rxrpc_conn_put_challenge_input);
|
||||
sp->chall.conn = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!call)
|
||||
rxrpc_post_packet_to_conn(conn, skb);
|
||||
|
|
|
|||
|
|
@ -181,7 +181,8 @@ void rxrpc_congestion_degrade(struct rxrpc_call *call)
|
|||
if (call->cong_ca_state != RXRPC_CA_SLOW_START &&
|
||||
call->cong_ca_state != RXRPC_CA_CONGEST_AVOIDANCE)
|
||||
return;
|
||||
if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
|
||||
if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_ACK ||
|
||||
__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
|
||||
return;
|
||||
|
||||
rtt = ns_to_ktime(call->srtt_us * (NSEC_PER_USEC / 8));
|
||||
|
|
@ -236,6 +237,9 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|||
call->acks_lowest_nak = to;
|
||||
}
|
||||
|
||||
if (after(seq, to))
|
||||
return false;
|
||||
|
||||
/* We may have a left over fully-consumed buffer at the front that we
|
||||
* couldn't drop before (rotate_and_keep below).
|
||||
*/
|
||||
|
|
@ -247,7 +251,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|||
tq = call->tx_queue;
|
||||
}
|
||||
|
||||
do {
|
||||
while (before_eq(seq, to)) {
|
||||
unsigned int ix = seq - call->tx_qbase;
|
||||
|
||||
_debug("tq=%x seq=%x i=%d f=%x", tq->qbase, seq, ix, tq->bufs[ix]->flags);
|
||||
|
|
@ -317,8 +321,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} while (before_eq(seq, to));
|
||||
}
|
||||
|
||||
if (trace)
|
||||
trace_rxrpc_rack_update(call, summary);
|
||||
|
|
@ -356,6 +359,7 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
|
|||
|
||||
switch (__rxrpc_call_state(call)) {
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_ACK:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
|
||||
if (reply_begun) {
|
||||
rxrpc_set_call_state(call, RXRPC_CALL_CLIENT_RECV_REPLY);
|
||||
|
|
@ -392,6 +396,14 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call)
|
|||
trace_rxrpc_timer_can(call, rxrpc_timer_trace_delayed_ack);
|
||||
}
|
||||
|
||||
/* Deal with an apparent reply coming in before we've got the request
|
||||
* queued or transmitted.
|
||||
*/
|
||||
if (!test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
|
||||
rxrpc_proto_abort(call, top, rxrpc_eproto_early_reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!test_bit(RXRPC_CALL_TX_LAST, &call->flags)) {
|
||||
if (!rxrpc_rotate_tx_window(call, top, &summary)) {
|
||||
rxrpc_proto_abort(call, top, rxrpc_eproto_early_reply);
|
||||
|
|
@ -694,6 +706,7 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb)
|
|||
|
||||
switch (__rxrpc_call_state(call)) {
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_ACK:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
|
||||
/* Received data implicitly ACKs all of the request
|
||||
* packets we sent when we're acting as a client.
|
||||
|
|
@ -1154,10 +1167,12 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
|
|||
if (hard_ack + 1 == 0)
|
||||
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
|
||||
|
||||
/* Ignore ACKs unless we are or have just been transmitting. */
|
||||
/* Ignore ACKs unless we are transmitting or are waiting for
|
||||
* acknowledgement of the packets we've just been transmitting.
|
||||
*/
|
||||
switch (__rxrpc_call_state(call)) {
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_REPLY:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_ACK:
|
||||
case RXRPC_CALL_SERVER_SEND_REPLY:
|
||||
case RXRPC_CALL_SERVER_AWAIT_ACK:
|
||||
break;
|
||||
|
|
@ -1215,7 +1230,17 @@ static void rxrpc_input_ackall(struct rxrpc_call *call, struct sk_buff *skb)
|
|||
{
|
||||
struct rxrpc_ack_summary summary = { 0 };
|
||||
|
||||
if (rxrpc_rotate_tx_window(call, call->tx_top, &summary))
|
||||
switch (__rxrpc_call_state(call)) {
|
||||
case RXRPC_CALL_CLIENT_SEND_REQUEST:
|
||||
case RXRPC_CALL_CLIENT_AWAIT_ACK:
|
||||
case RXRPC_CALL_SERVER_SEND_REPLY:
|
||||
case RXRPC_CALL_SERVER_AWAIT_ACK:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (rxrpc_rotate_tx_window(call, call->tx_transmitted, &summary))
|
||||
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ackall);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,11 +32,12 @@ struct rxrpc_oob_params {
|
|||
* Post an out-of-band message for attention by the socket or kernel service
|
||||
* associated with a reference call.
|
||||
*/
|
||||
void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
|
||||
bool rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
|
||||
{
|
||||
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
|
||||
struct rxrpc_sock *rx;
|
||||
struct sock *sk;
|
||||
bool queued = false;
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
|
|
@ -49,6 +50,7 @@ void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
|
|||
skb->skb_mstamp_ns = rx->oob_id_counter++;
|
||||
rxrpc_get_skb(skb, rxrpc_skb_get_post_oob);
|
||||
skb_queue_tail(&rx->recvmsg_oobq, skb);
|
||||
queued = true;
|
||||
|
||||
trace_rxrpc_notify_socket(call->debug_id, sp->hdr.serial);
|
||||
if (rx->app_ops)
|
||||
|
|
@ -56,11 +58,12 @@ void rxrpc_notify_socket_oob(struct rxrpc_call *call, struct sk_buff *skb)
|
|||
}
|
||||
|
||||
spin_unlock_irq(&rx->recvmsg_lock);
|
||||
if (!rx->app_ops && !sock_flag(sk, SOCK_DEAD))
|
||||
if (queued && !rx->app_ops && !sock_flag(sk, SOCK_DEAD))
|
||||
sk->sk_data_ready(sk);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
return queued;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -210,6 +213,11 @@ static int rxrpc_respond_to_oob(struct rxrpc_sock *rx,
|
|||
break;
|
||||
}
|
||||
|
||||
switch (skb->mark) {
|
||||
case RXRPC_OOB_CHALLENGE:
|
||||
rxrpc_put_connection(sp->chall.conn, rxrpc_conn_put_oob);
|
||||
break;
|
||||
}
|
||||
rxrpc_free_skb(skb, rxrpc_skb_put_oob);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,6 @@ void rxrpc_notify_socket(struct rxrpc_call *call)
|
|||
|
||||
_enter("%d", call->debug_id);
|
||||
|
||||
if (!list_empty(&call->recvmsg_link))
|
||||
return;
|
||||
if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
|
||||
rxrpc_see_call(call, rxrpc_call_see_notify_released);
|
||||
return;
|
||||
|
|
@ -438,7 +436,8 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (list_empty(&rx->recvmsg_q)) {
|
||||
if (list_empty(&rx->recvmsg_q) &&
|
||||
skb_queue_empty_lockless(&rx->recvmsg_oobq)) {
|
||||
ret = -EWOULDBLOCK;
|
||||
if (timeo == 0) {
|
||||
call = NULL;
|
||||
|
|
@ -471,7 +470,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
release_sock(&rx->sk);
|
||||
if (ret == -EAGAIN)
|
||||
goto try_again;
|
||||
goto error_no_call;
|
||||
goto error_trace;
|
||||
}
|
||||
|
||||
/* Find the next call and dequeue it if we're not just peeking. If we
|
||||
|
|
@ -530,8 +529,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
|
|||
if (test_bit(RXRPC_CALL_RELEASED, &call->flags)) {
|
||||
rxrpc_see_call(call, rxrpc_call_see_already_released);
|
||||
mutex_unlock(&call->user_mutex);
|
||||
if (!(flags & MSG_PEEK))
|
||||
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
|
||||
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -366,7 +366,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
|
|||
if (state >= RXRPC_CALL_COMPLETE)
|
||||
goto maybe_error;
|
||||
ret = -EPROTO;
|
||||
if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
|
||||
if (state != RXRPC_CALL_CLIENT_PRE_SEND &&
|
||||
state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
|
||||
state != RXRPC_CALL_SERVER_ACK_REQUEST &&
|
||||
state != RXRPC_CALL_SERVER_SEND_REPLY) {
|
||||
/* Request phase complete for this client call */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user