Re: [PATCH net 10/20] can: peak_usb: add bounds check for USB channel index

[email protected] Thu, 30 Jul 2026 10:29:51 +0000
Newsgroups org.kernel.vger.linux-can
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 3 potential issue(=
s) to consider:

Pre-existing issues:
- [High] Unvalidated CAN payload length from the USB packet causes a heap b=
uffer overflow when copying data into the SKB and reading from the URB buff=
er.
- [High] Inadequate bounds checking allows a NULL pointer dereference of un=
initialized channel device pointers.
- [High] Race condition during probe exposes the network interface before d=
river initialization is complete, leading to a NULL pointer dereference.
--

--- Patch [10]: [PATCH net 10/20] can: peak_usb: add bounds check for USB c=
hannel index ---
commit bda9ca94a61ede6bd59945cb6b8e4a5d2a8b5017
Author: James Gao <[email protected]>

can: peak_usb: add bounds check for USB channel index

The channel control index ctrl_idx is derived from rx->len which comes
directly from a device USB payload. The mask 0x0f allows values 0-15, but
the array size of usb_if->dev[] is only 2. Values 2-15 cause heap
out-of-bounds read, eventually causing kernel panic in the IRQ context.

Link: https://patch.msgid.link/TYWPR01MB8559DBAAAA6A7F410400329CF0012@TYWPR=
01MB8559.jpnprd01.prod.outlook.com

> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/ca=
n/usb/peak_usb/pcan_usb_pro.c
> index aefcded8e12a8..b6be8c19e537f 100644
> --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
> @@ -534,12 +534,18 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_u=
sb_pro_interface *usb_if,
>  				      struct pcan_usb_pro_rxmsg *rx)
>  {
>  	const unsigned int ctrl_idx =3D (rx->len >> 4) & 0x0f;
> -	struct peak_usb_device *dev =3D usb_if->dev[ctrl_idx];
> -	struct net_device *netdev =3D dev->netdev;
> +	struct peak_usb_device *dev;
> +	struct net_device *netdev;
>  	struct can_frame *can_frame;
>  	struct sk_buff *skb;
>  	struct skb_shared_hwtstamps *hwts;
> =20
> +	if (ctrl_idx >=3D ARRAY_SIZE(usb_if->dev))
> +		return -EINVAL;
> +
> +	dev =3D usb_if->dev[ctrl_idx];
> +	netdev =3D dev->netdev;

[Severity: High]
This isn't a bug introduced by this patch, but does checking against
ARRAY_SIZE() fully protect against NULL pointer dereferences here?

If a single-channel adapter is used, usb_if->dev[1] might be left
uninitialized (NULL). If a device sends URBs for channel 1, wouldn't it
bypass the ARRAY_SIZE() check and cause a kernel panic when dereferencing
dev->netdev?

There appears to be an identical inadequate bounds check in the FD variant
of the driver at pcan_usb_fd_decode_canmsg().

[Severity: High]
This is a pre-existing issue, but does this code overflow can_frame->data[]
when copying the payload?

Looking further down in pcan_usb_pro_handle_canmsg():

    can_frame->len =3D rx->len & 0x0f;
    ...
    } else {
        memcpy(can_frame->data, rx->data, can_frame->len);
    }

Since rx->len & 0x0f allows values up to 15, and can_frame->data[] is only =
an
8-byte array, could a malicious device send an oversized payload length and
overflow can_frame->data[]?

> +
>  	skb =3D alloc_can_skb(netdev, &can_frame);
>  	if (!skb)
>  		return -ENOMEM;

[ ... ]

> @@ -573,14 +579,20 @@ static int pcan_usb_pro_handle_error(struct pcan_us=
b_pro_interface *usb_if,
>  {
>  	const u16 raw_status =3D le16_to_cpu(er->status);
>  	const unsigned int ctrl_idx =3D (er->channel >> 4) & 0x0f;
> -	struct peak_usb_device *dev =3D usb_if->dev[ctrl_idx];
> -	struct net_device *netdev =3D dev->netdev;
> +	struct peak_usb_device *dev;
> +	struct net_device *netdev;
>  	struct can_frame *can_frame;
>  	enum can_state new_state =3D CAN_STATE_ERROR_ACTIVE;
>  	u8 err_mask =3D 0;
>  	struct sk_buff *skb;
>  	struct skb_shared_hwtstamps *hwts;
> =20
> +	if (ctrl_idx >=3D ARRAY_SIZE(usb_if->dev))
> +		return -EINVAL;
> +
> +	dev =3D usb_if->dev[ctrl_idx];
> +	netdev =3D dev->netdev;
> +
>  	/* nothing should be sent while in BUS_OFF state */
>  	if (dev->can.state =3D=3D CAN_STATE_BUS_OFF)
>  		return 0;

[Severity: High]
This is a pre-existing issue, but is there a race condition during probe
that could expose the network interface before driver initialization is
complete?

In peak_usb_create_dev(), register_candev() is called before the interface
is fully initialized:

drivers/net/can/usb/peak_usb/pcan_usb_core.c:peak_usb_create_dev() {
    ...
    err =3D register_candev(netdev);
    ...
}

If userspace immediately brings the interface up (e.g., via udev),
pcan_usb_pro_start() is called and dereferences pdev->usb_if:

drivers/net/can/usb/peak_usb/pcan_usb_pro.c:pcan_usb_pro_start() {
    ...
    if (pdev->usb_if->dev_opened_count =3D=3D 0) {
    ...
}

Since pdev->usb_if is only allocated and assigned later in
pcan_usb_pro_init(), wouldn't this cause a NULL pointer dereference?

--=20
Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260729102802.5051=
[email protected]?part=3D10