Skip to content

Commit 3f4c391

Browse files
woziwrtklassert
authored andcommitted
xfrm: fix stale skb->prev after async crypto steals a GSO segment
skb_gso_segment() leaves the segment list head with ->prev pointing at the last segment, an invariant validate_xmit_skb_list() relies on when it sets its tail pointer (tail = skb->prev). When validate_xmit_xfrm() walks a GSO list and some segments are stolen by async crypto (->xmit() returns -EINPROGRESS), those segments are unlinked from the list but the head ->prev is never updated. If the last segment is the one stolen, the returned head still has ->prev pointing at it, even though it is now owned by the crypto engine and may be freed. validate_xmit_skb_list() later does tail->next = skb, writing through that stale pointer -- a use-after-free. Repoint skb->prev at the last retained segment before returning. Fixes: f53c723 ("net: Add asynchronous callbacks for xfrm on layer 2.") Signed-off-by: Petr Wozniak <petr.wozniak@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
1 parent 6860b46 commit 3f4c391

1 file changed

Lines changed: 8 additions & 0 deletions

File tree

net/xfrm/xfrm_device.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
224224
pskb = skb2;
225225
}
226226

227+
/* skb_gso_segment() set skb->prev to the last segment, but async
228+
* crypto may have stolen it above without updating ->prev. Repoint
229+
* it at the last retained segment so validate_xmit_skb_list() does
230+
* not chain onto a segment now owned by the crypto engine.
231+
*/
232+
if (skb)
233+
skb->prev = pskb;
234+
227235
return skb ? skb : ERR_PTR(-EINPROGRESS);
228236
}
229237
EXPORT_SYMBOL_GPL(validate_xmit_xfrm);

0 commit comments

Comments
 (0)