Skip to content

Commit ff88784

Browse files
dhowellsgregkh
authored andcommitted
rxrpc: Fix missing security check on incoming calls
[ Upstream commit 063c60d ] Fix rxrpc_new_incoming_call() to check that we have a suitable service key available for the combination of service ID and security class of a new incoming call - and to reject calls for which we don't. This causes an assertion like the following to appear: rxrpc: Assertion failed - 6(0x6) == 12(0xc) is false kernel BUG at net/rxrpc/call_object.c:456! Where call->state is RXRPC_CALL_SERVER_SECURING (6) rather than RXRPC_CALL_COMPLETE (12). Fixes: 248f219 ("rxrpc: Rewrite the data and ack handling code") Reported-by: Marc Dionne <marc.dionne@auristor.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f928970 commit ff88784

6 files changed

Lines changed: 59 additions & 60 deletions

File tree

net/rxrpc/ar-internal.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ struct rxrpc_skb_priv {
209209
struct rxrpc_security {
210210
const char *name; /* name of this service */
211211
u8 security_index; /* security type provided */
212+
u32 no_key_abort; /* Abort code indicating no key */
212213

213214
/* Initialise a security service */
214215
int (*init)(void);
@@ -977,8 +978,9 @@ static inline void rxrpc_reduce_conn_timer(struct rxrpc_connection *conn,
977978
struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *,
978979
struct sk_buff *);
979980
struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t);
980-
void rxrpc_new_incoming_connection(struct rxrpc_sock *,
981-
struct rxrpc_connection *, struct sk_buff *);
981+
void rxrpc_new_incoming_connection(struct rxrpc_sock *, struct rxrpc_connection *,
982+
const struct rxrpc_security *, struct key *,
983+
struct sk_buff *);
982984
void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
983985

984986
/*
@@ -1103,7 +1105,9 @@ extern const struct rxrpc_security rxkad;
11031105
int __init rxrpc_init_security(void);
11041106
void rxrpc_exit_security(void);
11051107
int rxrpc_init_client_conn_security(struct rxrpc_connection *);
1106-
int rxrpc_init_server_conn_security(struct rxrpc_connection *);
1108+
bool rxrpc_look_up_server_security(struct rxrpc_local *, struct rxrpc_sock *,
1109+
const struct rxrpc_security **, struct key **,
1110+
struct sk_buff *);
11071111

11081112
/*
11091113
* sendmsg.c

net/rxrpc/call_accept.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
263263
struct rxrpc_local *local,
264264
struct rxrpc_peer *peer,
265265
struct rxrpc_connection *conn,
266+
const struct rxrpc_security *sec,
267+
struct key *key,
266268
struct sk_buff *skb)
267269
{
268270
struct rxrpc_backlog *b = rx->backlog;
@@ -310,7 +312,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
310312
conn->params.local = rxrpc_get_local(local);
311313
conn->params.peer = peer;
312314
rxrpc_see_connection(conn);
313-
rxrpc_new_incoming_connection(rx, conn, skb);
315+
rxrpc_new_incoming_connection(rx, conn, sec, key, skb);
314316
} else {
315317
rxrpc_get_connection(conn);
316318
}
@@ -349,9 +351,11 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
349351
struct sk_buff *skb)
350352
{
351353
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
354+
const struct rxrpc_security *sec = NULL;
352355
struct rxrpc_connection *conn;
353356
struct rxrpc_peer *peer = NULL;
354-
struct rxrpc_call *call;
357+
struct rxrpc_call *call = NULL;
358+
struct key *key = NULL;
355359

356360
_enter("");
357361

@@ -372,7 +376,11 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
372376
*/
373377
conn = rxrpc_find_connection_rcu(local, skb, &peer);
374378

375-
call = rxrpc_alloc_incoming_call(rx, local, peer, conn, skb);
379+
if (!conn && !rxrpc_look_up_server_security(local, rx, &sec, &key, skb))
380+
goto no_call;
381+
382+
call = rxrpc_alloc_incoming_call(rx, local, peer, conn, sec, key, skb);
383+
key_put(key);
376384
if (!call) {
377385
skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
378386
goto no_call;

net/rxrpc/conn_event.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -376,21 +376,7 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn)
376376
_enter("{%d}", conn->debug_id);
377377

378378
ASSERT(conn->security_ix != 0);
379-
380-
if (!conn->params.key) {
381-
_debug("set up security");
382-
ret = rxrpc_init_server_conn_security(conn);
383-
switch (ret) {
384-
case 0:
385-
break;
386-
case -ENOENT:
387-
abort_code = RX_CALL_DEAD;
388-
goto abort;
389-
default:
390-
abort_code = RXKADNOAUTH;
391-
goto abort;
392-
}
393-
}
379+
ASSERT(conn->server_key);
394380

395381
if (conn->security->issue_challenge(conn) < 0) {
396382
abort_code = RX_CALL_DEAD;

net/rxrpc/conn_service.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
148148
*/
149149
void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
150150
struct rxrpc_connection *conn,
151+
const struct rxrpc_security *sec,
152+
struct key *key,
151153
struct sk_buff *skb)
152154
{
153155
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -160,6 +162,8 @@ void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
160162
conn->service_id = sp->hdr.serviceId;
161163
conn->security_ix = sp->hdr.securityIndex;
162164
conn->out_clientflag = 0;
165+
conn->security = sec;
166+
conn->server_key = key_get(key);
163167
if (conn->security_ix)
164168
conn->state = RXRPC_CONN_SERVICE_UNSECURED;
165169
else

net/rxrpc/rxkad.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -648,9 +648,9 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
648648
u32 serial;
649649
int ret;
650650

651-
_enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
651+
_enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
652652

653-
ret = key_validate(conn->params.key);
653+
ret = key_validate(conn->server_key);
654654
if (ret < 0)
655655
return ret;
656656

@@ -1293,6 +1293,7 @@ static void rxkad_exit(void)
12931293
const struct rxrpc_security rxkad = {
12941294
.name = "rxkad",
12951295
.security_index = RXRPC_SECURITY_RXKAD,
1296+
.no_key_abort = RXKADUNKNOWNKEY,
12961297
.init = rxkad_init,
12971298
.exit = rxkad_exit,
12981299
.init_connection_security = rxkad_init_connection_security,

net/rxrpc/security.c

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -101,62 +101,58 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
101101
}
102102

103103
/*
104-
* initialise the security on a server connection
104+
* Find the security key for a server connection.
105105
*/
106-
int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
106+
bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx,
107+
const struct rxrpc_security **_sec,
108+
struct key **_key,
109+
struct sk_buff *skb)
107110
{
108111
const struct rxrpc_security *sec;
109-
struct rxrpc_local *local = conn->params.local;
110-
struct rxrpc_sock *rx;
111-
struct key *key;
112-
key_ref_t kref;
112+
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
113+
key_ref_t kref = NULL;
113114
char kdesc[5 + 1 + 3 + 1];
114115

115116
_enter("");
116117

117-
sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix);
118+
sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex);
118119

119-
sec = rxrpc_security_lookup(conn->security_ix);
120+
sec = rxrpc_security_lookup(sp->hdr.securityIndex);
120121
if (!sec) {
121-
_leave(" = -ENOKEY [lookup]");
122-
return -ENOKEY;
122+
trace_rxrpc_abort(0, "SVS",
123+
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
124+
RX_INVALID_OPERATION, EKEYREJECTED);
125+
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
126+
skb->priority = RX_INVALID_OPERATION;
127+
return false;
123128
}
124129

125-
/* find the service */
126-
read_lock(&local->services_lock);
127-
rx = rcu_dereference_protected(local->service,
128-
lockdep_is_held(&local->services_lock));
129-
if (rx && (rx->srx.srx_service == conn->service_id ||
130-
rx->second_service == conn->service_id))
131-
goto found_service;
130+
if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE)
131+
goto out;
132132

133-
/* the service appears to have died */
134-
read_unlock(&local->services_lock);
135-
_leave(" = -ENOENT");
136-
return -ENOENT;
137-
138-
found_service:
139133
if (!rx->securities) {
140-
read_unlock(&local->services_lock);
141-
_leave(" = -ENOKEY");
142-
return -ENOKEY;
134+
trace_rxrpc_abort(0, "SVR",
135+
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
136+
RX_INVALID_OPERATION, EKEYREJECTED);
137+
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
138+
skb->priority = RX_INVALID_OPERATION;
139+
return false;
143140
}
144141

145142
/* look through the service's keyring */
146143
kref = keyring_search(make_key_ref(rx->securities, 1UL),
147144
&key_type_rxrpc_s, kdesc, true);
148145
if (IS_ERR(kref)) {
149-
read_unlock(&local->services_lock);
150-
_leave(" = %ld [search]", PTR_ERR(kref));
151-
return PTR_ERR(kref);
146+
trace_rxrpc_abort(0, "SVK",
147+
sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
148+
sec->no_key_abort, EKEYREJECTED);
149+
skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
150+
skb->priority = sec->no_key_abort;
151+
return false;
152152
}
153153

154-
key = key_ref_to_ptr(kref);
155-
read_unlock(&local->services_lock);
156-
157-
conn->server_key = key;
158-
conn->security = sec;
159-
160-
_leave(" = 0");
161-
return 0;
154+
out:
155+
*_sec = sec;
156+
*_key = key_ref_to_ptr(kref);
157+
return true;
162158
}

0 commit comments

Comments
 (0)