aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-08-24 09:31:43 -0400
committerDavid Howells <dhowells@redhat.com>2016-08-24 10:15:59 -0400
commitdf5d8bf70f64a2ee34234553eb215418dbc4c8f3 (patch)
tree866b273fb3eb256464fe6d10185b63054601df5a /net
parent2266ffdef5737fdfa96005204fc5606dbd559956 (diff)
rxrpc: Make /proc/net/rxrpc_calls safer
Make /proc/net/rxrpc_calls safer by stashing a copy of the peer pointer in the rxrpc_call struct and checking in the show routine that the peer pointer, the socket pointer and the local pointer obtained from the socket pointer aren't NULL before we use them. Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'net')
-rw-r--r--net/rxrpc/ar-internal.h4
-rw-r--r--net/rxrpc/call_object.c3
-rw-r--r--net/rxrpc/conn_client.c1
-rw-r--r--net/rxrpc/proc.c27
4 files changed, 26 insertions, 9 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 7296039c537a..5292bf0bce52 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -407,6 +407,7 @@ enum rxrpc_call_state {
407struct rxrpc_call { 407struct rxrpc_call {
408 struct rcu_head rcu; 408 struct rcu_head rcu;
409 struct rxrpc_connection *conn; /* connection carrying call */ 409 struct rxrpc_connection *conn; /* connection carrying call */
410 struct rxrpc_peer *peer; /* Peer record for remote address */
410 struct rxrpc_sock *socket; /* socket responsible */ 411 struct rxrpc_sock *socket; /* socket responsible */
411 struct timer_list lifetimer; /* lifetime remaining on call */ 412 struct timer_list lifetimer; /* lifetime remaining on call */
412 struct timer_list deadspan; /* reap timer for re-ACK'ing, etc */ 413 struct timer_list deadspan; /* reap timer for re-ACK'ing, etc */
@@ -717,9 +718,10 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *,
717 struct sockaddr_rxrpc *, gfp_t); 718 struct sockaddr_rxrpc *, gfp_t);
718struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t); 719struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *, gfp_t);
719 720
720static inline void rxrpc_get_peer(struct rxrpc_peer *peer) 721static inline struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *peer)
721{ 722{
722 atomic_inc(&peer->usage); 723 atomic_inc(&peer->usage);
724 return peer;
723} 725}
724 726
725static inline 727static inline
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 4af01805bfc7..f23432591a0f 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -315,6 +315,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
315 chan = sp->hdr.cid & RXRPC_CHANNELMASK; 315 chan = sp->hdr.cid & RXRPC_CHANNELMASK;
316 candidate->socket = rx; 316 candidate->socket = rx;
317 candidate->conn = conn; 317 candidate->conn = conn;
318 candidate->peer = conn->params.peer;
318 candidate->cid = sp->hdr.cid; 319 candidate->cid = sp->hdr.cid;
319 candidate->call_id = sp->hdr.callNumber; 320 candidate->call_id = sp->hdr.callNumber;
320 candidate->rx_data_post = 0; 321 candidate->rx_data_post = 0;
@@ -384,6 +385,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
384 rcu_assign_pointer(conn->channels[chan].call, call); 385 rcu_assign_pointer(conn->channels[chan].call, call);
385 sock_hold(&rx->sk); 386 sock_hold(&rx->sk);
386 rxrpc_get_connection(conn); 387 rxrpc_get_connection(conn);
388 rxrpc_get_peer(call->peer);
387 spin_unlock(&conn->channel_lock); 389 spin_unlock(&conn->channel_lock);
388 390
389 spin_lock(&conn->params.peer->lock); 391 spin_lock(&conn->params.peer->lock);
@@ -610,6 +612,7 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
610 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); 612 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);
611 613
612 rxrpc_purge_queue(&call->rx_queue); 614 rxrpc_purge_queue(&call->rx_queue);
615 rxrpc_put_peer(call->peer);
613 kmem_cache_free(rxrpc_call_jar, call); 616 kmem_cache_free(rxrpc_call_jar, call);
614} 617}
615 618
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index fc32cc67c2de..2d43c99e5360 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -280,6 +280,7 @@ attached:
280found_channel: 280found_channel:
281 _debug("found chan"); 281 _debug("found chan");
282 call->conn = conn; 282 call->conn = conn;
283 call->peer = rxrpc_get_peer(conn->params.peer);
283 call->cid = conn->proto.cid | chan; 284 call->cid = conn->proto.cid | chan;
284 call->call_id = ++conn->channels[chan].call_counter; 285 call->call_id = ++conn->channels[chan].call_counter;
285 conn->channels[chan].call_id = call->call_id; 286 conn->channels[chan].call_id = call->call_id;
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 31b7f36a39cb..53872631a66d 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -46,7 +46,9 @@ static void rxrpc_call_seq_stop(struct seq_file *seq, void *v)
46 46
47static int rxrpc_call_seq_show(struct seq_file *seq, void *v) 47static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
48{ 48{
49 struct rxrpc_connection *conn; 49 struct rxrpc_local *local;
50 struct rxrpc_sock *rx;
51 struct rxrpc_peer *peer;
50 struct rxrpc_call *call; 52 struct rxrpc_call *call;
51 char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1]; 53 char lbuff[4 + 4 + 4 + 4 + 5 + 1], rbuff[4 + 4 + 4 + 4 + 5 + 1];
52 54
@@ -60,15 +62,24 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
60 62
61 call = list_entry(v, struct rxrpc_call, link); 63 call = list_entry(v, struct rxrpc_call, link);
62 64
63 sprintf(lbuff, "%pI4:%u", 65 rx = READ_ONCE(call->socket);
64 &call->socket->local->srx.transport.sin.sin_addr, 66 if (rx) {
65 ntohs(call->socket->local->srx.transport.sin.sin_port)); 67 local = READ_ONCE(rx->local);
68 if (local)
69 sprintf(lbuff, "%pI4:%u",
70 &local->srx.transport.sin.sin_addr,
71 ntohs(local->srx.transport.sin.sin_port));
72 else
73 strcpy(lbuff, "no_local");
74 } else {
75 strcpy(lbuff, "no_socket");
76 }
66 77
67 conn = call->conn; 78 peer = call->peer;
68 if (conn) 79 if (peer)
69 sprintf(rbuff, "%pI4:%u", 80 sprintf(rbuff, "%pI4:%u",
70 &conn->params.peer->srx.transport.sin.sin_addr, 81 &peer->srx.transport.sin.sin_addr,
71 ntohs(conn->params.peer->srx.transport.sin.sin_port)); 82 ntohs(peer->srx.transport.sin.sin_port));
72 else 83 else
73 strcpy(rbuff, "no_connection"); 84 strcpy(rbuff, "no_connection");
74 85