diff options
author | David Howells <dhowells@redhat.com> | 2022-07-06 12:26:14 +0200 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2022-08-02 19:21:29 +0200 |
commit | 2757a4dc184997c66ef1de32636f73b9f21aac14 (patch) | |
tree | e5d3b2a1c35bc3d8126b6b6d4b0c32a19e3fdc6d /fs/afs/rxrpc.c | |
parent | afs: Use refcount_t rather than atomic_t (diff) | |
download | linux-2757a4dc184997c66ef1de32636f73b9f21aac14.tar.xz linux-2757a4dc184997c66ef1de32636f73b9f21aac14.zip |
afs: Fix access after dec in put functions
Reference-putting functions should not access the object being put after
decrementing the refcount unless they reduce the refcount to zero.
Fix a couple of instances of this in afs by copying the information to be
logged by tracepoint to local variables before doing the decrement.
[Fixed a bit in afs_put_server() that I'd missed but Marc caught]
Fixes: 341f741f04be ("afs: Refcount the afs_call struct")
Fixes: 452181936931 ("afs: Trace afs_server usage")
Fixes: 977e5f8ed0ab ("afs: Split the usage count on struct afs_server")
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
Link: https://lore.kernel.org/r/165911278430.3745403.16526310736054780645.stgit@warthog.procyon.org.uk/ # v1
Diffstat (limited to 'fs/afs/rxrpc.c')
-rw-r--r-- | fs/afs/rxrpc.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index d9acc43cb6f0..d5c4785c862d 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -152,7 +152,7 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, call->iter = &call->def_iter; o = atomic_inc_return(&net->nr_outstanding_calls); - trace_afs_call(call, afs_call_trace_alloc, 1, o, + trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o, __builtin_return_address(0)); return call; } @@ -163,12 +163,13 @@ static struct afs_call *afs_alloc_call(struct afs_net *net, void afs_put_call(struct afs_call *call) { struct afs_net *net = call->net; + unsigned int debug_id = call->debug_id; bool zero; int r, o; zero = __refcount_dec_and_test(&call->ref, &r); o = atomic_read(&net->nr_outstanding_calls); - trace_afs_call(call, afs_call_trace_put, r - 1, o, + trace_afs_call(debug_id, afs_call_trace_put, r - 1, o, __builtin_return_address(0)); if (zero) { @@ -186,7 +187,7 @@ void afs_put_call(struct afs_call *call) afs_put_addrlist(call->alist); kfree(call->request); - trace_afs_call(call, afs_call_trace_free, 0, o, + trace_afs_call(call->debug_id, afs_call_trace_free, 0, o, __builtin_return_address(0)); kfree(call); @@ -203,7 +204,7 @@ static struct afs_call *afs_get_call(struct afs_call *call, __refcount_inc(&call->ref, &r); - trace_afs_call(call, why, r + 1, + trace_afs_call(call->debug_id, why, r + 1, atomic_read(&call->net->nr_outstanding_calls), __builtin_return_address(0)); return call; @@ -677,7 +678,7 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall, call->need_attention = true; if (__refcount_inc_not_zero(&call->ref, &r)) { - trace_afs_call(call, afs_call_trace_wake, r + 1, + trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1, atomic_read(&call->net->nr_outstanding_calls), __builtin_return_address(0)); |