CVE-2026-46320
Description
In the Linux kernel, the following vulnerability has been resolved:
tap: free page on error paths in tap_get_user_xdp()
tap_get_user_xdp() rejects a frame shorter than ETH_HLEN with -EINVAL, and returns -ENOMEM when build_skb() fails. Both paths jump to the err label without freeing the page that vhost_net_build_xdp() allocated for the frame. tap_sendmsg() discards the per-buffer return value and always returns 0, so vhost_tx_batch() takes the success path and never frees the page; each rejected frame in a batch leaks one page-frag chunk.
Free the page on both error paths, before the skb is built. This is the tap counterpart of the same leak in tun_xdp_one().
Affected products
1Patches
418a84c35842etap: free page on error paths in tap_get_user_xdp()
1 file changed · +2 −1
drivers/net/tap.c+2 −1 modifieddiff --git a/drivers/net/tap.c b/drivers/net/tap.c index a590e07ce0a98..fae115915c8ef 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1052,6 +1052,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) int err, depth; if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) { + put_page(virt_to_head_page(xdp->data)); err = -EINVAL; goto err; } @@ -1061,6 +1062,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) skb = build_skb(xdp->data_hard_start, buflen); if (!skb) { + put_page(virt_to_head_page(xdp->data)); err = -ENOMEM; goto err; } -- cgit 1.3-korg
3bcf7aec6a9dtap: free page on error paths in tap_get_user_xdp()
1 file changed · +2 −1
drivers/net/tap.c+2 −1 modifieddiff --git a/drivers/net/tap.c b/drivers/net/tap.c index a590e07ce0a98..fae115915c8ef 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1052,6 +1052,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) int err, depth; if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) { + put_page(virt_to_head_page(xdp->data)); err = -EINVAL; goto err; } @@ -1061,6 +1062,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) skb = build_skb(xdp->data_hard_start, buflen); if (!skb) { + put_page(virt_to_head_page(xdp->data)); err = -ENOMEM; goto err; } -- cgit 1.3-korg
18a84c35842etap: free page on error paths in tap_get_user_xdp()
1 file changed · +2 −1
drivers/net/tap.c+2 −1 modifieddiff --git a/drivers/net/tap.c b/drivers/net/tap.c index a590e07ce0a98..fae115915c8ef 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1052,6 +1052,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) int err, depth; if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) { + put_page(virt_to_head_page(xdp->data)); err = -EINVAL; goto err; } @@ -1061,6 +1062,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) skb = build_skb(xdp->data_hard_start, buflen); if (!skb) { + put_page(virt_to_head_page(xdp->data)); err = -ENOMEM; goto err; } -- cgit 1.3-korg
3bcf7aec6a9dtap: free page on error paths in tap_get_user_xdp()
1 file changed · +2 −1
drivers/net/tap.c+2 −1 modifieddiff --git a/drivers/net/tap.c b/drivers/net/tap.c index a590e07ce0a98..fae115915c8ef 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -1052,6 +1052,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) int err, depth; if (unlikely(xdp->data_end - xdp->data < ETH_HLEN)) { + put_page(virt_to_head_page(xdp->data)); err = -EINVAL; goto err; } @@ -1061,6 +1062,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp) skb = build_skb(xdp->data_hard_start, buflen); if (!skb) { + put_page(virt_to_head_page(xdp->data)); err = -ENOMEM; goto err; } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Error paths in tap_get_user_xdp() fail to free allocated pages, leading to memory leaks."
Attack vector
An attacker can trigger this vulnerability by sending frames shorter than ETH_HLEN or by causing build_skb() to fail within the tap_get_user_xdp() function. When these error conditions occur, the allocated page is not freed. If this happens repeatedly within a batch operation handled by tap_sendmsg() and vhost_tx_batch(), it results in a memory leak, consuming page-frag chunks.
Affected code
The vulnerability exists in the `tap_get_user_xdp()` function within the `drivers/net/tap.c` file. Specifically, the error paths leading to `-EINVAL` (frame too short) and `-ENOMEM` (build_skb() failure) did not include logic to free the allocated page.
What the fix does
The patch adds calls to `put_page(virt_to_head_page(xdp->data))` on both error paths within the tap_get_user_xdp() function [patch_id=5354535]. This ensures that the page allocated by vhost_net_build_xdp() is freed when a frame is shorter than ETH_HLEN or when build_skb() fails. By freeing the page before the skb is built, the memory leak is prevented.
Preconditions
- inputFrames shorter than ETH_HLEN or conditions causing build_skb() to fail.
Generated on Jun 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
1- Linux Kernel: 25 Vulnerabilities Disclosed in Single Batch on June 8-9, 2026Vypr Intelligence · Jun 9, 2026