Thread (47 messages) flat view 47 messages, 6 authors, 1d ago

Re: [PATCH 01/12] xfrm: iptfs: fix stack OOB read in iptfs_skb_reset_frag_walk()

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: 2026-09-16 09:02:43

On Tue, Sep 15, 2026 at 08:31:54AM -0000, Roshan Kumar wrote:
quoted hunk ↗ jump to hunk
Hi Steffen,

I had a look at the review and it is right that the guard changes the
len == 0 outcome, with one nuance worth splitting out.

The sharing branch needs a prepared frag walk, so the guard can only
change behavior for skbs that are frag walk eligible (head_frag set, or
all data in frags). For those, before the change
iptfs_skb_can_add_frags() fell through the "while (len && fragi <
walk->nr_frags)" loop and returned true, iptfs_skb_add_frags()
returned immediately on its own " !walk->nr_frags || offset out of
range" check, and reassembly continued with ra_wantseq++. With the
guard the same input returns false, takes the copy branch, and
skb_copy_seq_read(..., 0) returns EINVAL, so the in progress
reassembly is dropped.

For linear skbs the frag walk stays NULL and this corner dropped
reassembly before the change too: the copy branch runs either way and
skb_seq_read at the end of the buffer fails the same way. I reproduced
that part live on v7.3-rc3 today: a partial inner packet followed by
an AGGFRAG basic header only block with block_offset 0xffff kills the
in progress reassembly with and without the fix, so that part already
existed rather than being something the guard introduces.

The review's suggestion closes the gap for the frag walk case: return
true when len == 0, before the offset check. The dangerous walk in
iptfs_skb_reset_frag_walk() is skipped entirely for len == 0, and
iptfs_skb_add_frags() keeps its own bounds check for len > 0, so the
out of bounds read cannot come back this way. The reassembly outcome
stays identical to before the fix for head frag skbs, so there is no
efficiency cost either.

Something like this on top of the patch:
diff --git a/net/xfrm/xfrm_iptfs.c b/net/xfrm/xfrm_iptfs.c
--- a/net/xfrm/xfrm_iptfs.c
+++ b/net/xfrm/xfrm_iptfs.c
@@ static bool iptfs_skb_can_add_frags(const struct sk_buff *skb,
        if (skb_has_frag_list(skb) || skb->pp_recycle != walk->pp_recycle)
                return false;

+       /* len == 0: nothing to add, proceed as before the fix. */
+       if (!len)
+               return true;
That's ok with me. But drop the comment above, this does not
give any usefull information.
+
        /* Reject an @offset that is at or beyond the end of the walk's data
         * before calling iptfs_skb_reset_frag_walk(), whose fragment-advance
         * loop is otherwise unbounded and would index past walk->frags[].
         * This mirrors the guard already present in iptfs_skb_add_frags().
         */
        if (!walk->nr_frags || offset >= walk->total + walk->initial_offset)
                return false;

The len == 0 drop for linear skbs existed before this change; I am
happy to look at that separately once this series lands.
Thanks!
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help