FAILED: patch "[PATCH] Input: pegasus-notetaker - fix potential out-of-bounds access" failed to apply to 5.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 5.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.4.y
git checkout FETCH_HEAD
git cherry-pick -x 69aeb507312306f73495598a055293fa749d454e
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025112420-barman-maybe-9927@gregkh' --subject-prefix 'PATCH 5.4.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 69aeb507312306f73495598a055293fa749d454e Mon Sep 17 00:00:00 2001
From: Seungjin Bae <[email protected]>
Date: Fri, 17 Oct 2025 15:36:31 -0700
Subject: [PATCH] Input: pegasus-notetaker - fix potential out-of-bounds access
In the pegasus_notetaker driver, the pegasus_probe() function allocates the URB transfer buffer using the wMaxPacketSize value from the endpoint descriptor. An attacker can use a malicious USB descriptor to force the allocation of a very small buffer.
Subsequently, if the device sends an interrupt packet with a specific pattern (e.g., where the first byte is 0x80 or 0x42),
the pegasus_parse_packet() function parses the packet without checking the allocated buffer size. This leads to an out-of-bounds memory access.
drivers/input/tablet/pegasus_notetaker.c +9 -0
@@ -63,6 +63,9 @@#define BUTTON_PRESSED 0xb5#define COMMAND_VERSION 0xa9 +/* 1 Status + 1 Color + 2 X + 2 Y = 6 bytes */ +#define NOTETAKER_PACKET_SIZE 6 +/* in xy data packet */ #define BATTERY_NO_REPORT 0x40#define BATTERY_LOW 0x41
@@ -311,6 +314,12 @@ static int pegasus_probe(struct usb_interface *intf, } pegasus->data_len =usb_maxpacket (dev, pipe); +if (pegasus->data_len <NOTETAKER_PACKET_SIZE ) { +dev_err (&intf->dev,"packet size is too small (%d)\n" , + pegasus->data_len); + error = -EINVAL ; + goto err_free_mem; + } pegasus->data =usb_alloc_coherent (dev, pegasus->data_len,GFP_KERNEL , &pegasus->data_dma);
Sasha Levin
maintainerPATCH 1/3 usb: deprecate the third argument of usb_maxpacket()
From: Vincent Mailhol <[email protected]>
[ Upstream commit 0f08c2e7458e25c967d844170f8ad1aac3b57a02 ]
This is a transitional patch with the ultimate goal of changing the prototype of usb_maxpacket() from:
| static inline __u16
| usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
into:
| static inline u16 usb_maxpacket(struct usb_device *udev, int pipe)
The third argument of usb_maxpacket(): is_out gets removed because it can be derived from its second argument: pipe using usb_pipeout(pipe). Furthermore, in the current version, ubs_pipeout(pipe) is called regardless in order to sanitize the is_out parameter.
In order to make a smooth change, we first deprecate the is_out parameter by simply ignoring it (using a variadic function) and will remove it later, once all the callers get updated.
The body of the function is reworked accordingly and is_out is replaced by usb_pipeout(pipe). The WARN_ON() calls become unnecessary and get removed.
Finally, the return type is changed from __u16 to u16 because this is not a UAPI function.
Stable-dep-of: 69aeb5073123 ("Input: pegasus-notetaker - fix potential out-of-bounds access")
--- include/linux/usb.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
include/linux/usb.h +5 -11
@@ -1964,21 +1964,17 @@ usb_pipe_endpoint(struct usb_device *dev, unsigned int pipe)return eps[usb_pipeendpoint (pipe)]; } -/*-------------------------------------------------------------------------*/ - -static inline __u16 -usb_maxpacket (struct usb_device *udev,int pipe,int is_out) +static inline u16 usb_maxpacket (struct usb_device *udev,int pipe, +/* int is_out deprecated */ ...) {struct usb_host_endpoint *ep;unsigned epnum =usb_pipeendpoint (pipe); -if (is_out) { -WARN_ON (usb_pipein (pipe)); +if (usb_pipeout (pipe)) ep = udev->ep_out[epnum]; - }else { -WARN_ON (usb_pipeout (pipe)); +else ep = udev->ep_in[epnum]; - } +if (!ep)return 0 ;
@@ -1986,8 +1982,6 @@ usb_maxpacket(struct usb_device *udev, int pipe, int is_out)return usb_endpoint_maxp (&ep->desc); } -/* ----------------------------------------------------------------------- */ -/* translate USB error codes to codes user space understands */ static inline int usb_translate_errors (int error_code) {
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/3 Input: remove third argument of usb_maxpacket()
From: Vincent Mailhol <[email protected]>
[ Upstream commit 948bf187694fc1f4c20cf972fa18b1a6fb3d7603 ]
The third argument of usb_maxpacket(): in_out has been deprecated because it could be derived from the second argument (e.g. using usb_pipeout(pipe)).
N.B. function usb_maxpacket() was made variadic to accommodate the transition from the old prototype with three arguments to the new one with only two arguments (so that no renaming is needed). The variadic argument is to be removed once all users of usb_maxpacket() get migrated.
Stable-dep-of: 69aeb5073123 ("Input: pegasus-notetaker - fix potential out-of-bounds access")
--- drivers/input/misc/ati_remote2.c | 2 +- drivers/input/misc/cm109.c | 2 +- drivers/input/misc/powermate.c | 2 +- drivers/input/misc/yealink.c | 2 +- drivers/input/tablet/acecad.c | 2 +- drivers/input/tablet/pegasus_notetaker.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-)
drivers/input/misc/ati_remote2.c +1 -1
@@ -639,7 +639,7 @@ static int ati_remote2_urb_init(struct ati_remote2 *ar2)return -ENOMEM ; pipe =usb_rcvintpipe (udev, ar2->ep[i]->bEndpointAddress); - maxp =usb_maxpacket (udev, pipe,usb_pipeout (pipe)); + maxp =usb_maxpacket (udev, pipe); maxp = maxp >4 ?4 : maxp; usb_fill_int_urb(ar2->urb[i], udev, pipe, ar2->buf[i], maxp,
drivers/input/misc/cm109.c +1 -1
@@ -749,7 +749,7 @@ static int cm109_usb_probe(struct usb_interface *intf,/* get a handle to the interrupt data pipe */ pipe =usb_rcvintpipe (udev, endpoint->bEndpointAddress); - ret =usb_maxpacket (udev, pipe,usb_pipeout (pipe)); + ret =usb_maxpacket (udev, pipe);if (ret !=USB_PKT_LEN )dev_err (&intf->dev,"invalid payload size %d, expected %d\n" , ret,USB_PKT_LEN );
drivers/input/misc/powermate.c +1 -1
@@ -374,7 +374,7 @@ static int powermate_probe(struct usb_interface *intf, const struct usb_device_i/* get a handle to the interrupt data pipe */ pipe =usb_rcvintpipe (udev, endpoint->bEndpointAddress); - maxp =usb_maxpacket (udev, pipe,usb_pipeout (pipe)); + maxp =usb_maxpacket (udev, pipe);if (maxp <POWERMATE_PAYLOAD_SIZE_MIN || maxp >POWERMATE_PAYLOAD_SIZE_MAX ) { printk(KERN_WARNING "powermate: Expected payload of %d--%d bytes, found %d bytes!\n",
drivers/input/misc/yealink.c +1 -1
@@ -905,7 +905,7 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)/* get a handle to the interrupt data pipe */ pipe =usb_rcvintpipe (udev, endpoint->bEndpointAddress); - ret =usb_maxpacket (udev, pipe,usb_pipeout (pipe)); + ret =usb_maxpacket (udev, pipe);if (ret !=USB_PKT_LEN )dev_err (&intf->dev,"invalid payload size %d, expected %zd\n" , ret,USB_PKT_LEN );
drivers/input/tablet/acecad.c +1 -1
@@ -130,7 +130,7 @@ static int usb_acecad_probe(struct usb_interface *intf, const struct usb_device_return -ENODEV ; pipe =usb_rcvintpipe (dev, endpoint->bEndpointAddress); - maxp =usb_maxpacket (dev, pipe,usb_pipeout (pipe)); + maxp =usb_maxpacket (dev, pipe); acecad =kzalloc (sizeof (struct usb_acecad ),GFP_KERNEL ); input_dev =input_allocate_device ();
drivers/input/tablet/pegasus_notetaker.c +1 -1
@@ -296,7 +296,7 @@ static int pegasus_probe(struct usb_interface *intf, pegasus->intf = intf; pipe =usb_rcvintpipe (dev, endpoint->bEndpointAddress); - pegasus->data_len =usb_maxpacket (dev, pipe,usb_pipeout (pipe)); + pegasus->data_len =usb_maxpacket (dev, pipe); pegasus->data =usb_alloc_coherent (dev, pegasus->data_len,GFP_KERNEL , &pegasus->data_dma);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 3/3 Input: pegasus-notetaker - fix potential out-of-bounds access
In reply to Sasha LevinFrom: Seungjin Bae <[email protected]>
[ Upstream commit 69aeb507312306f73495598a055293fa749d454e ]
In the pegasus_notetaker driver, the pegasus_probe() function allocates the URB transfer buffer using the wMaxPacketSize value from the endpoint descriptor. An attacker can use a malicious USB descriptor to force the allocation of a very small buffer.
Subsequently, if the device sends an interrupt packet with a specific pattern (e.g., where the first byte is 0x80 or 0x42),
the pegasus_parse_packet() function parses the packet without checking the allocated buffer size. This leads to an out-of-bounds memory access.
--- drivers/input/tablet/pegasus_notetaker.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/input/tablet/pegasus_notetaker.c +9 -0
@@ -63,6 +63,9 @@#define BUTTON_PRESSED 0xb5#define COMMAND_VERSION 0xa9 +/* 1 Status + 1 Color + 2 X + 2 Y = 6 bytes */ +#define NOTETAKER_PACKET_SIZE 6 +/* in xy data packet */ #define BATTERY_NO_REPORT 0x40#define BATTERY_LOW 0x41
@@ -297,6 +300,12 @@ static int pegasus_probe(struct usb_interface *intf, pipe =usb_rcvintpipe (dev, endpoint->bEndpointAddress); pegasus->data_len =usb_maxpacket (dev, pipe); +if (pegasus->data_len <NOTETAKER_PACKET_SIZE ) { +dev_err (&intf->dev,"packet size is too small (%d)\n" , + pegasus->data_len); + error = -EINVAL ; + goto err_free_mem; + } pegasus->data =usb_alloc_coherent (dev, pegasus->data_len,GFP_KERNEL , &pegasus->data_dma);
Signature · 1 line
2.51.0