Linux CAN drivers development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Marc Kleine-Budde" <mkl@pengutronix.de>
Cc: "Marc Kleine-Budde" <mkl@pengutronix.de>,
	linux-can@vger.kernel.org,
	"Oleksij Rempel" <o.rempel@pengutronix.de>,
	"Vincent Mailhol" <mailhol@kernel.org>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>
Subject: Re: [PATCH net 10/20] can: peak_usb: add bounds check for USB channel index
Date: Thu, 30 Jul 2026 10:29:51 +0000	[thread overview]
Message-ID: <20260730102952.3DF481F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260729102802.505168-11-mkl@pengutronix.de>

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 buffer overflow when copying data into the SKB and reading from the URB buffer.
- [High] Inadequate bounds checking allows a NULL pointer dereference of uninitialized channel device pointers.
- [High] Race condition during probe exposes the network interface before driver initialization is complete, leading to a NULL pointer dereference.
--

--- Patch [10]: [PATCH net 10/20] can: peak_usb: add bounds check for USB channel index ---
commit bda9ca94a61ede6bd59945cb6b8e4a5d2a8b5017
Author: James Gao <jamesgao5@outlook.com>

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@TYWPR01MB8559.jpnprd01.prod.outlook.com

> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/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_usb_pro_interface *usb_if,
>  				      struct pcan_usb_pro_rxmsg *rx)
>  {
>  	const unsigned int ctrl_idx = (rx->len >> 4) & 0x0f;
> -	struct peak_usb_device *dev = usb_if->dev[ctrl_idx];
> -	struct net_device *netdev = 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;
>  
> +	if (ctrl_idx >= ARRAY_SIZE(usb_if->dev))
> +		return -EINVAL;
> +
> +	dev = usb_if->dev[ctrl_idx];
> +	netdev = 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 = 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 = alloc_can_skb(netdev, &can_frame);
>  	if (!skb)
>  		return -ENOMEM;

[ ... ]

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

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

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260729102802.505168-1-mkl@pengutronix.de?part=10

  reply	other threads:[~2026-07-30 10:29 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-29 10:12 [PATCH net 0/20] pull-request: can 2026-07-29 Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 01/20] can: j1939: use netdevice_tracker for j1939_{priv,session,ecu} tracking Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-30 13:20   ` patchwork-bot+netdevbpf
2026-07-29 10:12 ` [PATCH net 02/20] can: j1939: transport: j1939_session_fresh_new(): initialize receive buffer Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 03/20] can: isotp: fix timer drain order, wakeup handling and tx_gen ordering Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-30 12:28     ` Oliver Hartkopp
2026-07-29 10:12 ` [PATCH net 04/20] can: isotp: check register_netdevice_notifier() error in module init Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 05/20] can: ctucanfd: unmap BAR0 using base address Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 06/20] can: ctucanfd: mark error-active controller status valid Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-30 11:14     ` Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 07/20] can: ctucanfd: handle bus error interrupts Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-30 11:18     ` Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 08/20] can: ctucanfd: use self-test mode for PRESUME_ACK Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-30 11:25     ` Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 09/20] can: ctucanfd: add missing MODULE_DEVICE_TABLE() Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 10/20] can: peak_usb: add bounds check for USB channel index Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot [this message]
2026-07-29 10:12 ` [PATCH net 11/20] can: peak_usb: peak_usb_start(): fix double free of transfer buffer on URB submit error Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 12/20] can: peak_usb: validate uCAN receive record lengths Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 13/20] can: kvaser_usb: kvaser_usb_hydra_get_busparams(): fix memory leak in kvaser_usb_hydra_get_busparams() Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 14/20] can: kvaser_usb_leaf: kvaser_usb_leaf_wait_cmd(): validate received command extents Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 15/20] can: rcar_canfd: change the initializing flow for clocks and resets Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 16/20] can: softing: fw_parse(): validate firmware record spans Marc Kleine-Budde
2026-07-30 10:29   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 17/20] can: c_can: c_can_chip_config(): keep controller in init mode until bittiming is configured Marc Kleine-Budde
2026-07-30 10:30   ` sashiko-bot
2026-07-29 10:12 ` [PATCH net 18/20] can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure Marc Kleine-Budde
2026-07-29 10:12 ` [PATCH net 19/20] can: etas_es58x: es58x_read_bulk_callback(): fix RX buffer leak on URB resubmit failure Marc Kleine-Budde
2026-07-29 10:13 ` [PATCH net 20/20] can: ems_usb: validate CPC message lengths Marc Kleine-Budde
2026-07-30 10:30   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260730102952.3DF481F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-can@vger.kernel.org \
    --cc=mailhol@kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=o.rempel@pengutronix.de \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=socketcan@hartkopp.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox