Skip to content

Commit 166c881

Browse files
committed
Merge tag 'rxrpc-next-20171111' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: Fixes Here are some patches that fix some things in AF_RXRPC: (1) Prevent notifications from being passed to a kernel service for a call that it has ended. (2) Fix a null pointer deference that occurs under some circumstances when an ACK is generated. (3) Fix a number of things to do with call expiration. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 442866f + dcbefc3 commit 166c881

File tree

7 files changed

+36
-7
lines changed

7 files changed

+36
-7
lines changed

net/rxrpc/af_rxrpc.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
322322
}
323323
EXPORT_SYMBOL(rxrpc_kernel_begin_call);
324324

325+
/*
326+
* Dummy function used to stop the notifier talking to recvmsg().
327+
*/
328+
static void rxrpc_dummy_notify_rx(struct sock *sk, struct rxrpc_call *rxcall,
329+
unsigned long call_user_ID)
330+
{
331+
}
332+
325333
/**
326334
* rxrpc_kernel_end_call - Allow a kernel service to end a call it was using
327335
* @sock: The socket the call is on
@@ -336,6 +344,14 @@ void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call)
336344

337345
mutex_lock(&call->user_mutex);
338346
rxrpc_release_call(rxrpc_sk(sock->sk), call);
347+
348+
/* Make sure we're not going to call back into a kernel service */
349+
if (call->notify_rx) {
350+
spin_lock_bh(&call->notify_lock);
351+
call->notify_rx = rxrpc_dummy_notify_rx;
352+
spin_unlock_bh(&call->notify_lock);
353+
}
354+
339355
mutex_unlock(&call->user_mutex);
340356
rxrpc_put_call(call, rxrpc_call_put_kernel);
341357
}

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,7 @@ struct rxrpc_call {
525525
unsigned long flags;
526526
unsigned long events;
527527
spinlock_t lock;
528+
spinlock_t notify_lock; /* Kernel notification lock */
528529
rwlock_t state_lock; /* lock for state transition */
529530
u32 abort_code; /* Local/remote abort code */
530531
int error; /* Local error incurred */

net/rxrpc/call_event.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ void rxrpc_process_call(struct work_struct *work)
386386

387387
now = ktime_get_real();
388388
if (ktime_before(call->expire_at, now)) {
389-
rxrpc_abort_call("EXP", call, 0, RX_CALL_TIMEOUT, -ETIME);
389+
rxrpc_abort_call("EXP", call, 0, RX_USER_ABORT, -ETIME);
390390
set_bit(RXRPC_CALL_EV_ABORT, &call->events);
391391
goto recheck_state;
392392
}

net/rxrpc/call_object.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
124124
INIT_LIST_HEAD(&call->sock_link);
125125
init_waitqueue_head(&call->waitq);
126126
spin_lock_init(&call->lock);
127+
spin_lock_init(&call->notify_lock);
127128
rwlock_init(&call->state_lock);
128129
atomic_set(&call->usage, 1);
129130
call->debug_id = atomic_inc_return(&rxrpc_debug_id);

net/rxrpc/input.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,6 @@ static bool rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
298298

299299
write_unlock(&call->state_lock);
300300
if (call->state == RXRPC_CALL_CLIENT_AWAIT_REPLY) {
301-
rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, 0, false, true,
302-
rxrpc_propose_ack_client_tx_end);
303301
trace_rxrpc_transmit(call, rxrpc_transmit_await_reply);
304302
} else {
305303
trace_rxrpc_transmit(call, rxrpc_transmit_end);

net/rxrpc/output.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ struct rxrpc_abort_buffer {
3535
/*
3636
* Fill out an ACK packet.
3737
*/
38-
static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
38+
static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn,
39+
struct rxrpc_call *call,
3940
struct rxrpc_ack_buffer *pkt,
4041
rxrpc_seq_t *_hard_ack,
4142
rxrpc_seq_t *_top,
@@ -77,8 +78,8 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_call *call,
7778
} while (before_eq(seq, top));
7879
}
7980

80-
mtu = call->conn->params.peer->if_mtu;
81-
mtu -= call->conn->params.peer->hdrsize;
81+
mtu = conn->params.peer->if_mtu;
82+
mtu -= conn->params.peer->hdrsize;
8283
jmax = (call->nr_jumbo_bad > 3) ? 1 : rxrpc_rx_jumbo_max;
8384
pkt->ackinfo.rxMTU = htonl(rxrpc_rx_mtu);
8485
pkt->ackinfo.maxMTU = htonl(mtu);
@@ -148,7 +149,7 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping)
148149
}
149150
call->ackr_reason = 0;
150151
}
151-
n = rxrpc_fill_out_ack(call, pkt, &hard_ack, &top, reason);
152+
n = rxrpc_fill_out_ack(conn, call, pkt, &hard_ack, &top, reason);
152153

153154
spin_unlock_bh(&call->lock);
154155

@@ -221,6 +222,16 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
221222
rxrpc_serial_t serial;
222223
int ret;
223224

225+
/* Don't bother sending aborts for a client call once the server has
226+
* hard-ACK'd all of its request data. After that point, we're not
227+
* going to stop the operation proceeding, and whilst we might limit
228+
* the reply, it's not worth it if we can send a new call on the same
229+
* channel instead, thereby closing off this call.
230+
*/
231+
if (rxrpc_is_client_call(call) &&
232+
test_bit(RXRPC_CALL_TX_LAST, &call->flags))
233+
return 0;
234+
224235
spin_lock_bh(&call->lock);
225236
if (call->conn)
226237
conn = rxrpc_get_connection_maybe(call->conn);

net/rxrpc/recvmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ void rxrpc_notify_socket(struct rxrpc_call *call)
4040
sk = &rx->sk;
4141
if (rx && sk->sk_state < RXRPC_CLOSE) {
4242
if (call->notify_rx) {
43+
spin_lock_bh(&call->notify_lock);
4344
call->notify_rx(sk, call, call->user_call_ID);
45+
spin_unlock_bh(&call->notify_lock);
4446
} else {
4547
write_lock_bh(&rx->recvmsg_lock);
4648
if (list_empty(&call->recvmsg_link)) {

0 commit comments

Comments
 (0)