summaryrefslogtreecommitdiffstats
path: root/net/rxrpc
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-30 09:49:28 +0100
committerDavid Howells <dhowells@redhat.com>2016-08-30 15:56:12 +0100
commitccbd3dbe85e1445231a7e0da2dada130cedce9d0 (patch)
treecb96dbb4c0f156c993f18ccf9f3b3277b3492da1 /net/rxrpc
parent3201a39ba8d7edaa1698c438fdd8f1464290d033 (diff)
downloadlinux-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.c26
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);