diff options
author | David Howells <dhowells@redhat.com> | 2016-08-30 09:49:28 +0100 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2016-08-30 15:56:12 +0100 |
commit | ccbd3dbe85e1445231a7e0da2dada130cedce9d0 (patch) | |
tree | cb96dbb4c0f156c993f18ccf9f3b3277b3492da1 /net/rxrpc | |
parent | 3201a39ba8d7edaa1698c438fdd8f1464290d033 (diff) | |
download | linux-ccbd3dbe85e1445231a7e0da2dada130cedce9d0.tar.bz2 |
rxrpc: Fix a potential NULL-pointer deref in rxrpc_abort_calls
The call pointer in a channel on a connection will be NULL if there's no
active call on that channel. rxrpc_abort_calls() needs to check for this
before trying to take the call's state_lock.
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net/rxrpc')
-rw-r--r-- | net/rxrpc/conn_event.c | 26 |
1 files changed, 15 insertions, 11 deletions
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index 6296374df840..bb81801fb805 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c @@ -149,19 +149,23 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn, int state, call = rcu_dereference_protected( conn->channels[i].call, lockdep_is_held(&conn->channel_lock)); - write_lock_bh(&call->state_lock); - if (call->state <= RXRPC_CALL_COMPLETE) { - call->state = state; - if (state == RXRPC_CALL_LOCALLY_ABORTED) { - call->local_abort = conn->local_abort; - set_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events); - } else { - call->remote_abort = conn->remote_abort; - set_bit(RXRPC_CALL_EV_RCVD_ABORT, &call->events); + if (call) { + write_lock_bh(&call->state_lock); + if (call->state <= RXRPC_CALL_COMPLETE) { + call->state = state; + if (state == RXRPC_CALL_LOCALLY_ABORTED) { + call->local_abort = conn->local_abort; + set_bit(RXRPC_CALL_EV_CONN_ABORT, + &call->events); + } else { + call->remote_abort = conn->remote_abort; + set_bit(RXRPC_CALL_EV_RCVD_ABORT, + &call->events); + } + rxrpc_queue_call(call); } - rxrpc_queue_call(call); + write_unlock_bh(&call->state_lock); } - write_unlock_bh(&call->state_lock); } spin_unlock(&conn->channel_lock); |