Skip to content

Commit 34f61a0

Browse files
dhowellskuba-moo
authored andcommitted
rxrpc: Fix memory leaks in rxkad_verify_response()
Fix rxkad_verify_response() to free the ticket and the server key under all circumstances by initialising the ticket pointer to NULL and then making all paths through the function after the first allocation has been done go through a single common epilogue that just releases everything - where all the releases skip on a NULL pointer. Fixes: 57af281 ("rxrpc: Tidy up abort generation infrastructure") Fixes: ec832bd ("rxrpc: Don't retain the server key in the connection") Closes: https://sashiko.dev/#/patchset/20260408121252.2249051-1-dhowells%40redhat.com Signed-off-by: David Howells <[email protected]> cc: Marc Dionne <[email protected]> cc: Jeffrey Altman <[email protected]> cc: Simon Horman <[email protected]> cc: [email protected] cc: [email protected] Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 8141a2d commit 34f61a0

1 file changed

Lines changed: 42 additions & 61 deletions

File tree

net/rxrpc/rxkad.c

Lines changed: 42 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1136,7 +1136,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
11361136
struct rxrpc_crypt session_key;
11371137
struct key *server_key;
11381138
time64_t expiry;
1139-
void *ticket;
1139+
void *ticket = NULL;
11401140
u32 version, kvno, ticket_len, level;
11411141
__be32 csum;
11421142
int ret, i;
@@ -1162,13 +1162,13 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
11621162
ret = -ENOMEM;
11631163
response = kzalloc_obj(struct rxkad_response, GFP_NOFS);
11641164
if (!response)
1165-
goto temporary_error;
1165+
goto error;
11661166

11671167
if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header),
11681168
response, sizeof(*response)) < 0) {
1169-
rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
1170-
rxkad_abort_resp_short);
1171-
goto protocol_error;
1169+
ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
1170+
rxkad_abort_resp_short);
1171+
goto error;
11721172
}
11731173

11741174
version = ntohl(response->version);
@@ -1178,133 +1178,114 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
11781178
trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len);
11791179

11801180
if (version != RXKAD_VERSION) {
1181-
rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO,
1182-
rxkad_abort_resp_version);
1183-
goto protocol_error;
1181+
ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO,
1182+
rxkad_abort_resp_version);
1183+
goto error;
11841184
}
11851185

11861186
if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN) {
1187-
rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO,
1188-
rxkad_abort_resp_tkt_len);
1189-
goto protocol_error;
1187+
ret = rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO,
1188+
rxkad_abort_resp_tkt_len);
1189+
goto error;
11901190
}
11911191

11921192
if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5) {
1193-
rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO,
1194-
rxkad_abort_resp_unknown_tkt);
1195-
goto protocol_error;
1193+
ret = rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO,
1194+
rxkad_abort_resp_unknown_tkt);
1195+
goto error;
11961196
}
11971197

11981198
/* extract the kerberos ticket and decrypt and decode it */
11991199
ret = -ENOMEM;
12001200
ticket = kmalloc(ticket_len, GFP_NOFS);
12011201
if (!ticket)
1202-
goto temporary_error_free_resp;
1202+
goto error;
12031203

12041204
if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response),
12051205
ticket, ticket_len) < 0) {
1206-
rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
1207-
rxkad_abort_resp_short_tkt);
1208-
goto protocol_error;
1206+
ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO,
1207+
rxkad_abort_resp_short_tkt);
1208+
goto error;
12091209
}
12101210

12111211
ret = rxkad_decrypt_ticket(conn, server_key, skb, ticket, ticket_len,
12121212
&session_key, &expiry);
12131213
if (ret < 0)
1214-
goto temporary_error_free_ticket;
1214+
goto error;
12151215

12161216
/* use the session key from inside the ticket to decrypt the
12171217
* response */
12181218
ret = rxkad_decrypt_response(conn, response, &session_key);
12191219
if (ret < 0)
1220-
goto temporary_error_free_ticket;
1220+
goto error;
12211221

12221222
if (ntohl(response->encrypted.epoch) != conn->proto.epoch ||
12231223
ntohl(response->encrypted.cid) != conn->proto.cid ||
12241224
ntohl(response->encrypted.securityIndex) != conn->security_ix) {
1225-
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1226-
rxkad_abort_resp_bad_param);
1227-
goto protocol_error_free;
1225+
ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1226+
rxkad_abort_resp_bad_param);
1227+
goto error;
12281228
}
12291229

12301230
csum = response->encrypted.checksum;
12311231
response->encrypted.checksum = 0;
12321232
rxkad_calc_response_checksum(response);
12331233
if (response->encrypted.checksum != csum) {
1234-
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1235-
rxkad_abort_resp_bad_checksum);
1236-
goto protocol_error_free;
1234+
ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1235+
rxkad_abort_resp_bad_checksum);
1236+
goto error;
12371237
}
12381238

12391239
for (i = 0; i < RXRPC_MAXCALLS; i++) {
12401240
u32 call_id = ntohl(response->encrypted.call_id[i]);
12411241
u32 counter = READ_ONCE(conn->channels[i].call_counter);
12421242

12431243
if (call_id > INT_MAX) {
1244-
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1245-
rxkad_abort_resp_bad_callid);
1246-
goto protocol_error_free;
1244+
ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1245+
rxkad_abort_resp_bad_callid);
1246+
goto error;
12471247
}
12481248

12491249
if (call_id < counter) {
1250-
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1251-
rxkad_abort_resp_call_ctr);
1252-
goto protocol_error_free;
1250+
ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1251+
rxkad_abort_resp_call_ctr);
1252+
goto error;
12531253
}
12541254

12551255
if (call_id > counter) {
12561256
if (conn->channels[i].call) {
1257-
rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
1257+
ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO,
12581258
rxkad_abort_resp_call_state);
1259-
goto protocol_error_free;
1259+
goto error;
12601260
}
12611261
conn->channels[i].call_counter = call_id;
12621262
}
12631263
}
12641264

12651265
if (ntohl(response->encrypted.inc_nonce) != conn->rxkad.nonce + 1) {
1266-
rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO,
1267-
rxkad_abort_resp_ooseq);
1268-
goto protocol_error_free;
1266+
ret = rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO,
1267+
rxkad_abort_resp_ooseq);
1268+
goto error;
12691269
}
12701270

12711271
level = ntohl(response->encrypted.level);
12721272
if (level > RXRPC_SECURITY_ENCRYPT) {
1273-
rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO,
1274-
rxkad_abort_resp_level);
1275-
goto protocol_error_free;
1273+
ret = rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO,
1274+
rxkad_abort_resp_level);
1275+
goto error;
12761276
}
12771277
conn->security_level = level;
12781278

12791279
/* create a key to hold the security data and expiration time - after
12801280
* this the connection security can be handled in exactly the same way
12811281
* as for a client connection */
12821282
ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno);
1283-
if (ret < 0)
1284-
goto temporary_error_free_ticket;
1285-
1286-
kfree(ticket);
1287-
kfree(response);
1288-
_leave(" = 0");
1289-
return 0;
12901283

1291-
protocol_error_free:
1292-
kfree(ticket);
1293-
protocol_error:
1294-
kfree(response);
1295-
key_put(server_key);
1296-
return -EPROTO;
1297-
1298-
temporary_error_free_ticket:
1284+
error:
12991285
kfree(ticket);
1300-
temporary_error_free_resp:
13011286
kfree(response);
1302-
temporary_error:
1303-
/* Ignore the response packet if we got a temporary error such as
1304-
* ENOMEM. We just want to send the challenge again. Note that we
1305-
* also come out this way if the ticket decryption fails.
1306-
*/
13071287
key_put(server_key);
1288+
_leave(" = %d", ret);
13081289
return ret;
13091290
}
13101291

0 commit comments

Comments
 (0)