Skip to content

Commit 843e115

Browse files
dhowellsgregkh
authored andcommitted
rxrpc: Fix missing active use pinning of rxrpc_local object
[ Upstream commit 04d36d7 ] The introduction of a split between the reference count on rxrpc_local objects and the usage count didn't quite go far enough. A number of kernel work items need to make use of the socket to perform transmission. These also need to get an active count on the local object to prevent the socket from being closed. Fix this by getting the active count in those places. Also split out the raw active count get/put functions as these places tend to hold refs on the rxrpc_local object already, so getting and putting an extra object ref is just a waste of time. The problem can lead to symptoms like: BUG: kernel NULL pointer dereference, address: 0000000000000018 .. CPU: 2 PID: 818 Comm: kworker/u9:0 Not tainted 5.5.0-fscache+ hardkernel#51 ... RIP: 0010:selinux_socket_sendmsg+0x5/0x13 ... Call Trace: security_socket_sendmsg+0x2c/0x3e sock_sendmsg+0x1a/0x46 rxrpc_send_keepalive+0x131/0x1ae rxrpc_peer_keepalive_worker+0x219/0x34b process_one_work+0x18e/0x271 worker_thread+0x1a3/0x247 kthread+0xe6/0xeb ret_from_fork+0x1f/0x30 Fixes: 730c5fd ("rxrpc: Fix local endpoint refcounting") Signed-off-by: David Howells <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 524cba2 commit 843e115

File tree

5 files changed

+62
-40
lines changed

5 files changed

+62
-40
lines changed

net/rxrpc/af_rxrpc.c

+2
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len)
194194
service_in_use:
195195
write_unlock(&local->services_lock);
196196
rxrpc_unuse_local(local);
197+
rxrpc_put_local(local);
197198
ret = -EADDRINUSE;
198199
error_unlock:
199200
release_sock(&rx->sk);
@@ -899,6 +900,7 @@ static int rxrpc_release_sock(struct sock *sk)
899900
rxrpc_purge_queue(&sk->sk_receive_queue);
900901

901902
rxrpc_unuse_local(rx->local);
903+
rxrpc_put_local(rx->local);
902904
rx->local = NULL;
903905
key_put(rx->key);
904906
rx->key = NULL;

net/rxrpc/ar-internal.h

+10
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,16 @@ void rxrpc_unuse_local(struct rxrpc_local *);
10211021
void rxrpc_queue_local(struct rxrpc_local *);
10221022
void rxrpc_destroy_all_locals(struct rxrpc_net *);
10231023

1024+
static inline bool __rxrpc_unuse_local(struct rxrpc_local *local)
1025+
{
1026+
return atomic_dec_return(&local->active_users) == 0;
1027+
}
1028+
1029+
static inline bool __rxrpc_use_local(struct rxrpc_local *local)
1030+
{
1031+
return atomic_fetch_add_unless(&local->active_users, 1, 0) != 0;
1032+
}
1033+
10241034
/*
10251035
* misc.c
10261036
*/

net/rxrpc/conn_event.c

+20-10
Original file line numberDiff line numberDiff line change
@@ -438,16 +438,12 @@ static void rxrpc_process_delayed_final_acks(struct rxrpc_connection *conn)
438438
/*
439439
* connection-level event processor
440440
*/
441-
void rxrpc_process_connection(struct work_struct *work)
441+
static void rxrpc_do_process_connection(struct rxrpc_connection *conn)
442442
{
443-
struct rxrpc_connection *conn =
444-
container_of(work, struct rxrpc_connection, processor);
445443
struct sk_buff *skb;
446444
u32 abort_code = RX_PROTOCOL_ERROR;
447445
int ret;
448446

449-
rxrpc_see_connection(conn);
450-
451447
if (test_and_clear_bit(RXRPC_CONN_EV_CHALLENGE, &conn->events))
452448
rxrpc_secure_connection(conn);
453449

@@ -475,18 +471,32 @@ void rxrpc_process_connection(struct work_struct *work)
475471
}
476472
}
477473

478-
out:
479-
rxrpc_put_connection(conn);
480-
_leave("");
481474
return;
482475

483476
requeue_and_leave:
484477
skb_queue_head(&conn->rx_queue, skb);
485-
goto out;
478+
return;
486479

487480
protocol_error:
488481
if (rxrpc_abort_connection(conn, ret, abort_code) < 0)
489482
goto requeue_and_leave;
490483
rxrpc_free_skb(skb, rxrpc_skb_freed);
491-
goto out;
484+
return;
485+
}
486+
487+
void rxrpc_process_connection(struct work_struct *work)
488+
{
489+
struct rxrpc_connection *conn =
490+
container_of(work, struct rxrpc_connection, processor);
491+
492+
rxrpc_see_connection(conn);
493+
494+
if (__rxrpc_use_local(conn->params.local)) {
495+
rxrpc_do_process_connection(conn);
496+
rxrpc_unuse_local(conn->params.local);
497+
}
498+
499+
rxrpc_put_connection(conn);
500+
_leave("");
501+
return;
492502
}

net/rxrpc/local_object.c

+7-11
Original file line numberDiff line numberDiff line change
@@ -383,14 +383,11 @@ void rxrpc_put_local(struct rxrpc_local *local)
383383
*/
384384
struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
385385
{
386-
unsigned int au;
387-
388386
local = rxrpc_get_local_maybe(local);
389387
if (!local)
390388
return NULL;
391389

392-
au = atomic_fetch_add_unless(&local->active_users, 1, 0);
393-
if (au == 0) {
390+
if (!__rxrpc_use_local(local)) {
394391
rxrpc_put_local(local);
395392
return NULL;
396393
}
@@ -404,14 +401,11 @@ struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local)
404401
*/
405402
void rxrpc_unuse_local(struct rxrpc_local *local)
406403
{
407-
unsigned int au;
408-
409404
if (local) {
410-
au = atomic_dec_return(&local->active_users);
411-
if (au == 0)
405+
if (__rxrpc_unuse_local(local)) {
406+
rxrpc_get_local(local);
412407
rxrpc_queue_local(local);
413-
else
414-
rxrpc_put_local(local);
408+
}
415409
}
416410
}
417411

@@ -468,7 +462,7 @@ static void rxrpc_local_processor(struct work_struct *work)
468462

469463
do {
470464
again = false;
471-
if (atomic_read(&local->active_users) == 0) {
465+
if (!__rxrpc_use_local(local)) {
472466
rxrpc_local_destroyer(local);
473467
break;
474468
}
@@ -482,6 +476,8 @@ static void rxrpc_local_processor(struct work_struct *work)
482476
rxrpc_process_local_events(local);
483477
again = true;
484478
}
479+
480+
__rxrpc_unuse_local(local);
485481
} while (again);
486482

487483
rxrpc_put_local(local);

net/rxrpc/peer_event.c

+23-19
Original file line numberDiff line numberDiff line change
@@ -364,27 +364,31 @@ static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet,
364364
if (!rxrpc_get_peer_maybe(peer))
365365
continue;
366366

367-
spin_unlock_bh(&rxnet->peer_hash_lock);
368-
369-
keepalive_at = peer->last_tx_at + RXRPC_KEEPALIVE_TIME;
370-
slot = keepalive_at - base;
371-
_debug("%02x peer %u t=%d {%pISp}",
372-
cursor, peer->debug_id, slot, &peer->srx.transport);
367+
if (__rxrpc_use_local(peer->local)) {
368+
spin_unlock_bh(&rxnet->peer_hash_lock);
369+
370+
keepalive_at = peer->last_tx_at + RXRPC_KEEPALIVE_TIME;
371+
slot = keepalive_at - base;
372+
_debug("%02x peer %u t=%d {%pISp}",
373+
cursor, peer->debug_id, slot, &peer->srx.transport);
374+
375+
if (keepalive_at <= base ||
376+
keepalive_at > base + RXRPC_KEEPALIVE_TIME) {
377+
rxrpc_send_keepalive(peer);
378+
slot = RXRPC_KEEPALIVE_TIME;
379+
}
373380

374-
if (keepalive_at <= base ||
375-
keepalive_at > base + RXRPC_KEEPALIVE_TIME) {
376-
rxrpc_send_keepalive(peer);
377-
slot = RXRPC_KEEPALIVE_TIME;
381+
/* A transmission to this peer occurred since last we
382+
* examined it so put it into the appropriate future
383+
* bucket.
384+
*/
385+
slot += cursor;
386+
slot &= mask;
387+
spin_lock_bh(&rxnet->peer_hash_lock);
388+
list_add_tail(&peer->keepalive_link,
389+
&rxnet->peer_keepalive[slot & mask]);
390+
rxrpc_unuse_local(peer->local);
378391
}
379-
380-
/* A transmission to this peer occurred since last we examined
381-
* it so put it into the appropriate future bucket.
382-
*/
383-
slot += cursor;
384-
slot &= mask;
385-
spin_lock_bh(&rxnet->peer_hash_lock);
386-
list_add_tail(&peer->keepalive_link,
387-
&rxnet->peer_keepalive[slot & mask]);
388392
rxrpc_put_peer_locked(peer);
389393
}
390394

0 commit comments

Comments
 (0)