aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjoern A. Zeeb <bz@FreeBSD.org>2026-02-03 22:13:24 +0000
committerBjoern A. Zeeb <bz@FreeBSD.org>2026-07-17 15:48:54 +0000
commitcb13e826ec45e11e964e1921d281e0a06ca5e152 (patch)
treedadaceed67cfa6395b02146105fa393bd5dee355
parent1e4ec01603c4b1e0b0eb524f28f731eb5cb5f6dc (diff)
-rw-r--r--sys/compat/linuxkpi/common/src/linux_skbuff.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/compat/linuxkpi/common/src/linux_skbuff.c b/sys/compat/linuxkpi/common/src/linux_skbuff.c
index 5af9633691a6..d57c277c3267 100644
--- a/sys/compat/linuxkpi/common/src/linux_skbuff.c
+++ b/sys/compat/linuxkpi/common/src/linux_skbuff.c
@@ -140,6 +140,7 @@ linuxkpi_alloc_skb(size_t size, gfp_t gfp)
skb->head = skb->data = (uint8_t *)p;
skb_reset_tail_pointer(skb);
skb->end = skb->head + size;
+ refcount_set(&skb->refcnt, 1);
SKB_TRACE_FMT(skb, "data %p size %zu", (skb) ? skb->data : NULL, size);
return (skb);
@@ -180,6 +181,7 @@ linuxkpi_build_skb(void *data, size_t fragsz)
skb->head = skb->data = data;
skb_reset_tail_pointer(skb);
skb->end = skb->head + fragsz;
+ refcount_set(&skb->refcnt, 1);
return (skb);
}
@@ -288,6 +290,20 @@ lkpi___skb_linearize(struct sk_buff *skb)
return (0);
}
+static bool
+lkpi_skb_refcount_release(struct sk_buff *skb)
+{
+ if (skb == NULL)
+ return (false);
+
+ /* Do we need further tests to avoid freeing this one? */
+
+ if (!refcount_dec_and_test(&skb->refcnt))
+ return (false);
+
+ return (true);
+}
+
void
linuxkpi_kfree_skb(struct sk_buff *skb)
{
@@ -298,6 +314,11 @@ linuxkpi_kfree_skb(struct sk_buff *skb)
if (skb == NULL)
return;
+ if (!lkpi_skb_refcount_release(skb)) {
+ SKB_TRACE_FMT(skb, "not freed due to refcnt");
+ return;
+ }
+
/*
* XXX TODO this will go away once we have skb backed by mbuf.
* currently we allow the mbuf to stay around and use a private