Skip to content

Commit 773b27a

Browse files
jk-ozlabsPaolo Abeni
authored andcommitted
net: mctp: mctp_fraq_queue should take ownership of passed skb
As of commit f5d83cf ("net: mctp: unshare packets when reassembling"), we skb_unshare() in mctp_frag_queue(). The unshare may invalidate the original skb pointer, so we need to treat the skb as entirely owned by the fraq queue, even on failure. Fixes: f5d83cf ("net: mctp: unshare packets when reassembling") Signed-off-by: Jeremy Kerr <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent ba1e942 commit 773b27a

File tree

1 file changed

+19
-16
lines changed

1 file changed

+19
-16
lines changed

net/mctp/route.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {}
378378
static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {}
379379
#endif
380380

381+
/* takes ownership of skb, both in success and failure cases */
381382
static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
382383
{
383384
struct mctp_hdr *hdr = mctp_hdr(skb);
@@ -387,8 +388,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
387388
& MCTP_HDR_SEQ_MASK;
388389

389390
if (!key->reasm_head) {
390-
/* Since we're manipulating the shared frag_list, ensure it isn't
391-
* shared with any other SKBs.
391+
/* Since we're manipulating the shared frag_list, ensure it
392+
* isn't shared with any other SKBs. In the cloned case,
393+
* this will free the skb; callers can no longer access it
394+
* safely.
392395
*/
393396
key->reasm_head = skb_unshare(skb, GFP_ATOMIC);
394397
if (!key->reasm_head)
@@ -402,10 +405,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
402405
exp_seq = (key->last_seq + 1) & MCTP_HDR_SEQ_MASK;
403406

404407
if (this_seq != exp_seq)
405-
return -EINVAL;
408+
goto err_free;
406409

407410
if (key->reasm_head->len + skb->len > mctp_message_maxlen)
408-
return -EINVAL;
411+
goto err_free;
409412

410413
skb->next = NULL;
411414
skb->sk = NULL;
@@ -419,6 +422,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
419422
key->reasm_head->truesize += skb->truesize;
420423

421424
return 0;
425+
426+
err_free:
427+
kfree_skb(skb);
428+
return -EINVAL;
422429
}
423430

424431
static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
@@ -532,18 +539,16 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
532539
* key isn't observable yet
533540
*/
534541
mctp_frag_queue(key, skb);
542+
skb = NULL;
535543

536544
/* if the key_add fails, we've raced with another
537545
* SOM packet with the same src, dest and tag. There's
538546
* no way to distinguish future packets, so all we
539-
* can do is drop; we'll free the skb on exit from
540-
* this function.
547+
* can do is drop.
541548
*/
542549
rc = mctp_key_add(key, msk);
543-
if (!rc) {
550+
if (!rc)
544551
trace_mctp_key_acquire(key);
545-
skb = NULL;
546-
}
547552

548553
/* we don't need to release key->lock on exit, so
549554
* clean up here and suppress the unlock via
@@ -561,8 +566,7 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
561566
key = NULL;
562567
} else {
563568
rc = mctp_frag_queue(key, skb);
564-
if (!rc)
565-
skb = NULL;
569+
skb = NULL;
566570
}
567571
}
568572

@@ -572,17 +576,16 @@ static int mctp_dst_input(struct mctp_dst *dst, struct sk_buff *skb)
572576
*/
573577

574578
/* we need to be continuing an existing reassembly... */
575-
if (!key->reasm_head)
579+
if (!key->reasm_head) {
576580
rc = -EINVAL;
577-
else
581+
} else {
578582
rc = mctp_frag_queue(key, skb);
583+
skb = NULL;
584+
}
579585

580586
if (rc)
581587
goto out_unlock;
582588

583-
/* we've queued; the queue owns the skb now */
584-
skb = NULL;
585-
586589
/* end of message? deliver to socket, and we're done with
587590
* the reassembly/response key
588591
*/

0 commit comments

Comments
 (0)