When skb_orphan_frags() throws -ENOMEM, skb_copy_ubufs() may have
already reallocated and replaced 'from->head'. Accessing from->head to
drop the old refcount leaks the original head page, and erroneously
puts an unrelated new buffer. Use the local 'page' tracker variable
instead to drop the reference properly.
Fixes: 36d5fe6a0007 ("core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors")
Signed-off-by: Mina Almasry <redacted>
---
Note to sashiko: if you find pre-existing issues, mark them clearly as pre-existing.
---
net/core/skbuff.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 201c9ec1519c7..92aad6f0b0e14 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3907,7 +3907,7 @@ skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
}
if (!skb_frags_readable(from) && j > 0 && len) {
- put_page(virt_to_head_page(from->head));
+ put_page(page);
return -EFAULT;
}
@@ -3916,7 +3916,7 @@ skb_zerocopy(struct sk_buff *to, struct sk_buff *from, int len, int hlen)
if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
skb_tx_error(from);
if (j > 0)
- put_page(virt_to_head_page(from->head));
+ put_page(page);
return -ENOMEM;
}
skb_zerocopy_clone(to, from, GFP_ATOMIC);--
2.55.0.766.g2966f0265a-goog