Skip to content

Commit 27ae4bc

Browse files
committed
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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 8141a2d + ac33733 commit 27ae4bc

10 files changed

Lines changed: 106 additions & 100 deletions

File tree

include/trace/events/rxrpc.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
EM(rxkad_abort_1_short_encdata, "rxkad1-short-encdata") \
3838
EM(rxkad_abort_1_short_header, "rxkad1-short-hdr") \
3939
EM(rxkad_abort_2_short_check, "rxkad2-short-check") \
40+
EM(rxkad_abort_2_crypto_unaligned, "rxkad2-crypto-unaligned") \
4041
EM(rxkad_abort_2_short_data, "rxkad2-short-data") \
4142
EM(rxkad_abort_2_short_header, "rxkad2-short-hdr") \
4243
EM(rxkad_abort_2_short_len, "rxkad2-short-len") \
@@ -161,8 +162,6 @@
161162
E_(rxrpc_call_poke_timer_now, "Timer-now")
162163

163164
#define rxrpc_skb_traces \
164-
EM(rxrpc_skb_eaten_by_unshare, "ETN unshare ") \
165-
EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \
166165
EM(rxrpc_skb_get_call_rx, "GET call-rx ") \
167166
EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \
168167
EM(rxrpc_skb_get_conn_work, "GET conn-work") \
@@ -189,6 +188,7 @@
189188
EM(rxrpc_skb_put_purge, "PUT purge ") \
190189
EM(rxrpc_skb_put_purge_oob, "PUT purge-oob") \
191190
EM(rxrpc_skb_put_response, "PUT response ") \
191+
EM(rxrpc_skb_put_response_copy, "PUT resp-cpy ") \
192192
EM(rxrpc_skb_put_rotate, "PUT rotate ") \
193193
EM(rxrpc_skb_put_unknown, "PUT unknown ") \
194194
EM(rxrpc_skb_see_conn_work, "SEE conn-work") \
@@ -197,6 +197,7 @@
197197
EM(rxrpc_skb_see_recvmsg_oob, "SEE recvm-oob") \
198198
EM(rxrpc_skb_see_reject, "SEE reject ") \
199199
EM(rxrpc_skb_see_rotate, "SEE rotate ") \
200+
EM(rxrpc_skb_see_unshare_nomem, "SEE unshar-nm") \
200201
E_(rxrpc_skb_see_version, "SEE version ")
201202

202203
#define rxrpc_local_traces \

net/rxrpc/ar-internal.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1486,7 +1486,6 @@ int rxrpc_server_keyring(struct rxrpc_sock *, sockptr_t, int);
14861486
void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *);
14871487
void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
14881488
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
1489-
void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace);
14901489
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
14911490
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
14921491
void rxrpc_purge_queue(struct sk_buff_head *);

net/rxrpc/call_event.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,24 @@ bool rxrpc_input_call_event(struct rxrpc_call *call)
332332

333333
saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK;
334334

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+
}
336353
rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
337354
did_receive = true;
338355
}

net/rxrpc/conn_event.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,33 @@ static void rxrpc_call_is_secure(struct rxrpc_call *call)
240240
rxrpc_notify_socket(call);
241241
}
242242

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+
243270
/*
244271
* connection-level Rx packet processor
245272
*/
@@ -270,7 +297,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
270297
}
271298
spin_unlock_irq(&conn->state_lock);
272299

273-
ret = conn->security->verify_response(conn, skb);
300+
ret = rxrpc_verify_response(conn, skb);
274301
if (ret < 0)
275302
return ret;
276303

net/rxrpc/io_thread.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,13 +192,12 @@ static bool rxrpc_extract_abort(struct sk_buff *skb)
192192
/*
193193
* Process packets received on the local endpoint
194194
*/
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)
196196
{
197197
struct rxrpc_connection *conn;
198198
struct sockaddr_rxrpc peer_srx;
199199
struct rxrpc_skb_priv *sp;
200200
struct rxrpc_peer *peer = NULL;
201-
struct sk_buff *skb = *_skb;
202201
bool ret = false;
203202

204203
skb_pull(skb, sizeof(struct udphdr));
@@ -244,25 +243,6 @@ static bool rxrpc_input_packet(struct rxrpc_local *local, struct sk_buff **_skb)
244243
return rxrpc_bad_message(skb, rxrpc_badmsg_zero_call);
245244
if (sp->hdr.seq == 0)
246245
return rxrpc_bad_message(skb, rxrpc_badmsg_zero_seq);
247-
248-
/* Unshare the packet so that it can be modified for in-place
249-
* decryption.
250-
*/
251-
if (sp->hdr.securityIndex != 0) {
252-
skb = skb_unshare(skb, GFP_ATOMIC);
253-
if (!skb) {
254-
rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare_nomem);
255-
*_skb = NULL;
256-
return just_discard;
257-
}
258-
259-
if (skb != *_skb) {
260-
rxrpc_eaten_skb(*_skb, rxrpc_skb_eaten_by_unshare);
261-
*_skb = skb;
262-
rxrpc_new_skb(skb, rxrpc_skb_new_unshared);
263-
sp = rxrpc_skb(skb);
264-
}
265-
}
266246
break;
267247

268248
case RXRPC_PACKET_TYPE_CHALLENGE:
@@ -494,7 +474,7 @@ int rxrpc_io_thread(void *data)
494474
switch (skb->mark) {
495475
case RXRPC_SKB_MARK_PACKET:
496476
skb->priority = 0;
497-
if (!rxrpc_input_packet(local, &skb))
477+
if (!rxrpc_input_packet(local, skb))
498478
rxrpc_reject_packet(local, skb);
499479
trace_rxrpc_rx_done(skb->mark, skb->priority);
500480
rxrpc_free_skb(skb, rxrpc_skb_put_input);

net/rxrpc/key.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,10 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
502502
if (v1->security_index != RXRPC_SECURITY_RXKAD)
503503
goto error;
504504

505+
ret = -EKEYREJECTED;
506+
if (v1->ticket_length > AFSTOKEN_RK_TIX_MAX)
507+
goto error;
508+
505509
plen = sizeof(*token->kad) + v1->ticket_length;
506510
prep->quotalen += plen + sizeof(*token);
507511

net/rxrpc/rxgk_app.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ int rxgk_extract_token(struct rxrpc_connection *conn, struct sk_buff *skb,
214214
ticket_len = ntohl(container.token_len);
215215
ticket_offset = token_offset + sizeof(container);
216216

217-
if (xdr_round_up(ticket_len) > token_len - sizeof(container))
217+
if (ticket_len > xdr_round_down(token_len - sizeof(container)))
218218
goto short_packet;
219219

220220
_debug("KVNO %u", kvno);

net/rxrpc/rxgk_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ struct rxgk_context {
3434
};
3535

3636
#define xdr_round_up(x) (round_up((x), sizeof(__be32)))
37+
#define xdr_round_down(x) (round_down((x), sizeof(__be32)))
3738
#define xdr_object_len(x) (4 + xdr_round_up(x))
3839

3940
/*

0 commit comments

Comments
 (0)