Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'rxrpc-miscellaneous-fixes'

David Howells says:

====================
rxrpc: Miscellaneous fixes

Here are some fixes for rxrpc, as found by Sashiko[1]:

(1) Fix leaks in rxkad_verify_response().

(2) Fix handling of rxkad-encrypted packets with crypto-misaligned
lengths.

(3) Fix problem with unsharing DATA packets potentially causing a crash in
the caller.

(4) Fix lack of unsharing of RESPONSE packets.

(5) Fix integer overflow in RxGK ticket length check.

(6) Fix missing length check in RxKAD tickets.
====================

Link: https://patch.msgid.link/20260422161438.2593376-1-dhowells@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+106 -100
+3 -2
include/trace/events/rxrpc.h
··· 37 37 EM(rxkad_abort_1_short_encdata, "rxkad1-short-encdata") \ 38 38 EM(rxkad_abort_1_short_header, "rxkad1-short-hdr") \ 39 39 EM(rxkad_abort_2_short_check, "rxkad2-short-check") \ 40 + EM(rxkad_abort_2_crypto_unaligned, "rxkad2-crypto-unaligned") \ 40 41 EM(rxkad_abort_2_short_data, "rxkad2-short-data") \ 41 42 EM(rxkad_abort_2_short_header, "rxkad2-short-hdr") \ 42 43 EM(rxkad_abort_2_short_len, "rxkad2-short-len") \ ··· 162 161 E_(rxrpc_call_poke_timer_now, "Timer-now") 163 162 164 163 #define rxrpc_skb_traces \ 165 - EM(rxrpc_skb_eaten_by_unshare, "ETN unshare ") \ 166 - EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \ 167 164 EM(rxrpc_skb_get_call_rx, "GET call-rx ") \ 168 165 EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \ 169 166 EM(rxrpc_skb_get_conn_work, "GET conn-work") \ ··· 188 189 EM(rxrpc_skb_put_purge, "PUT purge ") \ 189 190 EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \ 190 191 EM(rxrpc_skb_put_response, "PUT response ") \ 192 + EM(rxrpc_skb_put_response_copy, "PUT resp-cpy ") \ 191 193 EM(rxrpc_skb_put_rotate, "PUT rotate ") \ 192 194 EM(rxrpc_skb_put_unknown, "PUT unknown ") \ 193 195 EM(rxrpc_skb_see_conn_work, "SEE conn-work") \ ··· 197 197 EM(rxrpc_skb_see_recvmsg_oob, "SEE recvm-oob") \ 198 198 EM(rxrpc_skb_see_reject, "SEE reject ") \ 199 199 EM(rxrpc_skb_see_rotate, "SEE rotate ") \ 200 + EM(rxrpc_skb_see_unshare_nomem, "SEE unshar-nm") \ 200 201 E_(rxrpc_skb_see_version, "SEE version ") 201 202 202 203 #define rxrpc_local_traces \
-1
net/rxrpc/ar-internal.h
··· 1486 1486 void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); 1487 1487 void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); 1488 1488 void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); 1489 - void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace); 1490 1489 void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); 1491 1490 void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); 1492 1491 void rxrpc_purge_queue(struct sk_buff_head *);
+18 -1
net/rxrpc/call_event.c
··· 332 332 333 333 saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK; 334 334 335 - rxrpc_input_call_packet(call, skb); 335 + if (sp->hdr.securityIndex != 0 && 336 + skb_cloned(skb)) { 337 + /* Unshare the packet so that it can be 338 + * modified by in-place decryption. 339 + */ 340 + struct sk_buff *nskb = skb_copy(skb, GFP_ATOMIC); 341 + 342 + if (nskb) { 343 + rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); 344 + rxrpc_input_call_packet(call, nskb); 345 + rxrpc_free_skb(nskb, rxrpc_skb_put_call_rx); 346 + } else { 347 + /* OOM - Drop the packet. */ 348 + rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); 349 + } 350 + } else { 351 + rxrpc_input_call_packet(call, skb); 352 + } 336 353 rxrpc_free_skb(skb, rxrpc_skb_put_call_rx); 337 354 did_receive = true; 338 355 }
+28 -1
net/rxrpc/conn_event.c
··· 240 240 rxrpc_notify_socket(call); 241 241 } 242 242 243 + static int rxrpc_verify_response(struct rxrpc_connection *conn, 244 + struct sk_buff *skb) 245 + { 246 + int ret; 247 + 248 + if (skb_cloned(skb)) { 249 + /* Copy the packet if shared so that we can do in-place 250 + * decryption. 251 + */ 252 + struct sk_buff *nskb = skb_copy(skb, GFP_NOFS); 253 + 254 + if (nskb) { 255 + rxrpc_new_skb(nskb, rxrpc_skb_new_unshared); 256 + ret = conn->security->verify_response(conn, nskb); 257 + rxrpc_free_skb(nskb, rxrpc_skb_put_response_copy); 258 + } else { 259 + /* OOM - Drop the packet. */ 260 + rxrpc_see_skb(skb, rxrpc_skb_see_unshare_nomem); 261 + ret = -ENOMEM; 262 + } 263 + } else { 264 + ret = conn->security->verify_response(conn, skb); 265 + } 266 + 267 + return ret; 268 + } 269 + 243 270 /* 244 271 * connection-level Rx packet processor 245 272 */ ··· 297 270 } 298 271 spin_unlock_irq(&conn->state_lock); 299 272 300 - ret = conn->security->verify_response(conn, skb); 273 + ret = rxrpc_verify_response(conn, skb); 301 274 if (ret < 0) 302 275 return ret; 303 276
+2 -22
net/rxrpc/io_thread.c
··· 192 192 /* 193 193 * Process packets received on the local endpoint 194 194 */ 195 - static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb) 195 + static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff *skb) 196 196 { 197 197 struct rxrpc_connection *conn; 198 198 struct sockaddr_rxrpc peer_srx; 199 199 struct rxrpc_skb_priv *sp; 200 200 struct rxrpc_peer *peer = NULL; 201 - struct sk_buff *skb = *_skb; 202 201 bool ret = false; 203 202 204 203 skb_pull(skb, sizeof(struct udphdr)); ··· 243 244 return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call); 244 245 if (sp->hdr.seq == 0) 245 246 return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq); 246 - 247 - /* Unshare the packet so that it can be modified for in-place 248 - * decryption. 249 - */ 250 - if (sp->hdr.securityIndex != 0) { 251 - skb = skb_unshare(skb, GFP_ATOMIC); 252 - if (!skb) { 253 - rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem); 254 - *_skb = NULL; 255 - return just_discard; 256 - } 257 - 258 - if (skb != *_skb) { 259 - rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare); 260 - *_skb = skb; 261 - rxrpc_new_skb(skb, rxrpc_skb_new_unshared); 262 - sp = rxrpc_skb(skb); 263 - } 264 - } 265 247 break; 266 248 267 249 case RXRPC_PACKET_TYPE_CHALLENGE: ··· 474 494 switch (skb->mark) { 475 495 case RXRPC_SKB_MARK_PACKET: 476 496 skb->priority = 0; 477 - if (!rxrpc_input_packet(local, &skb)) 497 + if (!rxrpc_input_packet(local, skb)) 478 498 rxrpc_reject_packet(local, skb); 479 499 trace_rxrpc_rx_done(skb->mark, skb->priority); 480 500 rxrpc_free_skb(skb, rxrpc_skb_put_input);
+4
net/rxrpc/key.c
··· 502 502 if (v1->security_index != RXRPC_SECURITY_RXKAD) 503 503 goto error; 504 504 505 + ret = -EKEYREJECTED; 506 + if (v1->ticket_length > AFSTOKEN_RK_TIX_MAX) 507 + goto error; 508 + 505 509 plen = sizeof(*token->kad) + v1->ticket_length; 506 510 prep->quotalen += plen + sizeof(*token); 507 511
+1 -1
net/rxrpc/rxgk_app.c
··· 214 214 ticket_len = ntohl(container.token_len); 215 215 ticket_offset = token_offset + sizeof(container); 216 216 217 - if (xdr_round_up(ticket_len) > token_len - sizeof(container)) 217 + if (ticket_len > xdr_round_down(token_len - sizeof(container))) 218 218 goto short_packet; 219 219 220 220 _debug("KVNO %u", kvno);
+1
net/rxrpc/rxgk_common.h
··· 34 34 }; 35 35 36 36 #define xdr_round_up(x) (round_up((x), sizeof(__be32))) 37 + #define xdr_round_down(x) (round_down((x), sizeof(__be32))) 37 38 #define xdr_object_len(x) (4 + xdr_round_up(x)) 38 39 39 40 /*
+49 -63
net/rxrpc/rxkad.c
··· 510 510 return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, 511 511 rxkad_abort_2_short_header); 512 512 513 + /* Don't let the crypto algo see a misaligned length. */ 514 + sp->len = round_down(sp->len, 8); 515 + 513 516 /* Decrypt the skbuff in-place. TODO: We really want to decrypt 514 517 * directly into the target buffer. 515 518 */ ··· 546 543 if (sg != _sg) 547 544 kfree(sg); 548 545 if (ret < 0) { 549 - WARN_ON_ONCE(ret != -ENOMEM); 550 - return ret; 546 + if (ret == -ENOMEM) 547 + return ret; 548 + return rxrpc_abort_eproto(call, skb, RXKADSEALEDINCON, 549 + rxkad_abort_2_crypto_unaligned); 551 550 } 552 551 553 552 /* Extract the decrypted packet length */ ··· 1141 1136 struct rxrpc_crypt session_key; 1142 1137 struct key *server_key; 1143 1138 time64_t expiry; 1144 - void *ticket; 1139 + void *ticket = NULL; 1145 1140 u32 version, kvno, ticket_len, level; 1146 1141 __be32 csum; 1147 1142 int ret, i; ··· 1167 1162 ret = -ENOMEM; 1168 1163 response = kzalloc_obj(struct rxkad_response, GFP_NOFS); 1169 1164 if (!response) 1170 - goto temporary_error; 1165 + goto error; 1171 1166 1172 1167 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header), 1173 1168 response, sizeof(*response)) < 0) { 1174 - rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, 1175 - rxkad_abort_resp_short); 1176 - goto protocol_error; 1169 + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, 1170 + rxkad_abort_resp_short); 1171 + goto error; 1177 1172 } 1178 1173 1179 1174 version = ntohl(response->version); ··· 1183 1178 trace_rxrpc_rx_response(conn, sp->hdr.serial, version, kvno, ticket_len); 1184 1179 1185 1180 if (version != RXKAD_VERSION) { 1186 - rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, 1187 - rxkad_abort_resp_version); 1188 - goto protocol_error; 1181 + ret = rxrpc_abort_conn(conn, skb, RXKADINCONSISTENCY, -EPROTO, 1182 + rxkad_abort_resp_version); 1183 + goto error; 1189 1184 } 1190 1185 1191 1186 if (ticket_len < 4 || ticket_len > MAXKRB5TICKETLEN) { 1192 - rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO, 1193 - rxkad_abort_resp_tkt_len); 1194 - goto protocol_error; 1187 + ret = rxrpc_abort_conn(conn, skb, RXKADTICKETLEN, -EPROTO, 1188 + rxkad_abort_resp_tkt_len); 1189 + goto error; 1195 1190 } 1196 1191 1197 1192 if (kvno >= RXKAD_TKT_TYPE_KERBEROS_V5) { 1198 - rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO, 1199 - rxkad_abort_resp_unknown_tkt); 1200 - goto protocol_error; 1193 + ret = rxrpc_abort_conn(conn, skb, RXKADUNKNOWNKEY, -EPROTO, 1194 + rxkad_abort_resp_unknown_tkt); 1195 + goto error; 1201 1196 } 1202 1197 1203 1198 /* extract the kerberos ticket and decrypt and decode it */ 1204 1199 ret = -ENOMEM; 1205 1200 ticket = kmalloc(ticket_len, GFP_NOFS); 1206 1201 if (!ticket) 1207 - goto temporary_error_free_resp; 1202 + goto error; 1208 1203 1209 1204 if (skb_copy_bits(skb, sizeof(struct rxrpc_wire_header) + sizeof(*response), 1210 1205 ticket, ticket_len) < 0) { 1211 - rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, 1212 - rxkad_abort_resp_short_tkt); 1213 - goto protocol_error; 1206 + ret = rxrpc_abort_conn(conn, skb, RXKADPACKETSHORT, -EPROTO, 1207 + rxkad_abort_resp_short_tkt); 1208 + goto error; 1214 1209 } 1215 1210 1216 1211 ret = rxkad_decrypt_ticket(conn, server_key, skb, ticket, ticket_len, 1217 1212 &session_key, &expiry); 1218 1213 if (ret < 0) 1219 - goto temporary_error_free_ticket; 1214 + goto error; 1220 1215 1221 1216 /* use the session key from inside the ticket to decrypt the 1222 1217 * response */ 1223 1218 ret = rxkad_decrypt_response(conn, response, &session_key); 1224 1219 if (ret < 0) 1225 - goto temporary_error_free_ticket; 1220 + goto error; 1226 1221 1227 1222 if (ntohl(response->encrypted.epoch) != conn->proto.epoch || 1228 1223 ntohl(response->encrypted.cid) != conn->proto.cid || 1229 1224 ntohl(response->encrypted.securityIndex) != conn->security_ix) { 1230 - rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1231 - rxkad_abort_resp_bad_param); 1232 - goto protocol_error_free; 1225 + ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1226 + rxkad_abort_resp_bad_param); 1227 + goto error; 1233 1228 } 1234 1229 1235 1230 csum = response->encrypted.checksum; 1236 1231 response->encrypted.checksum = 0; 1237 1232 rxkad_calc_response_checksum(response); 1238 1233 if (response->encrypted.checksum != csum) { 1239 - rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1240 - rxkad_abort_resp_bad_checksum); 1241 - goto protocol_error_free; 1234 + ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1235 + rxkad_abort_resp_bad_checksum); 1236 + goto error; 1242 1237 } 1243 1238 1244 1239 for (i = 0; i < RXRPC_MAXCALLS; i++) { ··· 1246 1241 u32 counter = READ_ONCE(conn->channels[i].call_counter); 1247 1242 1248 1243 if (call_id > INT_MAX) { 1249 - rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1250 - rxkad_abort_resp_bad_callid); 1251 - goto protocol_error_free; 1244 + ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1245 + rxkad_abort_resp_bad_callid); 1246 + goto error; 1252 1247 } 1253 1248 1254 1249 if (call_id < counter) { 1255 - rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1256 - rxkad_abort_resp_call_ctr); 1257 - goto protocol_error_free; 1250 + ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1251 + rxkad_abort_resp_call_ctr); 1252 + goto error; 1258 1253 } 1259 1254 1260 1255 if (call_id > counter) { 1261 1256 if (conn->channels[i].call) { 1262 - rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1257 + ret = rxrpc_abort_conn(conn, skb, RXKADSEALEDINCON, -EPROTO, 1263 1258 rxkad_abort_resp_call_state); 1264 - goto protocol_error_free; 1259 + goto error; 1265 1260 } 1266 1261 conn->channels[i].call_counter = call_id; 1267 1262 } 1268 1263 } 1269 1264 1270 1265 if (ntohl(response->encrypted.inc_nonce) != conn->rxkad.nonce + 1) { 1271 - rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO, 1272 - rxkad_abort_resp_ooseq); 1273 - goto protocol_error_free; 1266 + ret = rxrpc_abort_conn(conn, skb, RXKADOUTOFSEQUENCE, -EPROTO, 1267 + rxkad_abort_resp_ooseq); 1268 + goto error; 1274 1269 } 1275 1270 1276 1271 level = ntohl(response->encrypted.level); 1277 1272 if (level > RXRPC_SECURITY_ENCRYPT) { 1278 - rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO, 1279 - rxkad_abort_resp_level); 1280 - goto protocol_error_free; 1273 + ret = rxrpc_abort_conn(conn, skb, RXKADLEVELFAIL, -EPROTO, 1274 + rxkad_abort_resp_level); 1275 + goto error; 1281 1276 } 1282 1277 conn->security_level = level; 1283 1278 ··· 1285 1280 * this the connection security can be handled in exactly the same way 1286 1281 * as for a client connection */ 1287 1282 ret = rxrpc_get_server_data_key(conn, &session_key, expiry, kvno); 1288 - if (ret < 0) 1289 - goto temporary_error_free_ticket; 1290 1283 1284 + error: 1291 1285 kfree(ticket); 1292 - kfree(response); 1293 - _leave(" = 0"); 1294 - return 0; 1295 - 1296 - protocol_error_free: 1297 - kfree(ticket); 1298 - protocol_error: 1299 1286 kfree(response); 1300 1287 key_put(server_key); 1301 - return -EPROTO; 1302 - 1303 - temporary_error_free_ticket: 1304 - kfree(ticket); 1305 - temporary_error_free_resp: 1306 - kfree(response); 1307 - temporary_error: 1308 - /* Ignore the response packet if we got a temporary error such as 1309 - * ENOMEM. We just want to send the challenge again. Note that we 1310 - * also come out this way if the ticket decryption fails. 1311 - */ 1312 - key_put(server_key); 1288 + _leave(" = %d", ret); 1313 1289 return ret; 1314 1290 } 1315 1291
-9
net/rxrpc/skbuff.c
··· 47 47 } 48 48 49 49 /* 50 - * Note the dropping of a ref on a socket buffer by the core. 51 - */ 52 - void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace why) 53 - { 54 - int n = atomic_inc_return(&rxrpc_n_rx_skbs); 55 - trace_rxrpc_skb(skb, 0, n, why); 56 - } 57 - 58 - /* 59 50 * Note the destruction of a socket buffer. 60 51 */ 61 52 void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace why)