1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Service connection management
4 * Copyright (C) 2016 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
8 #include <linux/slab.h>
9 #include "ar-internal.h"
11 static struct rxrpc_bundle rxrpc_service_dummy_bundle
= {
12 .usage
= ATOMIC_INIT(1),
14 .channel_lock
= __SPIN_LOCK_UNLOCKED(&rxrpc_service_dummy_bundle
.channel_lock
),
18 * Find a service connection under RCU conditions.
20 * We could use a hash table, but that is subject to bucket stuffing by an
21 * attacker as the client gets to pick the epoch and cid values and would know
22 * the hash function. So, instead, we use a hash table for the peer and from
23 * that an rbtree to find the service connection. Under ordinary circumstances
24 * it might be slower than a large hash table, but it is at least limited in
27 struct rxrpc_connection
*rxrpc_find_service_conn_rcu(struct rxrpc_peer
*peer
,
30 struct rxrpc_connection
*conn
= NULL
;
31 struct rxrpc_conn_proto k
;
32 struct rxrpc_skb_priv
*sp
= rxrpc_skb(skb
);
36 k
.epoch
= sp
->hdr
.epoch
;
37 k
.cid
= sp
->hdr
.cid
& RXRPC_CIDMASK
;
40 /* Unfortunately, rbtree walking doesn't give reliable results
41 * under just the RCU read lock, so we have to check for
44 read_seqbegin_or_lock(&peer
->service_conn_lock
, &seq
);
46 p
= rcu_dereference_raw(peer
->service_conns
.rb_node
);
48 conn
= rb_entry(p
, struct rxrpc_connection
, service_node
);
50 if (conn
->proto
.index_key
< k
.index_key
)
51 p
= rcu_dereference_raw(p
->rb_left
);
52 else if (conn
->proto
.index_key
> k
.index_key
)
53 p
= rcu_dereference_raw(p
->rb_right
);
58 } while (need_seqretry(&peer
->service_conn_lock
, seq
));
60 done_seqretry(&peer
->service_conn_lock
, seq
);
61 _leave(" = %d", conn
? conn
->debug_id
: -1);
66 * Insert a service connection into a peer's tree, thereby making it a target
67 * for incoming packets.
69 static void rxrpc_publish_service_conn(struct rxrpc_peer
*peer
,
70 struct rxrpc_connection
*conn
)
72 struct rxrpc_connection
*cursor
= NULL
;
73 struct rxrpc_conn_proto k
= conn
->proto
;
74 struct rb_node
**pp
, *parent
;
76 write_seqlock_bh(&peer
->service_conn_lock
);
78 pp
= &peer
->service_conns
.rb_node
;
82 cursor
= rb_entry(parent
,
83 struct rxrpc_connection
, service_node
);
85 if (cursor
->proto
.index_key
< k
.index_key
)
87 else if (cursor
->proto
.index_key
> k
.index_key
)
88 pp
= &(*pp
)->rb_right
;
90 goto found_extant_conn
;
93 rb_link_node_rcu(&conn
->service_node
, parent
, pp
);
94 rb_insert_color(&conn
->service_node
, &peer
->service_conns
);
96 set_bit(RXRPC_CONN_IN_SERVICE_CONNS
, &conn
->flags
);
97 write_sequnlock_bh(&peer
->service_conn_lock
);
98 _leave(" = %d [new]", conn
->debug_id
);
102 if (atomic_read(&cursor
->usage
) == 0)
103 goto replace_old_connection
;
104 write_sequnlock_bh(&peer
->service_conn_lock
);
105 /* We should not be able to get here. rxrpc_incoming_connection() is
106 * called in a non-reentrant context, so there can't be a race to
107 * insert a new connection.
111 replace_old_connection
:
112 /* The old connection is from an outdated epoch. */
113 _debug("replace conn");
114 rb_replace_node_rcu(&cursor
->service_node
,
116 &peer
->service_conns
);
117 clear_bit(RXRPC_CONN_IN_SERVICE_CONNS
, &cursor
->flags
);
122 * Preallocate a service connection. The connection is placed on the proc and
123 * reap lists so that we don't have to get the lock from BH context.
125 struct rxrpc_connection
*rxrpc_prealloc_service_connection(struct rxrpc_net
*rxnet
,
128 struct rxrpc_connection
*conn
= rxrpc_alloc_connection(gfp
);
131 /* We maintain an extra ref on the connection whilst it is on
132 * the rxrpc_connections list.
134 conn
->state
= RXRPC_CONN_SERVICE_PREALLOC
;
135 atomic_set(&conn
->usage
, 2);
136 conn
->bundle
= rxrpc_get_bundle(&rxrpc_service_dummy_bundle
);
138 atomic_inc(&rxnet
->nr_conns
);
139 write_lock(&rxnet
->conn_lock
);
140 list_add_tail(&conn
->link
, &rxnet
->service_conns
);
141 list_add_tail(&conn
->proc_link
, &rxnet
->conn_proc_list
);
142 write_unlock(&rxnet
->conn_lock
);
144 trace_rxrpc_conn(conn
->debug_id
, rxrpc_conn_new_service
,
145 atomic_read(&conn
->usage
),
146 __builtin_return_address(0));
153 * Set up an incoming connection. This is called in BH context with the RCU
156 void rxrpc_new_incoming_connection(struct rxrpc_sock
*rx
,
157 struct rxrpc_connection
*conn
,
158 const struct rxrpc_security
*sec
,
161 struct rxrpc_skb_priv
*sp
= rxrpc_skb(skb
);
165 conn
->proto
.epoch
= sp
->hdr
.epoch
;
166 conn
->proto
.cid
= sp
->hdr
.cid
& RXRPC_CIDMASK
;
167 conn
->params
.service_id
= sp
->hdr
.serviceId
;
168 conn
->service_id
= sp
->hdr
.serviceId
;
169 conn
->security_ix
= sp
->hdr
.securityIndex
;
170 conn
->out_clientflag
= 0;
171 conn
->security
= sec
;
172 if (conn
->security_ix
)
173 conn
->state
= RXRPC_CONN_SERVICE_UNSECURED
;
175 conn
->state
= RXRPC_CONN_SERVICE
;
177 /* See if we should upgrade the service. This can only happen on the
178 * first packet on a new connection. Once done, it applies to all
179 * subsequent calls on that connection.
181 if (sp
->hdr
.userStatus
== RXRPC_USERSTATUS_SERVICE_UPGRADE
&&
182 conn
->service_id
== rx
->service_upgrade
.from
)
183 conn
->service_id
= rx
->service_upgrade
.to
;
185 /* Make the connection a target for incoming packets. */
186 rxrpc_publish_service_conn(conn
->params
.peer
, conn
);
188 _net("CONNECTION new %d {%x}", conn
->debug_id
, conn
->proto
.cid
);
192 * Remove the service connection from the peer's tree, thereby removing it as a
193 * target for incoming packets.
195 void rxrpc_unpublish_service_conn(struct rxrpc_connection
*conn
)
197 struct rxrpc_peer
*peer
= conn
->params
.peer
;
199 write_seqlock_bh(&peer
->service_conn_lock
);
200 if (test_and_clear_bit(RXRPC_CONN_IN_SERVICE_CONNS
, &conn
->flags
))
201 rb_erase(&conn
->service_node
, &peer
->service_conns
);
202 write_sequnlock_bh(&peer
->service_conn_lock
);