diff options
author | David Howells <dhowells@redhat.com> | 2020-01-30 21:50:36 +0000 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2020-01-30 21:50:41 +0000 |
commit | 04d36d748fac349b068ef621611f454010054c58 (patch) | |
tree | 77b18f2ab733cda5c199ea289d3008df7726fa46 /net/rxrpc/ar-internal.h | |
parent | f71dbf2fb28489a79bde0dca1c8adfb9cdb20a6b (diff) | |
download | linux-04d36d748fac349b068ef621611f454010054c58.tar.gz linux-04d36d748fac349b068ef621611f454010054c58.tar.bz2 linux-04d36d748fac349b068ef621611f454010054c58.zip |
rxrpc: Fix missing active use pinning of rxrpc_local object
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+ #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: 730c5fd42c1e ("rxrpc: Fix local endpoint refcounting")
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc/ar-internal.h')
-rw-r--r-- | net/rxrpc/ar-internal.h | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 5e99df80e80a..94441fee85bc 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -1021,6 +1021,16 @@ void rxrpc_unuse_local(struct rxrpc_local *); void rxrpc_queue_local(struct rxrpc_local *); void rxrpc_destroy_all_locals(struct rxrpc_net *); +static inline bool __rxrpc_unuse_local(struct rxrpc_local *local) +{ + return atomic_dec_return(&local->active_users) == 0; +} + +static inline bool __rxrpc_use_local(struct rxrpc_local *local) +{ + return atomic_fetch_add_unless(&local->active_users, 1, 0) != 0; +} + /* * misc.c */ |