summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2018-03-30 16:05:23 -0400
committerDavid Howells <dhowells@redhat.com>2018-03-30 16:05:23 -0400
commitd3be4d244330f7ef53242d8dc1b7f77d105e767f (patch)
tree794c9aeba90ac11e8d6a3109df89ad966adc73f6
parent88f2a8257c9aa7df957b1a79a104f348d60d8027 (diff)
rxrpc: Fix potential call vs socket/net destruction race
rxrpc_call structs don't pin sockets or network namespaces, but may attempt to access both after their refcount reaches 0 so that they can detach themselves from the network namespace. However, there's no guarantee that the socket still exists at this point (so sock_net(&call->socket->sk) may be invalid) and the namespace may have gone away if the call isn't pinning a peer. Fix this by (a) carrying a net pointer in the rxrpc_call struct and (b) waiting for all calls to be destroyed when the network namespace goes away. This was detected by checker: net/rxrpc/call_object.c:634:57: warning: incorrect type in argument 1 (different address spaces) net/rxrpc/call_object.c:634:57: expected struct sock const *sk net/rxrpc/call_object.c:634:57: got struct sock [noderef] <asn:4>*<noident> Fixes: 2baec2c3f854 ("rxrpc: Support network namespacing") Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h2
-rw-r--r--net/rxrpc/call_accept.c1
-rw-r--r--net/rxrpc/call_object.c16
-rw-r--r--net/rxrpc/net_ns.c1
4 files changed, 17 insertions, 3 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 8a348e0a9d95..2a2b0fdfb157 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -75,6 +75,7 @@ struct rxrpc_net {
75 u32 epoch; /* Local epoch for detecting local-end reset */ 75 u32 epoch; /* Local epoch for detecting local-end reset */
76 struct list_head calls; /* List of calls active in this namespace */ 76 struct list_head calls; /* List of calls active in this namespace */
77 rwlock_t call_lock; /* Lock for ->calls */ 77 rwlock_t call_lock; /* Lock for ->calls */
78 atomic_t nr_calls; /* Count of allocated calls */
78 79
79 struct list_head conn_proc_list; /* List of conns in this namespace for proc */ 80 struct list_head conn_proc_list; /* List of conns in this namespace for proc */
80 struct list_head service_conns; /* Service conns in this namespace */ 81 struct list_head service_conns; /* Service conns in this namespace */
@@ -528,6 +529,7 @@ struct rxrpc_call {
528 struct rxrpc_connection *conn; /* connection carrying call */ 529 struct rxrpc_connection *conn; /* connection carrying call */
529 struct rxrpc_peer *peer; /* Peer record for remote address */ 530 struct rxrpc_peer *peer; /* Peer record for remote address */
530 struct rxrpc_sock __rcu *socket; /* socket responsible */ 531 struct rxrpc_sock __rcu *socket; /* socket responsible */
532 struct rxrpc_net *rxnet; /* Network namespace to which call belongs */
531 struct mutex user_mutex; /* User access mutex */ 533 struct mutex user_mutex; /* User access mutex */
532 unsigned long ack_at; /* When deferred ACK needs to happen */ 534 unsigned long ack_at; /* When deferred ACK needs to happen */
533 unsigned long ack_lost_at; /* When ACK is figured as lost */ 535 unsigned long ack_lost_at; /* When ACK is figured as lost */
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 4ce24c000653..493545033e42 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -138,6 +138,7 @@ static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
138 138
139 write_unlock(&rx->call_lock); 139 write_unlock(&rx->call_lock);
140 140
141 rxnet = call->rxnet;
141 write_lock(&rxnet->call_lock); 142 write_lock(&rxnet->call_lock);
142 list_add_tail(&call->link, &rxnet->calls); 143 list_add_tail(&call->link, &rxnet->calls);
143 write_unlock(&rxnet->call_lock); 144 write_unlock(&rxnet->call_lock);
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 85b12c472522..f721c2b7e234 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -103,6 +103,7 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
103 unsigned int debug_id) 103 unsigned int debug_id)
104{ 104{
105 struct rxrpc_call *call; 105 struct rxrpc_call *call;
106 struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
106 107
107 call = kmem_cache_zalloc(rxrpc_call_jar, gfp); 108 call = kmem_cache_zalloc(rxrpc_call_jar, gfp);
108 if (!call) 109 if (!call)
@@ -153,6 +154,9 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
153 154
154 call->cong_cwnd = 2; 155 call->cong_cwnd = 2;
155 call->cong_ssthresh = RXRPC_RXTX_BUFF_SIZE - 1; 156 call->cong_ssthresh = RXRPC_RXTX_BUFF_SIZE - 1;
157
158 call->rxnet = rxnet;
159 atomic_inc(&rxnet->nr_calls);
156 return call; 160 return call;
157 161
158nomem_2: 162nomem_2:
@@ -222,7 +226,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
222 __acquires(&call->user_mutex) 226 __acquires(&call->user_mutex)
223{ 227{
224 struct rxrpc_call *call, *xcall; 228 struct rxrpc_call *call, *xcall;
225 struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); 229 struct rxrpc_net *rxnet;
226 struct rb_node *parent, **pp; 230 struct rb_node *parent, **pp;
227 const void *here = __builtin_return_address(0); 231 const void *here = __builtin_return_address(0);
228 int ret; 232 int ret;
@@ -272,6 +276,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
272 276
273 write_unlock(&rx->call_lock); 277 write_unlock(&rx->call_lock);
274 278
279 rxnet = call->rxnet;
275 write_lock(&rxnet->call_lock); 280 write_lock(&rxnet->call_lock);
276 list_add_tail(&call->link, &rxnet->calls); 281 list_add_tail(&call->link, &rxnet->calls);
277 write_unlock(&rxnet->call_lock); 282 write_unlock(&rxnet->call_lock);
@@ -617,7 +622,7 @@ void rxrpc_release_calls_on_socket(struct rxrpc_sock *rx)
617 */ 622 */
618void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op) 623void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
619{ 624{
620 struct rxrpc_net *rxnet; 625 struct rxrpc_net *rxnet = call->rxnet;
621 const void *here = __builtin_return_address(0); 626 const void *here = __builtin_return_address(0);
622 int n; 627 int n;
623 628
@@ -631,7 +636,6 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
631 ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE); 636 ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
632 637
633 if (!list_empty(&call->link)) { 638 if (!list_empty(&call->link)) {
634 rxnet = rxrpc_net(sock_net(&call->socket->sk));
635 write_lock(&rxnet->call_lock); 639 write_lock(&rxnet->call_lock);
636 list_del_init(&call->link); 640 list_del_init(&call->link);
637 write_unlock(&rxnet->call_lock); 641 write_unlock(&rxnet->call_lock);
@@ -647,11 +651,14 @@ void rxrpc_put_call(struct rxrpc_call *call, enum rxrpc_call_trace op)
647static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) 651static void rxrpc_rcu_destroy_call(struct rcu_head *rcu)
648{ 652{
649 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu); 653 struct rxrpc_call *call = container_of(rcu, struct rxrpc_call, rcu);
654 struct rxrpc_net *rxnet = call->rxnet;
650 655
651 rxrpc_put_peer(call->peer); 656 rxrpc_put_peer(call->peer);
652 kfree(call->rxtx_buffer); 657 kfree(call->rxtx_buffer);
653 kfree(call->rxtx_annotations); 658 kfree(call->rxtx_annotations);
654 kmem_cache_free(rxrpc_call_jar, call); 659 kmem_cache_free(rxrpc_call_jar, call);
660 if (atomic_dec_and_test(&rxnet->nr_calls))
661 wake_up_atomic_t(&rxnet->nr_calls);
655} 662}
656 663
657/* 664/*
@@ -716,4 +723,7 @@ void rxrpc_destroy_all_calls(struct rxrpc_net *rxnet)
716 } 723 }
717 724
718 write_unlock(&rxnet->call_lock); 725 write_unlock(&rxnet->call_lock);
726
727 atomic_dec(&rxnet->nr_calls);
728 wait_on_atomic_t(&rxnet->nr_calls, atomic_t_wait, TASK_UNINTERRUPTIBLE);
719} 729}
diff --git a/net/rxrpc/net_ns.c b/net/rxrpc/net_ns.c
index 66baf2b80b6c..101019b0be34 100644
--- a/net/rxrpc/net_ns.c
+++ b/net/rxrpc/net_ns.c
@@ -55,6 +55,7 @@ static __net_init int rxrpc_init_net(struct net *net)
55 55
56 INIT_LIST_HEAD(&rxnet->calls); 56 INIT_LIST_HEAD(&rxnet->calls);
57 rwlock_init(&rxnet->call_lock); 57 rwlock_init(&rxnet->call_lock);
58 atomic_set(&rxnet->nr_calls, 1);
58 59
59 INIT_LIST_HEAD(&rxnet->conn_proc_list); 60 INIT_LIST_HEAD(&rxnet->conn_proc_list);
60 INIT_LIST_HEAD(&rxnet->service_conns); 61 INIT_LIST_HEAD(&rxnet->service_conns);