CVE-2026-46167
Description
In the Linux kernel, the following vulnerability has been resolved:
usb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
Just like in a previous problem in this driver, usblp_ctrl_msg() will collapse the usb_control_msg() return value to 0/-errno, discarding the actual number of bytes transferred.
Ideally that short command should be detected and error out, but many printers are known to send "incorrect" responses back so we can't just do that.
statusbuf is kmalloc(8) at probe time and never filled before the first LPGETSTATUS ioctl.
usblp_read_status() requests 1 byte. If a malicious printer responds with zero bytes, *statusbuf is one byte of stale kmalloc heap, sign-extended into the local int status, which the LPGETSTATUS path then copy_to_user()s directly to the ioctl caller.
Fix this all by just zapping out the memory buffer when allocated at probe time. If a later call does a short read, the data will be identical to what the device sent it the last time, so there is no "leak" of information happening.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
LPGETSTATUS ioctl in Linux kernel usblp driver leaks uninitialized heap data due to improper handling of short USB control transfers.
Vulnerability
The LPGETSTATUS ioctl in the Linux kernel's usblp driver (usb: usblp) leaks uninitialized heap data. The function usblp_read_status() calls usblp_ctrl_msg(), which collapses the usb_control_msg() return value to 0/-errno, discarding the actual number of bytes transferred. If a malicious printer responds with zero bytes, the status buffer (statusbuf) remains uninitialized. The buffer is allocated with kmalloc(8) at probe time and is never zeroed. This issue affects Linux kernel versions prior to the fix commit [1].
Exploitation
An attacker must have a malicious USB printer device (physical or emulated) that responds to a LPGETSTATUS request with zero bytes. No special privileges are required beyond the ability to open the printer device file (e.g., /dev/usb/lp*). The attacker triggers the ioctl, and the driver copies uninitialized heap data to user space via copy_to_user().
Impact
Successful exploitation results in information disclosure: up to 1 byte of kernel heap memory is leaked to the ioctl caller. The leaked data may contain sensitive kernel pointers or other heap contents, potentially aiding further attacks.
Mitigation
The fix zeros the statusbuf at probe time, ensuring no stale data is leaked. The commit is part of the Linux kernel stable tree [1]. Users should apply the patch or update to a kernel version that includes the fix. No workaround exists, but exploitation requires a malicious USB device.
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
10d06d937b0a4cusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a04acadc4faf01..7424052a1fa961 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1166,7 +1166,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
6b0e7438e31cusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index e9b848622a3aa5..746414763da5d6 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
a502b9976684usb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a04acadc4faf01..7424052a1fa961 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1166,7 +1166,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
b38e53cbfb9dusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index e9b848622a3aa5..746414763da5d6 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
762a6ccf391dusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 2c47acdc35be4c..a213b8397d44a1 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
b38e53cbfb9dusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index e9b848622a3aa5..746414763da5d6 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
762a6ccf391dusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 2c47acdc35be4c..a213b8397d44a1 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
a502b9976684usb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a04acadc4faf01..7424052a1fa961 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1166,7 +1166,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
6b0e7438e31cusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index e9b848622a3aa5..746414763da5d6 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1178,7 +1178,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
d06d937b0a4cusb: usblp: fix uninitialized heap leak via LPGETSTATUS ioctl
1 file changed · +1 −2
drivers/usb/class/usblp.c+1 −2 modifieddiff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index a04acadc4faf01..7424052a1fa961 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -1166,7 +1166,7 @@ static int usblp_probe(struct usb_interface *intf, } /* Allocate buffer for printer status */ - usblp->statusbuf = kmalloc(STATUS_BUF_SIZE, GFP_KERNEL); + usblp->statusbuf = kzalloc(STATUS_BUF_SIZE, GFP_KERNEL); if (!usblp->statusbuf) { retval = -ENOMEM; goto abort; -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Uninitialized heap memory in statusbuf (allocated with kmalloc instead of kzalloc) is exposed to user-space via the LPGETSTATUS ioctl when a malicious printer returns fewer bytes than requested."
Attack vector
An attacker must connect a malicious USB printer device to the target system. When a user-space program issues the `LPGETSTATUS` ioctl, the kernel calls `usblp_read_status()` which requests 1 byte from the device via a USB control message. If the malicious printer responds with zero bytes, `*statusbuf` retains one byte of stale kmalloc heap memory. That byte is sign-extended into a local `int status`, which is then copied directly to the ioctl caller via `copy_to_user()`, leaking uninitialized kernel heap data [patch_id=2898118].
Affected code
The vulnerability is in `drivers/usb/class/usblp.c` in the `usblp_probe()` function. The `statusbuf` buffer is allocated with `kmalloc(STATUS_BUF_SIZE, GFP_KERNEL)` which does not zero the memory, leaving it uninitialized. The `usblp_read_status()` function then reads into this buffer via `usb_control_msg()`, but `usblp_ctrl_msg()` collapses the return value to 0/-errno, discarding the actual byte count — so a short or zero-byte response leaves stale heap data in `statusbuf`.
What the fix does
The patch changes `kmalloc(STATUS_BUF_SIZE, GFP_KERNEL)` to `kzalloc(STATUS_BUF_SIZE, GFP_KERNEL)` in `usblp_probe()` [patch_id=2898118]. This zero-initializes the `statusbuf` buffer at allocation time, so even if a malicious printer sends a zero-byte response (or no response at all before the first ioctl), the buffer contains predictable zeros instead of stale heap data. The commit notes that detecting short reads and erroring out is not feasible because many printers send "incorrect" responses, so zeroing at allocation is the chosen mitigation.
Preconditions
- inputAttacker must connect a malicious USB printer device to the target system
- inputA user-space program must issue the LPGETSTATUS ioctl on the usblp device node
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/6b0e7438e31c74b01514d31ff35c1e688c4baabanvd
- git.kernel.org/stable/c/762a6ccf391db0d629e590a803a3a2231e17dd3fnvd
- git.kernel.org/stable/c/a502b997668401a6821501fc98b7f9220f9b6ff2nvd
- git.kernel.org/stable/c/b38e53cbfb9d84732e5984fbd73e128d592415c5nvd
- git.kernel.org/stable/c/d06d937b0a4cdb8867f04275c8100a8b943da31anvd
News mentions
0No linked articles in our index yet.