Skip to content

Commit 058e422

Browse files
jk-ozlabsgregkh
authored andcommitted
net: mctp: mctp_fraq_queue should take ownership of passed skb
[ Upstream commit 773b27a ] 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 <jk@codeconstruct.com.au> Link: https://patch.msgid.link/20250829-mctp-skb-unshare-v1-1-1c28fe10235a@codeconstruct.com.au Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 34f17cb commit 058e422

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
@@ -325,6 +325,7 @@ static void mctp_skb_set_flow(struct sk_buff *skb, struct mctp_sk_key *key) {}
325325
static void mctp_flow_prepare_output(struct sk_buff *skb, struct mctp_dev *dev) {}
326326
#endif
327327

328+
/* takes ownership of skb, both in success and failure cases */
328329
static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
329330
{
330331
struct mctp_hdr *hdr = mctp_hdr(skb);
@@ -334,8 +335,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
334335
& MCTP_HDR_SEQ_MASK;
335336

336337
if (!key->reasm_head) {
337-
/* Since we're manipulating the shared frag_list, ensure it isn't
338-
* shared with any other SKBs.
338+
/* Since we're manipulating the shared frag_list, ensure it
339+
* isn't shared with any other SKBs. In the cloned case,
340+
* this will free the skb; callers can no longer access it
341+
* safely.
339342
*/
340343
key->reasm_head = skb_unshare(skb, GFP_ATOMIC);
341344
if (!key->reasm_head)
@@ -349,10 +352,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
349352
exp_seq = (key->last_seq + 1) & MCTP_HDR_SEQ_MASK;
350353

351354
if (this_seq != exp_seq)
352-
return -EINVAL;
355+
goto err_free;
353356

354357
if (key->reasm_head->len + skb->len > mctp_message_maxlen)
355-
return -EINVAL;
358+
goto err_free;
356359

357360
skb->next = NULL;
358361
skb->sk = NULL;
@@ -366,6 +369,10 @@ static int mctp_frag_queue(struct mctp_sk_key *key, struct sk_buff *skb)
366369
key->reasm_head->truesize += skb->truesize;
367370

368371
return 0;
372+
373+
err_free:
374+
kfree_skb(skb);
375+
return -EINVAL;
369376
}
370377

371378
static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
@@ -476,18 +483,16 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
476483
* key isn't observable yet
477484
*/
478485
mctp_frag_queue(key, skb);
486+
skb = NULL;
479487

480488
/* if the key_add fails, we've raced with another
481489
* SOM packet with the same src, dest and tag. There's
482490
* no way to distinguish future packets, so all we
483-
* can do is drop; we'll free the skb on exit from
484-
* this function.
491+
* can do is drop.
485492
*/
486493
rc = mctp_key_add(key, msk);
487-
if (!rc) {
494+
if (!rc)
488495
trace_mctp_key_acquire(key);
489-
skb = NULL;
490-
}
491496

492497
/* we don't need to release key->lock on exit, so
493498
* clean up here and suppress the unlock via
@@ -505,8 +510,7 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
505510
key = NULL;
506511
} else {
507512
rc = mctp_frag_queue(key, skb);
508-
if (!rc)
509-
skb = NULL;
513+
skb = NULL;
510514
}
511515
}
512516

@@ -516,17 +520,16 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
516520
*/
517521

518522
/* we need to be continuing an existing reassembly... */
519-
if (!key->reasm_head)
523+
if (!key->reasm_head) {
520524
rc = -EINVAL;
521-
else
525+
} else {
522526
rc = mctp_frag_queue(key, skb);
527+
skb = NULL;
528+
}
523529

524530
if (rc)
525531
goto out_unlock;
526532

527-
/* we've queued; the queue owns the skb now */
528-
skb = NULL;
529-
530533
/* end of message? deliver to socket, and we're done with
531534
* the reassembly/response key
532535
*/

0 commit comments

Comments
 (0)