From: Greg Kroah-Hartman Date: Wed, 5 Aug 2026 12:04:49 +0000 (+0200) Subject: 6.12-stable patches X-Git-Tag: v5.10.263~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=83eade28a3e10ac49507e669f1a898d54bac1405;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: can-c_can-c_can_chip_config-keep-controller-in-init-mode-until-bittiming-is-configured.patch can-ctucanfd-add-missing-module_device_table.patch can-ctucanfd-handle-bus-error-interrupts.patch can-ctucanfd-mark-error-active-controller-status-valid.patch can-ctucanfd-unmap-bar0-using-base-address.patch can-ctucanfd-use-self-test-mode-for-presume_ack.patch can-ems_usb-validate-cpc-message-lengths.patch can-etas_es58x-es58x_read_bulk_callback-fix-rx-buffer-leak-on-urb-resubmit-failure.patch can-gs_usb-gs_usb_receive_bulk_callback-resubmit-urb-on-skb-allocation-failure.patch can-j1939-transport-j1939_session_fresh_new-initialize-receive-buffer.patch can-j1939-use-netdevice_tracker-for-j1939_-priv-session-ecu-tracking.patch can-kvaser_usb-kvaser_usb_hydra_get_busparams-fix-memory-leak-in-kvaser_usb_hydra_get_busparams.patch can-kvaser_usb_leaf-kvaser_usb_leaf_wait_cmd-validate-received-command-extents.patch can-peak_usb-add-bounds-check-for-usb-channel-index.patch can-peak_usb-peak_usb_start-fix-double-free-of-transfer-buffer-on-urb-submit-error.patch can-peak_usb-validate-ucan-receive-record-lengths.patch can-softing-fw_parse-validate-firmware-record-spans.patch drm-amd-display-add-av-mute-wait-frames-to-dce110_set_avmute.patch drm-amdgpu-cap-gtt-size-to-physical-ram-on-apus.patch drm-amdgpu-restore-umd-profile-pstate-after-runtime-resume.patch drm-dp-read-the-pcon-max-frl-bandwidth-only-for-hdmi-dfps.patch drm-mediatek-ovl_adaptor-balance-component-registrations.patch drm-panthor-reject-firmware-sections-with-oversized-data.patch drm-panthor-validate-firmware-interface-structure-sizes.patch drm-vc4-supply-the-overflow-slot-size-in-bpos-not-the-whole-bin-bo-size.patch drm-vc4-zero-the-tile-state-data-array-before-each-bin-job.patch --- diff --git a/queue-6.12/can-c_can-c_can_chip_config-keep-controller-in-init-mode-until-bittiming-is-configured.patch b/queue-6.12/can-c_can-c_can_chip_config-keep-controller-in-init-mode-until-bittiming-is-configured.patch new file mode 100644 index 0000000000..a8a607bc86 --- /dev/null +++ b/queue-6.12/can-c_can-c_can_chip_config-keep-controller-in-init-mode-until-bittiming-is-configured.patch @@ -0,0 +1,62 @@ +From 26504844613fb44c7cab1c5f6fcff77861709baa Mon Sep 17 00:00:00 2001 +From: Lucas Martins Alves +Date: Tue, 14 Jul 2026 16:48:57 +0000 +Subject: can: c_can: c_can_chip_config(): keep controller in init mode until bittiming is configured + +From: Lucas Martins Alves + +commit 26504844613fb44c7cab1c5f6fcff77861709baa upstream. + +c_can_chip_config() was programming C_CAN_CTRL_REG without CONTROL_INIT, +which may allow the controller to become active before +c_can_set_bittiming() finishes. + +That creates a short timing window where the peripheral can interact with +the bus using a different/default bitrate, potentially generating bus +errors and corrupting traffic. + +Set CONTROL_INIT together with the control-mode writes in +c_can_chip_config() (normal, loopback and listen-only paths), so the +controller stays halted until bit timing is fully programmed. + +This prevents transient bus disturbance during startup when the configured +bitrate differs from the active bus bitrate. + +Signed-off-by: Lucas Martins Alves +Link: https://patch.msgid.link/20260714164839.771123-1-lucas.alves@lumal21.com.br +Fixes: 881ff67ad450 ("can: c_can: Added support for Bosch C_CAN controller") +Cc: stable@kernel.org +[mkl: remove space before close parenthesis] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/c_can/c_can_main.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/net/can/c_can/c_can_main.c ++++ b/drivers/net/can/c_can/c_can_main.c +@@ -597,20 +597,20 @@ static int c_can_chip_config(struct net_ + return err; + + /* enable automatic retransmission */ +- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR); ++ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_ENABLE_AR | CONTROL_INIT); + + if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && + (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { + /* loopback + silent mode : useful for hot self-test */ +- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); ++ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT); + priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK | TEST_SILENT); + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { + /* loopback mode : useful for self-test function */ +- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); ++ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT); + priv->write_reg(priv, C_CAN_TEST_REG, TEST_LBACK); + } else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) { + /* silent mode : bus-monitoring mode */ +- priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST); ++ priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_TEST | CONTROL_INIT); + priv->write_reg(priv, C_CAN_TEST_REG, TEST_SILENT); + } + diff --git a/queue-6.12/can-ctucanfd-add-missing-module_device_table.patch b/queue-6.12/can-ctucanfd-add-missing-module_device_table.patch new file mode 100644 index 0000000000..491aa24aa2 --- /dev/null +++ b/queue-6.12/can-ctucanfd-add-missing-module_device_table.patch @@ -0,0 +1,41 @@ +From d937bdb244a751fe5967052ea2d64a7b2c476cc0 Mon Sep 17 00:00:00 2001 +From: Pengpeng Hou +Date: Sat, 4 Jul 2026 23:19:57 +0800 +Subject: can: ctucanfd: add missing MODULE_DEVICE_TABLE() + +From: Pengpeng Hou + +commit d937bdb244a751fe5967052ea2d64a7b2c476cc0 upstream. + +The driver has a match table for the pci bus wired into its driver +structure, but the table is not exported with MODULE_DEVICE_TABLE(). + +Add the missing MODULE_DEVICE_TABLE() entry so module alias information +is generated for automatic module loading. + +This is a source-level fix. It does not claim dynamic hardware +reproduction; the evidence is the driver-owned match table, its use by +the driver registration structure, and the missing module alias +publication. + +Signed-off-by: Pengpeng Hou +Acked-by: Pavel Pisa +Link: https://patch.msgid.link/20260704151957.48194-1-pengpeng@iscas.ac.cn +Fixes: 792a5b678e81 ("can: ctucanfd: CTU CAN FD open-source IP core - PCI bus support.") +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/ctucanfd/ctucanfd_pci.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c ++++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c +@@ -274,6 +274,7 @@ static const struct pci_device_id ctucan + CTUCAN_WITH_CTUCAN_ID)}, + {}, + }; ++MODULE_DEVICE_TABLE(pci, ctucan_pci_tbl); + + static struct pci_driver ctucan_pci_driver = { + .name = KBUILD_MODNAME, diff --git a/queue-6.12/can-ctucanfd-handle-bus-error-interrupts.patch b/queue-6.12/can-ctucanfd-handle-bus-error-interrupts.patch new file mode 100644 index 0000000000..5984502afc --- /dev/null +++ b/queue-6.12/can-ctucanfd-handle-bus-error-interrupts.patch @@ -0,0 +1,44 @@ +From e74bae899529f49c0f375307983d12e8ecad7d4b Mon Sep 17 00:00:00 2001 +From: Avi Weiss +Date: Thu, 23 Jul 2026 10:44:03 +0300 +Subject: can: ctucanfd: handle bus error interrupts + +From: Avi Weiss + +commit e74bae899529f49c0f375307983d12e8ecad7d4b upstream. + +Include REG_INT_STAT_BEI in the top-level error interrupt condition. + +BEI is enabled when CAN_CTRLMODE_BERR_REPORTING is requested and +ctucan_err_interrupt() already handles it. Without checking and +clearing BEI in the top-level handler, bus error interrupts are not +handled or acknowledged. + +Fixes: 2dcb8e8782d8 ("can: ctucanfd: add support for CTU CAN FD open-source IP core - bus independent part.") +Signed-off-by: Avi Weiss +Acked-by: Pavel Pisa +Link: https://patch.msgid.link/20260723074403.131575-1-thnkslprpt@gmail.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/ctucanfd/ctucanfd_base.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/ctucanfd/ctucanfd_base.c ++++ b/drivers/net/can/ctucanfd/ctucanfd_base.c +@@ -1135,8 +1135,12 @@ static irqreturn_t ctucan_interrupt(int + /* Error interrupts */ + if (FIELD_GET(REG_INT_STAT_EWLI, isr) || + FIELD_GET(REG_INT_STAT_FCSI, isr) || +- FIELD_GET(REG_INT_STAT_ALI, isr)) { +- icr = isr & (REG_INT_STAT_EWLI | REG_INT_STAT_FCSI | REG_INT_STAT_ALI); ++ FIELD_GET(REG_INT_STAT_ALI, isr) || ++ FIELD_GET(REG_INT_STAT_BEI, isr)) { ++ icr = isr & (REG_INT_STAT_EWLI | ++ REG_INT_STAT_FCSI | ++ REG_INT_STAT_ALI | ++ REG_INT_STAT_BEI); + + ctucan_netdev_dbg(ndev, "some ERR interrupt: clearing 0x%08x\n", icr); + ctucan_write32(priv, CTUCANFD_INT_STAT, icr); diff --git a/queue-6.12/can-ctucanfd-mark-error-active-controller-status-valid.patch b/queue-6.12/can-ctucanfd-mark-error-active-controller-status-valid.patch new file mode 100644 index 0000000000..d120b3e788 --- /dev/null +++ b/queue-6.12/can-ctucanfd-mark-error-active-controller-status-valid.patch @@ -0,0 +1,37 @@ +From 4e735cbe3affe88001428fdd9cae8e685ce92f21 Mon Sep 17 00:00:00 2001 +From: Avi Weiss +Date: Thu, 23 Jul 2026 18:55:43 +0300 +Subject: can: ctucanfd: mark error-active controller status valid + +From: Avi Weiss + +commit 4e735cbe3affe88001428fdd9cae8e685ce92f21 upstream. + +In the CAN_STATE_ERROR_ACTIVE case, cf->data[1] is set to +CAN_ERR_CRTL_ACTIVE, but cf->can_id is not set with CAN_ERR_CRTL in +that path. + +Set CAN_ERR_CRTL so consumers know the controller-status information +in cf->data[1] is valid. + +Fixes: 9bd24927e3ee ("can: ctucanfd: handle skb allocation failure") +Signed-off-by: Avi Weiss +Link: https://patch.msgid.link/20260723155543.318414-1-thnkslprpt@gmail.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/ctucanfd/ctucanfd_base.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/can/ctucanfd/ctucanfd_base.c ++++ b/drivers/net/can/ctucanfd/ctucanfd_base.c +@@ -868,7 +868,7 @@ static void ctucan_err_interrupt(struct + break; + case CAN_STATE_ERROR_ACTIVE: + if (skb) { +- cf->can_id |= CAN_ERR_CNT; ++ cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT; + cf->data[1] = CAN_ERR_CRTL_ACTIVE; + cf->data[6] = bec.txerr; + cf->data[7] = bec.rxerr; diff --git a/queue-6.12/can-ctucanfd-unmap-bar0-using-base-address.patch b/queue-6.12/can-ctucanfd-unmap-bar0-using-base-address.patch new file mode 100644 index 0000000000..95a3346a44 --- /dev/null +++ b/queue-6.12/can-ctucanfd-unmap-bar0-using-base-address.patch @@ -0,0 +1,37 @@ +From a6873910f983096746d1a2e0af94f36b8003e839 Mon Sep 17 00:00:00 2001 +From: Avi Weiss +Date: Thu, 23 Jul 2026 12:59:34 +0300 +Subject: can: ctucanfd: unmap BAR0 using base address + +From: Avi Weiss + +commit a6873910f983096746d1a2e0af94f36b8003e839 upstream. + +BAR0 is mapped into bar0_base, while cra_addr points to an offset +within that mapping and is used for other purposes. + +Pass bar0_base to pci_iounmap(), instead of cra_addr, on the probe error +path so the address returned by pci_iomap() is used for unmapping. + +Fixes: 792a5b678e81 ("can: ctucanfd: CTU CAN FD open-source IP core - PCI bus support.") +Signed-off-by: Avi Weiss +Acked-by: Pavel Pisa +Link: https://patch.msgid.link/20260723095934.181042-1-thnkslprpt@gmail.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/ctucanfd/ctucanfd_pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/can/ctucanfd/ctucanfd_pci.c ++++ b/drivers/net/can/ctucanfd/ctucanfd_pci.c +@@ -202,7 +202,7 @@ err_free_board: + pci_set_drvdata(pdev, NULL); + kfree(bdata); + err_pci_iounmap_bar0: +- pci_iounmap(pdev, cra_addr); ++ pci_iounmap(pdev, bar0_base); + err_pci_iounmap_bar1: + pci_iounmap(pdev, addr); + err_release_regions: diff --git a/queue-6.12/can-ctucanfd-use-self-test-mode-for-presume_ack.patch b/queue-6.12/can-ctucanfd-use-self-test-mode-for-presume_ack.patch new file mode 100644 index 0000000000..b2e57f34a4 --- /dev/null +++ b/queue-6.12/can-ctucanfd-use-self-test-mode-for-presume_ack.patch @@ -0,0 +1,39 @@ +From c31a435933f18be0f874302161333e9f16e200a0 Mon Sep 17 00:00:00 2001 +From: Avi Weiss +Date: Wed, 22 Jul 2026 22:27:26 +0300 +Subject: can: ctucanfd: use self-test mode for PRESUME_ACK + +From: Avi Weiss + +commit c31a435933f18be0f874302161333e9f16e200a0 upstream. + +Use self-test mode for CAN_CTRLMODE_PRESUME_ACK so transmitted +frames can complete without receiving an ACK. + +ACK forbidden mode prevents the controller from acknowledging +received frames and does not implement the presume-ack behavior. + +Fixes: 2dcb8e8782d8 ("can: ctucanfd: add support for CTU CAN FD open-source IP core - bus independent part.") +Signed-off-by: Avi Weiss +Acked-by: Pavel Pisa +Link: https://patch.msgid.link/20260722192726.230729-1-thnkslprpt@gmail.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/ctucanfd/ctucanfd_base.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/ctucanfd/ctucanfd_base.c ++++ b/drivers/net/can/ctucanfd/ctucanfd_base.c +@@ -340,8 +340,8 @@ static void ctucan_set_mode(struct ctuca + (mode_reg & ~REG_MODE_FDE); + + mode_reg = (mode->flags & CAN_CTRLMODE_PRESUME_ACK) ? +- (mode_reg | REG_MODE_ACF) : +- (mode_reg & ~REG_MODE_ACF); ++ (mode_reg | REG_MODE_STM) : ++ (mode_reg & ~REG_MODE_STM); + + mode_reg = (mode->flags & CAN_CTRLMODE_FD_NON_ISO) ? + (mode_reg | REG_MODE_NISOFD) : diff --git a/queue-6.12/can-ems_usb-validate-cpc-message-lengths.patch b/queue-6.12/can-ems_usb-validate-cpc-message-lengths.patch new file mode 100644 index 0000000000..e145f8f4d6 --- /dev/null +++ b/queue-6.12/can-ems_usb-validate-cpc-message-lengths.patch @@ -0,0 +1,85 @@ +From 02925f51377f2a42a6724f00549167499c9302e5 Mon Sep 17 00:00:00 2001 +From: Pengpeng Hou +Date: Mon, 6 Jul 2026 17:27:52 +0800 +Subject: can: ems_usb: validate CPC message lengths + +From: Pengpeng Hou + +commit 02925f51377f2a42a6724f00549167499c9302e5 upstream. + +ems_usb_read_bulk_callback() walks CPC messages packed in one USB +receive buffer. + +Check that each declared message fits in the URB payload. Also require the +type-specific payload to cover the fields used by the CAN, state, error and +overrun handlers. + +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706092752.79600-1-pengpeng@iscas.ac.cn +Fixes: 702171adeed3 ("ems_usb: Added support for EMS CPC-USB/ARM7 CAN/USB interface") +Cc: stable@vger.kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/ems_usb.c | 43 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 43 insertions(+) + +--- a/drivers/net/can/usb/ems_usb.c ++++ b/drivers/net/can/usb/ems_usb.c +@@ -409,6 +409,40 @@ static void ems_usb_rx_err(struct ems_us + netif_rx(skb); + } + ++static bool ems_usb_rx_msg_len_valid(struct ems_cpc_msg *msg) ++{ ++ size_t len = msg->length; ++ size_t can_len; ++ ++ switch (msg->type) { ++ case CPC_MSG_TYPE_CAN_STATE: ++ return len >= sizeof(msg->msg.can_state); ++ ++ case CPC_MSG_TYPE_CAN_FRAME: ++ case CPC_MSG_TYPE_EXT_CAN_FRAME: ++ case CPC_MSG_TYPE_RTR_FRAME: ++ case CPC_MSG_TYPE_EXT_RTR_FRAME: ++ if (len < CPC_CAN_MSG_MIN_SIZE) ++ return false; ++ ++ if (msg->type == CPC_MSG_TYPE_RTR_FRAME || ++ msg->type == CPC_MSG_TYPE_EXT_RTR_FRAME) ++ return true; ++ ++ can_len = can_cc_dlc2len(msg->msg.can_msg.length & 0xf); ++ return len >= CPC_CAN_MSG_MIN_SIZE + can_len; ++ ++ case CPC_MSG_TYPE_CAN_FRAME_ERROR: ++ return len >= sizeof(msg->msg.error); ++ ++ case CPC_MSG_TYPE_OVERRUN: ++ return len >= sizeof(msg->msg.overrun); ++ ++ default: ++ return true; ++ } ++} ++ + /* + * callback for bulk IN urb + */ +@@ -451,6 +485,15 @@ static void ems_usb_read_bulk_callback(s + } + + msg = (struct ems_cpc_msg *)&ibuf[start]; ++ if (msg->length > ++ urb->actual_length - start - CPC_MSG_HEADER_LEN) { ++ netdev_err(netdev, "format error\n"); ++ break; ++ } ++ if (!ems_usb_rx_msg_len_valid(msg)) { ++ netdev_err(netdev, "format error\n"); ++ break; ++ } + + switch (msg->type) { + case CPC_MSG_TYPE_CAN_STATE: diff --git a/queue-6.12/can-etas_es58x-es58x_read_bulk_callback-fix-rx-buffer-leak-on-urb-resubmit-failure.patch b/queue-6.12/can-etas_es58x-es58x_read_bulk_callback-fix-rx-buffer-leak-on-urb-resubmit-failure.patch new file mode 100644 index 0000000000..49857a0e38 --- /dev/null +++ b/queue-6.12/can-etas_es58x-es58x_read_bulk_callback-fix-rx-buffer-leak-on-urb-resubmit-failure.patch @@ -0,0 +1,41 @@ +From 7a0cf2b2497c757c3cb1286eddf2986abb0d387b Mon Sep 17 00:00:00 2001 +From: Guangshuo Li +Date: Mon, 6 Jul 2026 09:46:01 +0800 +Subject: can: etas_es58x: es58x_read_bulk_callback(): fix RX buffer leak on URB resubmit failure + +From: Guangshuo Li + +commit 7a0cf2b2497c757c3cb1286eddf2986abb0d387b upstream. + +es58x_read_bulk_callback() resubmits the RX URB after processing a received +packet. If the resubmit succeeds, the URB remains anchored and will be +handled by the normal RX path or by teardown. + +However, if usb_submit_urb() fails, the callback unanchors the URB and then +returns directly. This skips the existing free_urb path, so the coherent +transfer buffer allocated with usb_alloc_coherent() is not released. + +Reuse the existing free_urb path after a resubmit failure so that the RX +coherent buffer is freed before leaving the callback. + +Fixes: 5eaad4f76826 ("can: usb: etas_es58x: correctly anchor the urb in the read bulk callback") +Signed-off-by: Guangshuo Li +Reviewed-by: Vincent Mailhol +Link: https://patch.msgid.link/20260706014601.415445-1-lgs201920130244@gmail.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/etas_es58x/es58x_core.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/can/usb/etas_es58x/es58x_core.c ++++ b/drivers/net/can/usb/etas_es58x/es58x_core.c +@@ -1476,7 +1476,6 @@ static void es58x_read_bulk_callback(str + dev_err_ratelimited(dev, + "Failed resubmitting read bulk urb: %pe\n", + ERR_PTR(ret)); +- return; + + free_urb: + usb_free_coherent(urb->dev, urb->transfer_buffer_length, diff --git a/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-resubmit-urb-on-skb-allocation-failure.patch b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-resubmit-urb-on-skb-allocation-failure.patch new file mode 100644 index 0000000000..785dd5f2bc --- /dev/null +++ b/queue-6.12/can-gs_usb-gs_usb_receive_bulk_callback-resubmit-urb-on-skb-allocation-failure.patch @@ -0,0 +1,49 @@ +From 68c5724ecd159992f76edb7b57dc508a44c8b7da Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Thu, 9 Jul 2026 09:54:26 +0200 +Subject: can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure + +From: Marc Kleine-Budde + +commit 68c5724ecd159992f76edb7b57dc508a44c8b7da upstream. + +If the allocation of the SKB in gs_usb_receive_bulk_callback() fails, the +driver returns from the callback without resubmitting the URB in order to +receive further USB in URBs. + +This results in a silent performance degradation which, if it occurs +repeatedly, results in starvation of USB in traffic. + +Instead of returning immediately, try to resend the URB. If this also +fails, this is logged as an info message. + +Fixes: d08e973a77d1 ("can: gs_usb: Added support for the GS_USB CAN devices") +Fixes: 26949ac935e3 ("can: gs_usb: add CAN-FD support") +Link: https://patch.msgid.link/20260709-gs_usb-resubmit-urb-v1-1-4dd40030cc84@pengutronix.de +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/gs_usb.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/usb/gs_usb.c ++++ b/drivers/net/can/usb/gs_usb.c +@@ -671,7 +671,7 @@ static void gs_usb_receive_bulk_callback + if (hf->flags & GS_CAN_FLAG_FD) { + skb = alloc_canfd_skb(netdev, &cfd); + if (!skb) +- return; ++ goto resubmit_urb; + + cfd->can_id = le32_to_cpu(hf->can_id); + cfd->len = data_length; +@@ -684,7 +684,7 @@ static void gs_usb_receive_bulk_callback + } else { + skb = alloc_can_skb(netdev, &cf); + if (!skb) +- return; ++ goto resubmit_urb; + + cf->can_id = le32_to_cpu(hf->can_id); + can_frame_set_cc_len(cf, hf->can_dlc, dev->can.ctrlmode); diff --git a/queue-6.12/can-j1939-transport-j1939_session_fresh_new-initialize-receive-buffer.patch b/queue-6.12/can-j1939-transport-j1939_session_fresh_new-initialize-receive-buffer.patch new file mode 100644 index 0000000000..f7ffa8e0f7 --- /dev/null +++ b/queue-6.12/can-j1939-transport-j1939_session_fresh_new-initialize-receive-buffer.patch @@ -0,0 +1,40 @@ +From eb96c58907922546e415e545fe9a14ea63b02719 Mon Sep 17 00:00:00 2001 +From: Oleksij Rempel +Date: Tue, 28 Jul 2026 07:58:35 +0200 +Subject: can: j1939: transport: j1939_session_fresh_new(): initialize receive buffer + +From: Oleksij Rempel + +commit eb96c58907922546e415e545fe9a14ea63b02719 upstream. + +Zero the allocated buffer in j1939_session_fresh_new() to ensure it +contains no residual data. + +While there is a potential performance impact if users allocate maximum +sized ETP buffers, most real-world use cases are not noticeably affected +since the maximum known buffer size is typically around 65K. + +Fixes: 9d71dd0c7009 ("can: add support of SAE J1939 protocol") +Reported-by: Ji'an Zhou +Message-ID: +Signed-off-by: Oleksij Rempel +Link: https://patch.msgid.link/20260728055835.1151785-3-o.rempel@pengutronix.de +Cc: stable@kernel.org +[mkl: add Message-ID] +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/j1939/transport.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -1562,7 +1562,7 @@ j1939_session *j1939_session_fresh_new(s + } + + /* alloc data area */ +- skb_put(skb, size); ++ skb_put_zero(skb, size); + /* skb is recounted in j1939_session_new() */ + return session; + } diff --git a/queue-6.12/can-j1939-use-netdevice_tracker-for-j1939_-priv-session-ecu-tracking.patch b/queue-6.12/can-j1939-use-netdevice_tracker-for-j1939_-priv-session-ecu-tracking.patch new file mode 100644 index 0000000000..e8c0a2583d --- /dev/null +++ b/queue-6.12/can-j1939-use-netdevice_tracker-for-j1939_-priv-session-ecu-tracking.patch @@ -0,0 +1,162 @@ +From d2fb981384b3a45f690616d550b29046e8ad16a4 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Tue, 28 Jul 2026 07:58:34 +0200 +Subject: can: j1939: use netdevice_tracker for j1939_{priv,session,ecu} tracking + +From: Tetsuo Handa + +commit d2fb981384b3a45f690616d550b29046e8ad16a4 upstream. + +syzbot is still reporting + + unregister_netdevice: waiting for vcan0 to become free. Usage count = 2 + +problem. A debug printk() patch in linux-next-20260508 identified that +there is dev_hold()/dev_put() imbalance in j1939_priv management. + + Call trace for vcan0[26] +4 at + __dev_hold include/linux/netdevice.h:4470 [inline] + netdev_hold include/linux/netdevice.h:4513 [inline] + dev_hold include/linux/netdevice.h:4536 [inline] + j1939_priv_create net/can/j1939/main.c:140 [inline] + j1939_netdev_start+0x36b/0xc10 net/can/j1939/main.c:268 + j1939_sk_bind+0x853/0xb30 net/can/j1939/socket.c:506 + __sys_bind_socket net/socket.c:1948 [inline] + __sys_bind+0x2e9/0x410 net/socket.c:1979 + + Call trace for vcan0[28] -3 at + __dev_put include/linux/netdevice.h:4456 [inline] + netdev_put include/linux/netdevice.h:4523 [inline] + dev_put include/linux/netdevice.h:4548 [inline] + __j1939_priv_release net/can/j1939/main.c:166 [inline] + kref_put include/linux/kref.h:65 [inline] + j1939_priv_put+0x128/0x270 net/can/j1939/main.c:172 + j1939_sk_sock_destruct+0x52/0x90 net/can/j1939/socket.c:388 + __sk_destruct+0x8d/0x9d0 net/core/sock.c:2352 + rcu_do_batch kernel/rcu/tree.c:2617 [inline] + rcu_core kernel/rcu/tree.c:2869 [inline] + rcu_cpu_kthread+0x99e/0x1470 kernel/rcu/tree.c:2957 + smpboot_thread_fn+0x541/0xa50 kernel/smpboot.c:160 + kthread+0x388/0x470 kernel/kthread.c:436 + ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158 + ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 + +This refcount leak in j1939_priv might be caused by a refcount leak in +j1939_{session,ecu} because j1939_{session,ecu} holds a ref on j1939_priv. +For further investigation using upstream kernels, enable netdevice_tracker +in j1939_{priv,session,ecu} management. + +Signed-off-by: Tetsuo Handa +Acked-by: Oleksij Rempel +Signed-off-by: Oleksij Rempel +Link: https://patch.msgid.link/20260728055835.1151785-2-o.rempel@pengutronix.de +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + net/can/j1939/bus.c | 2 ++ + net/can/j1939/j1939-priv.h | 3 +++ + net/can/j1939/main.c | 8 ++++---- + net/can/j1939/transport.c | 2 ++ + 4 files changed, 11 insertions(+), 4 deletions(-) + +--- a/net/can/j1939/bus.c ++++ b/net/can/j1939/bus.c +@@ -20,6 +20,7 @@ static void __j1939_ecu_release(struct k + struct j1939_priv *priv = ecu->priv; + + list_del(&ecu->list); ++ netdev_put(priv->ndev, &ecu->priv_dev_tracker); + kfree(ecu); + j1939_priv_put(priv); + } +@@ -155,6 +156,7 @@ struct j1939_ecu *j1939_ecu_create_locke + if (!ecu) + return ERR_PTR(-ENOMEM); + kref_init(&ecu->kref); ++ netdev_hold(priv->ndev, &ecu->priv_dev_tracker, gfp_any()); + ecu->addr = J1939_IDLE_ADDR; + ecu->name = name; + +--- a/net/can/j1939/j1939-priv.h ++++ b/net/can/j1939/j1939-priv.h +@@ -38,6 +38,7 @@ struct j1939_ecu { + struct hrtimer ac_timer; + struct kref kref; + struct j1939_priv *priv; ++ netdevice_tracker priv_dev_tracker; + + /* count users, to help transport protocol decide for interaction */ + int nusers; +@@ -60,6 +61,7 @@ struct j1939_priv { + rwlock_t lock; + + struct net_device *ndev; ++ netdevice_tracker dev_tracker; + + /* list of 256 ecu ptrs, that cache the claimed addresses. + * also protected by the above lock +@@ -229,6 +231,7 @@ enum j1939_session_state { + + struct j1939_session { + struct j1939_priv *priv; ++ netdevice_tracker priv_dev_tracker; + struct list_head active_session_list_entry; + struct list_head sk_session_queue_entry; + struct kref kref; +--- a/net/can/j1939/main.c ++++ b/net/can/j1939/main.c +@@ -137,7 +137,7 @@ static struct j1939_priv *j1939_priv_cre + priv->ndev = ndev; + kref_init(&priv->kref); + kref_init(&priv->rx_kref); +- dev_hold(ndev); ++ netdev_hold(ndev, &priv->dev_tracker, GFP_KERNEL); + + netdev_dbg(priv->ndev, "%s : 0x%p\n", __func__, priv); + +@@ -163,7 +163,7 @@ static void __j1939_priv_release(struct + WARN_ON_ONCE(!list_empty(&priv->ecus)); + WARN_ON_ONCE(!list_empty(&priv->j1939_socks)); + +- dev_put(ndev); ++ netdev_put(ndev, &priv->dev_tracker); + kfree(priv); + } + +@@ -281,7 +281,7 @@ struct j1939_priv *j1939_netdev_start(st + */ + kref_get(&priv_new->rx_kref); + mutex_unlock(&j1939_netdev_lock); +- dev_put(ndev); ++ netdev_put(ndev, &priv->dev_tracker); + kfree(priv); + return priv_new; + } +@@ -298,7 +298,7 @@ struct j1939_priv *j1939_netdev_start(st + j1939_priv_set(ndev, NULL); + mutex_unlock(&j1939_netdev_lock); + +- dev_put(ndev); ++ netdev_put(ndev, &priv->dev_tracker); + kfree(priv); + + return ERR_PTR(ret); +--- a/net/can/j1939/transport.c ++++ b/net/can/j1939/transport.c +@@ -282,6 +282,7 @@ static void j1939_session_destroy(struct + kfree_skb(skb); + } + __j1939_session_drop(session); ++ netdev_put(session->priv->ndev, &session->priv_dev_tracker); + j1939_priv_put(session->priv); + kfree(session); + } +@@ -1510,6 +1511,7 @@ static struct j1939_session *j1939_sessi + INIT_LIST_HEAD(&session->active_session_list_entry); + INIT_LIST_HEAD(&session->sk_session_queue_entry); + kref_init(&session->kref); ++ netdev_hold(priv->ndev, &session->priv_dev_tracker, gfp_any()); + + j1939_priv_get(priv); + session->priv = priv; diff --git a/queue-6.12/can-kvaser_usb-kvaser_usb_hydra_get_busparams-fix-memory-leak-in-kvaser_usb_hydra_get_busparams.patch b/queue-6.12/can-kvaser_usb-kvaser_usb_hydra_get_busparams-fix-memory-leak-in-kvaser_usb_hydra_get_busparams.patch new file mode 100644 index 0000000000..999a591c57 --- /dev/null +++ b/queue-6.12/can-kvaser_usb-kvaser_usb_hydra_get_busparams-fix-memory-leak-in-kvaser_usb_hydra_get_busparams.patch @@ -0,0 +1,33 @@ +From 941eaf9a6d3b33dea49f2c0a1da7546a03b6ff71 Mon Sep 17 00:00:00 2001 +From: Abdun Nihaal +Date: Wed, 22 Jul 2026 16:09:03 +0530 +Subject: can: kvaser_usb: kvaser_usb_hydra_get_busparams(): fix memory leak in kvaser_usb_hydra_get_busparams() + +From: Abdun Nihaal + +commit 941eaf9a6d3b33dea49f2c0a1da7546a03b6ff71 upstream. + +The memory allocated for cmd is not freed after the call to +kvaser_usb_send_cmd() in both the normal and error paths. +Fix that by adding a kfree() immediately after the call. + +Fixes: 39d3df6b0ea8 ("can: kvaser_usb: Compare requested bittiming parameters with actual parameters in do_set_{,data}_bittiming") +Cc: stable@vger.kernel.org +Signed-off-by: Abdun Nihaal +Link: https://patch.msgid.link/20260722103906.108571-1-nihaal@cse.iitm.ac.in +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +@@ -1625,6 +1625,7 @@ static int kvaser_usb_hydra_get_busparam + reinit_completion(&priv->get_busparams_comp); + + err = kvaser_usb_send_cmd(dev, cmd, cmd_len); ++ kfree(cmd); + if (err) + return err; + diff --git a/queue-6.12/can-kvaser_usb_leaf-kvaser_usb_leaf_wait_cmd-validate-received-command-extents.patch b/queue-6.12/can-kvaser_usb_leaf-kvaser_usb_leaf_wait_cmd-validate-received-command-extents.patch new file mode 100644 index 0000000000..51d91b9180 --- /dev/null +++ b/queue-6.12/can-kvaser_usb_leaf-kvaser_usb_leaf_wait_cmd-validate-received-command-extents.patch @@ -0,0 +1,63 @@ +From 0293dd153f9dbc1ddf5dacdccc76b363bce4a8ee Mon Sep 17 00:00:00 2001 +From: Pengpeng Hou +Date: Wed, 22 Jul 2026 12:22:21 +0800 +Subject: can: kvaser_usb_leaf: kvaser_usb_leaf_wait_cmd(): validate received command extents + +From: Pengpeng Hou + +commit 0293dd153f9dbc1ddf5dacdccc76b363bce4a8ee upstream. + +The wait and bulk receive paths walk variable-length commands from a +USB buffer. A nonzero command shorter than CMD_HEADER_LEN can still be +dispatched, and the wait path copies a matching command into a fixed +caller-owned struct kvaser_cmd using the device-provided length. + +Reject nonzero commands that do not contain the fixed header or that +extend beyond the current USB buffer item. In the wait path, also reject +a matching command that exceeds the destination before copying it. + +Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260722042221.44066-1-pengpeng@iscas.ac.cn +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c ++++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c +@@ -668,13 +668,22 @@ static int kvaser_usb_leaf_wait_cmd(cons + continue; + } + +- if (pos + tmp->len > actual_len) { ++ if (tmp->len < CMD_HEADER_LEN || ++ tmp->len > actual_len - pos) { + dev_err_ratelimited(&dev->intf->dev, + "Format error\n"); + break; + } + + if (tmp->id == id) { ++ if (tmp->len > sizeof(*cmd)) { ++ dev_err_ratelimited(&dev->intf->dev, ++ "Received command %u too large (%u)\n", ++ tmp->id, tmp->len); ++ err = -EIO; ++ goto end; ++ } ++ + memcpy(cmd, tmp, tmp->len); + goto end; + } +@@ -1677,7 +1686,7 @@ static void kvaser_usb_leaf_read_bulk_ca + continue; + } + +- if (pos + cmd->len > len) { ++ if (cmd->len < CMD_HEADER_LEN || cmd->len > len - pos) { + dev_err_ratelimited(&dev->intf->dev, "Format error\n"); + break; + } diff --git a/queue-6.12/can-peak_usb-add-bounds-check-for-usb-channel-index.patch b/queue-6.12/can-peak_usb-add-bounds-check-for-usb-channel-index.patch new file mode 100644 index 0000000000..b6e0390f40 --- /dev/null +++ b/queue-6.12/can-peak_usb-add-bounds-check-for-usb-channel-index.patch @@ -0,0 +1,74 @@ +From 39132f166ca8ce00ae60d8a9068e06a60943cc4b Mon Sep 17 00:00:00 2001 +From: James Gao +Date: Wed, 20 May 2026 13:40:03 +0800 +Subject: can: peak_usb: add bounds check for USB channel index + +From: James Gao + +commit 39132f166ca8ce00ae60d8a9068e06a60943cc4b upstream. + +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. + +Add bounds checking for ctrl_idx before the array access in both +pcan_usb_pro_handle_canmsg() and pcan_usb_pro_handle_error(). + +Fixes: d8a199355f8f ("can: usb: PEAK-System Technik PCAN-USB Pro specific part") +Signed-off-by: James Gao +Reviewed-by: Vincent Mailhol +Link: https://patch.msgid.link/TYWPR01MB8559DBAAAA6A7F410400329CF0012@TYWPR01MB8559.jpnprd01.prod.outlook.com +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 20 ++++++++++++++++---- + 1 file changed, 16 insertions(+), 4 deletions(-) + +--- 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(st + 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; ++ + skb = alloc_can_skb(netdev, &can_frame); + if (!skb) + return -ENOMEM; +@@ -573,14 +579,20 @@ static int pcan_usb_pro_handle_error(str + { + 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; diff --git a/queue-6.12/can-peak_usb-peak_usb_start-fix-double-free-of-transfer-buffer-on-urb-submit-error.patch b/queue-6.12/can-peak_usb-peak_usb_start-fix-double-free-of-transfer-buffer-on-urb-submit-error.patch new file mode 100644 index 0000000000..f46e989045 --- /dev/null +++ b/queue-6.12/can-peak_usb-peak_usb_start-fix-double-free-of-transfer-buffer-on-urb-submit-error.patch @@ -0,0 +1,51 @@ +From 9b3d5a6d952c38bbcf07f903cbeadefdb56b9bc9 Mon Sep 17 00:00:00 2001 +From: Maoyi Xie +Date: Wed, 17 Jun 2026 02:15:31 +0800 +Subject: can: peak_usb: peak_usb_start(): fix double free of transfer buffer on URB submit error + +From: Maoyi Xie + +commit 9b3d5a6d952c38bbcf07f903cbeadefdb56b9bc9 upstream. + +In peak_usb_start(), each RX URB transfer buffer is allocated with kmalloc() +and the URB is flagged URB_FREE_BUFFER so that the final usb_free_urb() also +frees the transfer buffer. + +If usb_submit_urb() fails, the error path frees the buffer explicitly with +kfree(buf) and then calls usb_free_urb(urb). Because URB_FREE_BUFFER is set, +usb_free_urb() -> urb_destroy() frees the same buffer a second time, a double +free of the transfer buffer. + + BUG: KASAN: double-free in usb_free_urb.part.0+0x91/0xb0 + Free of addr ffff8881069ccb80 by task trigger.sh/285 + + Call Trace: + kfree+0x113/0x3c0 + usb_free_urb.part.0+0x91/0xb0 + +Drop the redundant kfree(buf); usb_free_urb() already releases the transfer +buffer. This mirrors commit 03819abbeb11 ("net: usb: lan78xx: Fix double free +issue with interrupt buffer allocation"). + +Fixes: bb4785551f64 ("can: usb: PEAK-System Technik USB adapters driver core") +Closes: https://lore.kernel.org/linux-can/178159320216.2154888.16953451793788581739@maoyixie.com/T/#u +Cc: stable@vger.kernel.org +Signed-off-by: Maoyi Xie +Reviewed-by: Vincent Mailhol +Link: https://patch.msgid.link/178163373110.2507866.216458825145756798@maoyixie.com +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/peak_usb/pcan_usb_core.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c +@@ -470,7 +470,6 @@ static int peak_usb_start(struct peak_us + netif_device_detach(dev->netdev); + + usb_unanchor_urb(urb); +- kfree(buf); + usb_free_urb(urb); + break; + } diff --git a/queue-6.12/can-peak_usb-validate-ucan-receive-record-lengths.patch b/queue-6.12/can-peak_usb-validate-ucan-receive-record-lengths.patch new file mode 100644 index 0000000000..78709d7337 --- /dev/null +++ b/queue-6.12/can-peak_usb-validate-ucan-receive-record-lengths.patch @@ -0,0 +1,100 @@ +From 93fcab2c6968446316bbb49548848df604d6346f Mon Sep 17 00:00:00 2001 +From: Pengpeng Hou +Date: Mon, 6 Jul 2026 17:28:36 +0800 +Subject: can: peak_usb: validate uCAN receive record lengths + +From: Pengpeng Hou + +commit 93fcab2c6968446316bbb49548848df604d6346f upstream. + +pcan_usb_fd_decode_buf() walks uCAN records packed in one USB +receive buffer. + +Require each record to contain the fixed header for its type, and verify +CAN payload bytes before copying them into the skb. + +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260706092836.79754-1-pengpeng@iscas.ac.cn +Fixes: 0a25e1f4f185 ("can: peak_usb: add support for PEAK new CANFD USB adapters") +Cc: stable@vger.kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 40 ++++++++++++++++++++++++++++- + 1 file changed, 39 insertions(+), 1 deletion(-) + +--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c ++++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c +@@ -565,6 +565,13 @@ static int pcan_usb_fd_decode_canmsg(str + dev->can.ctrlmode); + } + ++ if (!(rx_msg_flags & PUCAN_MSG_RTR) && ++ le16_to_cpu(rx_msg->size) - offsetof(struct pucan_rx_msg, d) < ++ cfd->len) { ++ kfree_skb(skb); ++ return -EBADMSG; ++ } ++ + cfd->can_id = le32_to_cpu(rm->can_id); + + if (rx_msg_flags & PUCAN_MSG_EXT_ID) +@@ -713,6 +720,24 @@ static void pcan_usb_fd_decode_ts(struct + peak_usb_set_ts_now(&usb_if->time_ref, le32_to_cpu(ts->ts_low)); + } + ++static size_t pcan_usb_fd_rx_msg_min_size(u16 rx_msg_type) ++{ ++ switch (rx_msg_type) { ++ case PUCAN_MSG_CAN_RX: ++ return offsetof(struct pucan_rx_msg, d); ++ case PCAN_UFD_MSG_CALIBRATION: ++ return sizeof(struct pcan_ufd_ts_msg); ++ case PUCAN_MSG_ERROR: ++ return sizeof(struct pucan_error_msg); ++ case PUCAN_MSG_STATUS: ++ return sizeof(struct pucan_status_msg); ++ case PCAN_UFD_MSG_OVERRUN: ++ return sizeof(struct pcan_ufd_ovr_msg); ++ default: ++ return sizeof(struct pucan_msg); ++ } ++} ++ + /* callback for bulk IN urb */ + static int pcan_usb_fd_decode_buf(struct peak_usb_device *dev, struct urb *urb) + { +@@ -727,6 +752,12 @@ static int pcan_usb_fd_decode_buf(struct + msg_end = urb->transfer_buffer + urb->actual_length; + for (; msg_ptr < msg_end;) { + u16 rx_msg_type, rx_msg_size; ++ size_t rx_msg_min_size; ++ ++ if (msg_end - msg_ptr < sizeof(*rx_msg)) { ++ err = -EBADMSG; ++ break; ++ } + + rx_msg = (struct pucan_msg *)msg_ptr; + if (!rx_msg->size) { +@@ -738,12 +769,19 @@ static int pcan_usb_fd_decode_buf(struct + rx_msg_type = le16_to_cpu(rx_msg->type); + + /* check if the record goes out of current packet */ +- if (msg_ptr + rx_msg_size > msg_end) { ++ if (rx_msg_size > msg_end - msg_ptr) { + netdev_err(netdev, + "got frag rec: should inc usb rx buf sze\n"); + err = -EBADMSG; + break; + } ++ ++ rx_msg_min_size = pcan_usb_fd_rx_msg_min_size(rx_msg_type); ++ if (rx_msg_size < rx_msg_min_size) { ++ netdev_err(netdev, "got short rec\n"); ++ err = -EBADMSG; ++ break; ++ } + + switch (rx_msg_type) { + case PUCAN_MSG_CAN_RX: diff --git a/queue-6.12/can-softing-fw_parse-validate-firmware-record-spans.patch b/queue-6.12/can-softing-fw_parse-validate-firmware-record-spans.patch new file mode 100644 index 0000000000..d71f570d8b --- /dev/null +++ b/queue-6.12/can-softing-fw_parse-validate-firmware-record-spans.patch @@ -0,0 +1,158 @@ +From 856d6cb04e5407523566b075841dcd6423757d1c Mon Sep 17 00:00:00 2001 +From: Pengpeng Hou +Date: Wed, 22 Jul 2026 12:43:47 +0800 +Subject: can: softing: fw_parse(): validate firmware record spans + +From: Pengpeng Hou + +commit 856d6cb04e5407523566b075841dcd6423757d1c upstream. + +fw_parse() reads a fixed record header, a firmware-provided payload, +and a trailing checksum without knowing the end of the firmware blob. A +truncated record can therefore make those reads exceed the blob. + +The same record also supplies addresses and lengths for writes into +DPRAM. The generic loader uses wrap-prone mixed signed arithmetic for its +bounds check, while the application loader does not bound the staging +copy at all. + +Pass the firmware end to the parser and validate the full source record. +Use a signed wide offset for generic DPRAM records and validate the +application staging span against the mapped DPRAM before copying. + +Fixes: 03fd3cf5a179 ("can: add driver for Softing card") +Signed-off-by: Pengpeng Hou +Link: https://patch.msgid.link/20260722044347.2708-1-pengpeng@iscas.ac.cn +Cc: stable@kernel.org +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/can/softing/softing_fw.c | 46 ++++++++++++++++++++++++----------- + 1 file changed, 32 insertions(+), 14 deletions(-) + +--- a/drivers/net/can/softing/softing_fw.c ++++ b/drivers/net/can/softing/softing_fw.c +@@ -91,12 +91,12 @@ int softing_bootloader_command(struct so + return ret; + } + +-static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr, +- uint16_t *plen, const uint8_t **pdat) ++static int fw_parse(const u8 **pmem, const u8 *limit, u16 *ptype, ++ u32 *paddr, u16 *plen, const u8 **pdat) + { + uint16_t checksum[2]; +- const uint8_t *mem; +- const uint8_t *end; ++ const u8 *mem; ++ const u8 *record_end; + + /* + * firmware records are a binary, unaligned stream composed of: +@@ -114,14 +114,21 @@ static int fw_parse(const uint8_t **pmem + * endianness & alignment. + */ + mem = *pmem; ++ /* A record needs an 8-byte prefix and a 2-byte checksum. */ ++ if (mem > limit || limit - mem < 10) ++ return -EINVAL; ++ + *ptype = le16_to_cpup((void *)&mem[0]); + *paddr = le32_to_cpup((void *)&mem[2]); + *plen = le16_to_cpup((void *)&mem[6]); ++ if (*plen > limit - mem - 10) ++ return -EINVAL; ++ + *pdat = &mem[8]; + /* verify checksum */ +- end = &mem[8 + *plen]; +- checksum[0] = le16_to_cpup((void *)end); +- for (checksum[1] = 0; mem < end; ++mem) ++ record_end = &mem[8 + *plen]; ++ checksum[0] = le16_to_cpup((void *)record_end); ++ for (checksum[1] = 0; mem < record_end; ++mem) + checksum[1] += *mem; + if (checksum[0] != checksum[1]) + return -EINVAL; +@@ -139,6 +146,7 @@ int softing_load_fw(const char *file, st + uint16_t type, len; + uint32_t addr; + uint8_t *buf = NULL, *new_buf; ++ s64 dpram_offset; + int buflen = 0; + int8_t type_end = 0; + +@@ -153,7 +161,7 @@ int softing_load_fw(const char *file, st + mem = fw->data; + end = &mem[fw->size]; + /* look for header record */ +- ret = fw_parse(&mem, &type, &addr, &len, &dat); ++ ret = fw_parse(&mem, end, &type, &addr, &len, &dat); + if (ret < 0) + goto failed; + if (type != 0xffff) +@@ -164,7 +172,7 @@ int softing_load_fw(const char *file, st + } + /* ok, we had a header */ + while (mem < end) { +- ret = fw_parse(&mem, &type, &addr, &len, &dat); ++ ret = fw_parse(&mem, end, &type, &addr, &len, &dat); + if (ret < 0) + goto failed; + if (type == 3) { +@@ -179,9 +187,13 @@ int softing_load_fw(const char *file, st + goto failed; + } + +- if ((addr + len + offset) > size) ++ dpram_offset = (s64)addr + offset; ++ if (dpram_offset < 0 || dpram_offset > size || ++ len > size - dpram_offset) { ++ ret = -EINVAL; + goto failed; +- memcpy_toio(&dpram[addr + offset], dat, len); ++ } ++ memcpy_toio(&dpram[dpram_offset], dat, len); + /* be sure to flush caches from IO space */ + mb(); + if (len > buflen) { +@@ -195,7 +207,7 @@ int softing_load_fw(const char *file, st + buf = new_buf; + } + /* verify record data */ +- memcpy_fromio(buf, &dpram[addr + offset], len); ++ memcpy_fromio(buf, &dpram[dpram_offset], len); + if (memcmp(buf, dat, len)) { + /* is not ok */ + dev_alert(&card->pdev->dev, "DPRAM readback failed\n"); +@@ -237,7 +249,7 @@ int softing_load_app_fw(const char *file + mem = fw->data; + end = &mem[fw->size]; + /* look for header record */ +- ret = fw_parse(&mem, &type, &addr, &len, &dat); ++ ret = fw_parse(&mem, end, &type, &addr, &len, &dat); + if (ret) + goto failed; + ret = -EINVAL; +@@ -253,7 +265,7 @@ int softing_load_app_fw(const char *file + } + /* ok, we had a header */ + while (mem < end) { +- ret = fw_parse(&mem, &type, &addr, &len, &dat); ++ ret = fw_parse(&mem, end, &type, &addr, &len, &dat); + if (ret) + goto failed; + +@@ -279,6 +291,12 @@ int softing_load_app_fw(const char *file + /* work in 16bit (target) */ + sum &= 0xffff; + ++ if (card->pdat->app.offs > card->dpram_size || ++ len > card->dpram_size - card->pdat->app.offs) { ++ ret = -EINVAL; ++ goto failed; ++ } ++ + memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len); + iowrite32(card->pdat->app.offs + card->pdat->app.addr, + &card->dpram[DPRAM_COMMAND + 2]); diff --git a/queue-6.12/drm-amd-display-add-av-mute-wait-frames-to-dce110_set_avmute.patch b/queue-6.12/drm-amd-display-add-av-mute-wait-frames-to-dce110_set_avmute.patch new file mode 100644 index 0000000000..9f497d460e --- /dev/null +++ b/queue-6.12/drm-amd-display-add-av-mute-wait-frames-to-dce110_set_avmute.patch @@ -0,0 +1,60 @@ +From 443290d70b01e9c35830c300e3247c06581b594c Mon Sep 17 00:00:00 2001 +From: Ray Wu +Date: Mon, 13 Jul 2026 22:23:34 +0800 +Subject: drm/amd/display: Add AV mute wait frames to dce110_set_avmute + +From: Ray Wu + +commit 443290d70b01e9c35830c300e3247c06581b594c upstream. + +Port the three-frame wait logic from dcn30_set_avmute to +dce110_set_avmute so that older DCN versions (1.0, 2.0) also +wait for GCP packets to be sent out before proceeding. + +This ensures HDMI sinks properly process the mute state, +preventing garbled display after link re-establishment. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5167 +Reviewed-by: Wayne Lin +Signed-off-by: Ray Wu +Signed-off-by: Fangzhi Zuo +Tested-by: Dan Wheeler +Signed-off-by: Alex Deucher +(cherry picked from commit 414da24137ace80d8c59fefd43ba3ec9f5f854ba) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c | 21 +++++++++++++- + 1 file changed, 20 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c ++++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +@@ -1256,8 +1256,27 @@ void dce110_blank_stream(struct pipe_ctx + + void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable) + { +- if (pipe_ctx != NULL && pipe_ctx->stream_res.stream_enc != NULL) ++ if (pipe_ctx == NULL || pipe_ctx->stream_res.stream_enc == NULL) ++ return; ++ ++ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) { + pipe_ctx->stream_res.stream_enc->funcs->set_avmute(pipe_ctx->stream_res.stream_enc, enable); ++ ++ /* Wait for three frames to make sure AV mute is sent out. ++ * Some HDMI sinks need additional GCP packets to properly ++ * process the mute state, especially after link re-establishment ++ * with HDMI 2.0 scrambling enabled. ++ */ ++ if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) { ++ int i; ++ ++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); ++ for (i = 0; i < 3; i++) { ++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK); ++ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE); ++ } ++ } ++ } + } + + static enum audio_dto_source translate_to_dto_source(enum controller_id crtc_id) diff --git a/queue-6.12/drm-amdgpu-cap-gtt-size-to-physical-ram-on-apus.patch b/queue-6.12/drm-amdgpu-cap-gtt-size-to-physical-ram-on-apus.patch new file mode 100644 index 0000000000..59514408ad --- /dev/null +++ b/queue-6.12/drm-amdgpu-cap-gtt-size-to-physical-ram-on-apus.patch @@ -0,0 +1,60 @@ +From 5e70f6804b4d6256058c360b10e044ee04ea4a4e Mon Sep 17 00:00:00 2001 +From: Harkirat Gill +Date: Mon, 27 Jul 2026 14:37:56 -0400 +Subject: drm/amdgpu: cap GTT size to physical RAM on APUs + +From: Harkirat Gill + +commit 5e70f6804b4d6256058c360b10e044ee04ea4a4e upstream. + +On APUs, the GTT pool is backed by system RAM, but its size is not bound +to the non-carveout memory that actually backs it. A user can end up +with GTT + VRAM exceeding total physical memory through the following +sequence: + + - Have a large non-carveout memory space (~128GB) and accordingly set a + large GTT (~100GB) via the ttm module parameter. + - Lower the non-carveout memory space in BIOS by increasing the UMA + Frame Buffer Size (VRAM) to 64GB. + - The previously set GTT value (~100GB) persists, even though the new + non-carveout space (64GB) can no longer back it. + +This leads to a case where kernel reports GTT (100GB) + VRAM (64GB) +despite the sum being greater than total physical memory (128GB). + +Cap the GTT size to totalram_pages() on APUs. totalram_pages() already +excludes the VRAM carveout, so the resulting GTT can never exceed the +system RAM that actually backs it. + +Signed-off-by: Harkirat Gill +Reviewed-by: David Francis +Assisted-by: Claude:claude-opus-4 +Signed-off-by: Alex Deucher +(cherry picked from commit 5dafdd649280c7dc6c22c8f877da3f54fcc441e1) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +@@ -1996,6 +1996,18 @@ int amdgpu_ttm_init(struct amdgpu_device + else + gtt_size = (uint64_t)amdgpu_gtt_size << 20; + ++ /* Cap GTT so that it does not exceed total physical RAM. */ ++ if (adev->flags & AMD_IS_APU) { ++ u64 phys_ram = (u64)totalram_pages() << PAGE_SHIFT; ++ ++ if (gtt_size > phys_ram) { ++ gtt_size = phys_ram; ++ dev_info(adev->dev, ++ "Capping GTT to %uM to not exceed available system memory\n", ++ (unsigned int)(gtt_size / (1024 * 1024))); ++ } ++ } ++ + /* Initialize GTT memory pool */ + r = amdgpu_gtt_mgr_init(adev, gtt_size); + if (r) { diff --git a/queue-6.12/drm-amdgpu-restore-umd-profile-pstate-after-runtime-resume.patch b/queue-6.12/drm-amdgpu-restore-umd-profile-pstate-after-runtime-resume.patch new file mode 100644 index 0000000000..9e8bd7d00b --- /dev/null +++ b/queue-6.12/drm-amdgpu-restore-umd-profile-pstate-after-runtime-resume.patch @@ -0,0 +1,55 @@ +From f931c54b241ce2f36bfc34955aec43a188276b8d Mon Sep 17 00:00:00 2001 +From: Candice Li +Date: Tue, 21 Jul 2026 21:38:58 +0800 +Subject: drm/amdgpu: restore UMD profile pstate after runtime resume + +From: Candice Li + +commit f931c54b241ce2f36bfc34955aec43a188276b8d upstream. + +Runtime suspend runs GFX hw_fini and clears perfmon clock gating while +the UMD profile DPM level remains set in software. Re-apply stable +pstate after a successful runtime resume when a profile mode is active. + +Signed-off-by: Candice Li +Reviewed-by: Hawking Zhang +Reviewed-by: Yang Wang +Signed-off-by: Alex Deucher +(cherry picked from commit 138531c8850cc247aa12b104bb29ea387bcdcbb1) +Cc: stable@vger.kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -2824,6 +2824,19 @@ static int amdgpu_pmops_runtime_suspend( + return 0; + } + ++static void amdgpu_restore_umd_profile_pstate_after_runpm(struct amdgpu_device *adev) ++{ ++ enum amd_dpm_forced_level level; ++ uint32_t profile_mode_mask = AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD | ++ AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK | ++ AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK | ++ AMD_DPM_FORCED_LEVEL_PROFILE_PEAK; ++ ++ level = amdgpu_dpm_get_performance_level(adev); ++ if (level & profile_mode_mask) ++ amdgpu_asic_update_umd_stable_pstate(adev, true); ++} ++ + static int amdgpu_pmops_runtime_resume(struct device *dev) + { + struct pci_dev *pdev = to_pci_dev(dev); +@@ -2868,6 +2881,8 @@ static int amdgpu_pmops_runtime_resume(s + + if (adev->pm.rpm_mode == AMDGPU_RUNPM_PX) + drm_dev->switch_power_state = DRM_SWITCH_POWER_ON; ++ ++ amdgpu_restore_umd_profile_pstate_after_runpm(adev); + adev->in_runpm = false; + return 0; + } diff --git a/queue-6.12/drm-dp-read-the-pcon-max-frl-bandwidth-only-for-hdmi-dfps.patch b/queue-6.12/drm-dp-read-the-pcon-max-frl-bandwidth-only-for-hdmi-dfps.patch new file mode 100644 index 0000000000..6ee8ed067b --- /dev/null +++ b/queue-6.12/drm-dp-read-the-pcon-max-frl-bandwidth-only-for-hdmi-dfps.patch @@ -0,0 +1,79 @@ +From e40e20ac089e32f1d910636155dc82e61e61dcf3 Mon Sep 17 00:00:00 2001 +From: Alexander Kaplan +Date: Wed, 10 Jun 2026 21:38:25 +0200 +Subject: drm/dp: Read the PCON max FRL bandwidth only for HDMI DFPs + +From: Alexander Kaplan + +commit e40e20ac089e32f1d910636155dc82e61e61dcf3 upstream. + +The PCON max FRL bandwidth field lives in byte 2 of the DFP Detailed +Capability Info (DPCD 0x82 for the first DFP). +The DP standard defines the meaning of descriptor bytes 1-3 strictly +per DFP type, and for a DisplayPort type DFP all of them are +reserved, with "read all 0s" semantics (DP v2.0, section 2.12.3, +Table 2-183). +The FRL bandwidth field is an HDMI DFP extension added by the VESA +DP-to-HDMI PCON specification. +drm_dp_get_pcon_max_frl_bw() however parses the byte without checking +the DFP type, the branch presence or DETAILED_CAP_INFO_AVAILABLE. +Without the latter the port descriptors are one byte wide and +port_cap[2] is not even the right register. + +All neighbouring helpers parsing the same descriptor are scoped by +the DFP type already, see for instance drm_dp_downstream_max_bpc() +reading the same byte and returning 0 for a DP type DFP. +amdgpu's DC parses the field only for HDMI(/DP++) detailed types as +well. + +This is not theoretical. +A Synaptics VMM7100 based USB-C to HDMI adapter with a macOS targeted +firmware advertises a DisplayPort type DFP with the type byte +replicated across the whole descriptor (08 08 08 08). +i915 decodes that as "PCON limited to 18 Gbps FRL" and prunes every +mode above ~750 MHz dotclock, including all the 4k@100/120 modes the +sink EDID offers, while macOS drives 4k@120 through the same adapter +just fine via DP DSC (and amdgpu's type-scoped parser would ignore +the bogus field as well). + +Only parse the field for an HDMI DFP behind a DPCD 1.1+ branch +device that reports detailed cap info, matching the type-scoped +field layout of the spec and the rest of the helpers. + +Fixes: ce32a6239de6 ("drm/dp_helper: Add Helpers for FRL Link Training support for DP-HDMI2.1 PCON") +Cc: Ankit Nautiyal +Cc: Uma Shankar (v2) +Cc: Jani Nikula +Cc: Maarten Lankhorst +Cc: dri-devel@lists.freedesktop.org +Cc: # v5.12+ +Signed-off-by: Alexander Kaplan +Reviewed-by: Ankit Nautiyal +Signed-off-by: Ankit Nautiyal +Link: https://patch.msgid.link/20260610193825.2933-1-alexander.kaplan@sms-medipool.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/display/drm_dp_helper.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +--- a/drivers/gpu/drm/display/drm_dp_helper.c ++++ b/drivers/gpu/drm/display/drm_dp_helper.c +@@ -3145,6 +3145,18 @@ int drm_dp_get_pcon_max_frl_bw(const u8 + int bw; + u8 buf; + ++ if (!drm_dp_is_branch(dpcd)) ++ return 0; ++ ++ if (dpcd[DP_DPCD_REV] < 0x11) ++ return 0; ++ ++ if ((dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) == 0) ++ return 0; ++ ++ if ((port_cap[0] & DP_DS_PORT_TYPE_MASK) != DP_DS_PORT_TYPE_HDMI) ++ return 0; ++ + buf = port_cap[2]; + bw = buf & DP_PCON_MAX_FRL_BW; + diff --git a/queue-6.12/drm-mediatek-ovl_adaptor-balance-component-registrations.patch b/queue-6.12/drm-mediatek-ovl_adaptor-balance-component-registrations.patch new file mode 100644 index 0000000000..e7388aff46 --- /dev/null +++ b/queue-6.12/drm-mediatek-ovl_adaptor-balance-component-registrations.patch @@ -0,0 +1,74 @@ +From 533e3469a57996905cdb95f178e7efe38c21aeb2 Mon Sep 17 00:00:00 2001 +From: Myeonghun Pak +Date: Wed, 22 Jul 2026 00:22:42 +0900 +Subject: drm/mediatek: ovl_adaptor: balance component registrations + +From: Myeonghun Pak + +commit 533e3469a57996905cdb95f178e7efe38c21aeb2 upstream. + +The OVL adaptor registers both an aggregate driver for its child devices +and a component for the main DRM aggregate. Probe currently ignores an +error from registering the child aggregate and leaves that aggregate +registered if registering the DRM component fails. The remove callback +also leaves the DRM component registered. + +These imbalances can leave component framework entries referring to a +device whose probe failed or whose driver has been detached. The aggregate +unbind callback also fails to undo component_bind_all(), leaving its child +components marked as bound when the aggregate is removed. + +Check the aggregate registration result, unwind it when the component +registration fails, and unregister the component before the aggregate on +remove. Keep runtime PM enabled until both framework registrations have +been removed, and unbind all child components from the aggregate unbind +callback. + +Fixes: 453c3364632a ("drm/mediatek: Add ovl_adaptor support for MT8195") +Cc: stable@vger.kernel.org # 6.4+ +Co-developed-by: Ijae Kim +Signed-off-by: Ijae Kim +Signed-off-by: Myeonghun Pak +Reviewed-by: CK Hu +Link: https://patchwork.kernel.org/project/linux-mediatek/patch/20260721152242.47138-1-mhun512@gmail.com/ +Signed-off-by: Chun-Kuang Hu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c ++++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c +@@ -585,6 +585,7 @@ static void mtk_disp_ovl_adaptor_master_ + struct mtk_disp_ovl_adaptor *priv = dev_get_drvdata(dev); + + priv->children_bound = false; ++ component_unbind_all(dev, priv->mmsys_dev); + } + + static const struct component_master_ops mtk_disp_ovl_adaptor_master_ops = { +@@ -611,12 +612,15 @@ static int mtk_disp_ovl_adaptor_probe(st + + priv->mmsys_dev = pdev->dev.platform_data; + +- component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match); ++ ret = component_master_add_with_match(dev, &mtk_disp_ovl_adaptor_master_ops, match); ++ if (ret) ++ return dev_err_probe(dev, ret, "Failed to add component master\n"); + + pm_runtime_enable(dev); + + ret = component_add(dev, &mtk_disp_ovl_adaptor_comp_ops); + if (ret != 0) { ++ component_master_del(dev, &mtk_disp_ovl_adaptor_master_ops); + pm_runtime_disable(dev); + return dev_err_probe(dev, ret, "Failed to add component\n"); + } +@@ -626,6 +630,7 @@ static int mtk_disp_ovl_adaptor_probe(st + + static void mtk_disp_ovl_adaptor_remove(struct platform_device *pdev) + { ++ component_del(&pdev->dev, &mtk_disp_ovl_adaptor_comp_ops); + component_master_del(&pdev->dev, &mtk_disp_ovl_adaptor_master_ops); + pm_runtime_disable(&pdev->dev); + } diff --git a/queue-6.12/drm-panthor-reject-firmware-sections-with-oversized-data.patch b/queue-6.12/drm-panthor-reject-firmware-sections-with-oversized-data.patch new file mode 100644 index 0000000000..cbba0bf082 --- /dev/null +++ b/queue-6.12/drm-panthor-reject-firmware-sections-with-oversized-data.patch @@ -0,0 +1,81 @@ +From a3caaa06809248b996254be5b47e10804a3494e2 Mon Sep 17 00:00:00 2001 +From: Osama Abdelkader +Date: Thu, 16 Jul 2026 16:39:38 +0200 +Subject: drm/panthor: reject firmware sections with oversized data + +From: Osama Abdelkader + +commit a3caaa06809248b996254be5b47e10804a3494e2 upstream. + +In panthor_fw_load_section_entry(), the data size to copy is calculated +without validating it against the allocated section_size: + + section->data.size = hdr.data.end - hdr.data.start; + +If a crafted firmware sets data.size larger than the allocated memory, +this could cause a heap buffer overflow in panthor_fw_init_section_mem() + + memcpy(section->mem->kmap, section->data.buf, section->data.size); + +Additionally, if the section->data.size exceeds the BO size, could this +memset underflow the size calculation, leading to a massive out-of-bounds +zeroing of kernel memory? + + memset(section->mem->kmap + section->data.size, 0, + panthor_kernel_bo_size(section->mem) - section->data.size); + +Reject section entries whose initial data is larger than the section size. + +Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block") +Cc: stable@vger.kernel.org +Signed-off-by: Osama Abdelkader +Reviewed-by: Steven Price +Reviewed-by: Boris Brezillon +Link: https://patch.msgid.link/20260716143939.21903-1-osama.abdelkader@gmail.com +Signed-off-by: Steven Price +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/panthor/panthor_fw.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +--- a/drivers/gpu/drm/panthor/panthor_fw.c ++++ b/drivers/gpu/drm/panthor/panthor_fw.c +@@ -491,6 +491,7 @@ static int panthor_fw_load_section_entry + struct panthor_fw_binary_section_entry_hdr hdr; + struct panthor_fw_section *section; + u32 section_size; ++ u32 data_size; + u32 name_len; + int ret; + +@@ -541,6 +542,13 @@ static int panthor_fw_load_section_entry + return -EINVAL; + } + ++ section_size = hdr.va.end - hdr.va.start; ++ data_size = hdr.data.end - hdr.data.start; ++ if (data_size > section_size) { ++ drm_err(&ptdev->base, "Firmware corrupted, section data exceeds section size\n"); ++ return -EINVAL; ++ } ++ + name_len = iter->size - iter->offset; + + section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL); +@@ -549,7 +557,7 @@ static int panthor_fw_load_section_entry + + list_add_tail(§ion->node, &ptdev->fw->sections); + section->flags = hdr.flags; +- section->data.size = hdr.data.end - hdr.data.start; ++ section->data.size = data_size; + + if (section->data.size > 0) { + void *data = drmm_kmalloc(&ptdev->base, section->data.size, GFP_KERNEL); +@@ -572,7 +580,6 @@ static int panthor_fw_load_section_entry + section->name = name; + } + +- section_size = hdr.va.end - hdr.va.start; + if (section_size) { + u32 cache_mode = hdr.flags & CSF_FW_BINARY_IFACE_ENTRY_RD_CACHE_MODE_MASK; + struct panthor_gem_object *bo; diff --git a/queue-6.12/drm-panthor-validate-firmware-interface-structure-sizes.patch b/queue-6.12/drm-panthor-validate-firmware-interface-structure-sizes.patch new file mode 100644 index 0000000000..0f7714e56c --- /dev/null +++ b/queue-6.12/drm-panthor-validate-firmware-interface-structure-sizes.patch @@ -0,0 +1,100 @@ +From b921b8613790a3f9e78ab64017fa7149ef0b750c Mon Sep 17 00:00:00 2001 +From: Osama Abdelkader +Date: Mon, 20 Jul 2026 13:49:17 +0200 +Subject: drm/panthor: validate firmware interface structure sizes + +From: Osama Abdelkader + +commit b921b8613790a3f9e78ab64017fa7149ef0b750c upstream. + +iface_fw_to_cpu_addr() only checks that the firmware-provided MCU virtual +address points inside the shared section. The returned pointer is later +used as a full firmware interface structure, so accepting an address near +the end of the shared section can still lead to out-of-bounds accesses. + +Pass the expected object size to iface_fw_to_cpu_addr() and reject ranges +that do not fit entirely in the shared section. + +Fixes: 2718d91816ee ("drm/panthor: Add the FW logical block") +Cc: stable@vger.kernel.org +Signed-off-by: Osama Abdelkader +Reviewed-by: Steven Price +Signed-off-by: Steven Price +Link: https://patch.msgid.link/20260720114918.15973-1-osama.abdelkader@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/panthor/panthor_fw.c | 36 +++++++++++++++++++++++------------ + 1 file changed, 24 insertions(+), 12 deletions(-) + +--- a/drivers/gpu/drm/panthor/panthor_fw.c ++++ b/drivers/gpu/drm/panthor/panthor_fw.c +@@ -767,18 +767,24 @@ out: + * iface_fw_to_cpu_addr() - Turn an MCU address into a CPU address + * @ptdev: Device. + * @mcu_va: MCU address. ++ * @size: Size of the object pointed to by @mcu_va. + * +- * Return: NULL if the address is not part of the shared section, non-NULL otherwise. ++ * Return: NULL if the object is not part of the shared section, non-NULL otherwise. + */ +-static void *iface_fw_to_cpu_addr(struct panthor_device *ptdev, u32 mcu_va) ++static void *iface_fw_to_cpu_addr(struct panthor_device *ptdev, u32 mcu_va, size_t size) + { + u64 shared_mem_start = panthor_kernel_bo_gpuva(ptdev->fw->shared_section->mem); +- u64 shared_mem_end = shared_mem_start + +- panthor_kernel_bo_size(ptdev->fw->shared_section->mem); +- if (mcu_va < shared_mem_start || mcu_va >= shared_mem_end) ++ size_t shared_mem_size = panthor_kernel_bo_size(ptdev->fw->shared_section->mem); ++ u64 offset; ++ ++ if (mcu_va < shared_mem_start) ++ return NULL; ++ ++ offset = mcu_va - shared_mem_start; ++ if (offset > shared_mem_size || size > shared_mem_size - offset) + return NULL; + +- return ptdev->fw->shared_section->mem->kmap + (mcu_va - shared_mem_start); ++ return ptdev->fw->shared_section->mem->kmap + offset; + } + + static int panthor_init_cs_iface(struct panthor_device *ptdev, +@@ -800,8 +806,10 @@ static int panthor_init_cs_iface(struct + + spin_lock_init(&cs_iface->lock); + cs_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; +- cs_iface->input = iface_fw_to_cpu_addr(ptdev, cs_iface->control->input_va); +- cs_iface->output = iface_fw_to_cpu_addr(ptdev, cs_iface->control->output_va); ++ cs_iface->input = iface_fw_to_cpu_addr(ptdev, cs_iface->control->input_va, ++ sizeof(*cs_iface->input)); ++ cs_iface->output = iface_fw_to_cpu_addr(ptdev, cs_iface->control->output_va, ++ sizeof(*cs_iface->output)); + + if (!cs_iface->input || !cs_iface->output) { + drm_err(&ptdev->base, "Invalid stream control interface input/output VA"); +@@ -851,8 +859,10 @@ static int panthor_init_csg_iface(struct + + spin_lock_init(&csg_iface->lock); + csg_iface->control = ptdev->fw->shared_section->mem->kmap + iface_offset; +- csg_iface->input = iface_fw_to_cpu_addr(ptdev, csg_iface->control->input_va); +- csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va); ++ csg_iface->input = iface_fw_to_cpu_addr(ptdev, csg_iface->control->input_va, ++ sizeof(*csg_iface->input)); ++ csg_iface->output = iface_fw_to_cpu_addr(ptdev, csg_iface->control->output_va, ++ sizeof(*csg_iface->output)); + + if (csg_iface->control->stream_num < MIN_CS_PER_CSG || + csg_iface->control->stream_num > MAX_CS_PER_CSG) +@@ -909,8 +919,10 @@ static int panthor_fw_init_ifaces(struct + return -EINVAL; + } + +- glb_iface->input = iface_fw_to_cpu_addr(ptdev, glb_iface->control->input_va); +- glb_iface->output = iface_fw_to_cpu_addr(ptdev, glb_iface->control->output_va); ++ glb_iface->input = iface_fw_to_cpu_addr(ptdev, glb_iface->control->input_va, ++ sizeof(*glb_iface->input)); ++ glb_iface->output = iface_fw_to_cpu_addr(ptdev, glb_iface->control->output_va, ++ sizeof(*glb_iface->output)); + if (!glb_iface->input || !glb_iface->output) { + drm_err(&ptdev->base, "Invalid global control interface input/output VA"); + return -EINVAL; diff --git a/queue-6.12/drm-vc4-supply-the-overflow-slot-size-in-bpos-not-the-whole-bin-bo-size.patch b/queue-6.12/drm-vc4-supply-the-overflow-slot-size-in-bpos-not-the-whole-bin-bo-size.patch new file mode 100644 index 0000000000..b76a2c69a4 --- /dev/null +++ b/queue-6.12/drm-vc4-supply-the-overflow-slot-size-in-bpos-not-the-whole-bin-bo-size.patch @@ -0,0 +1,52 @@ +From 6395789e4739aa5177bbec0fa0f07ccc38d249b0 Mon Sep 17 00:00:00 2001 +From: Jose Maria Casanova Crespo +Date: Mon, 27 Jul 2026 11:32:28 -0300 +Subject: drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jose Maria Casanova Crespo + +commit 6395789e4739aa5177bbec0fa0f07ccc38d249b0 upstream. + +vc4_overflow_mem_work() points BPOA at a 512KB slot inside the 16MB +binner BO, but writes the size of the whole BO to BPOS. On every binner +out-of-memory event the PTB is therefore authorized to write tile lists +across all the other slots (which may hold the tile state, tile alloc and +overflow memory of in-flight jobs) and, for any slot but the first, past +the end of the binner BO into unrelated CMA memory. + +Since CMA pages are recycled into page cache and user allocations, this +is arbitrary memory corruption by GPU DMA. In practice it shows up as GPU +hangs with corrupted control list pointers, userspace heap corruption, a +GPU that stays permanently wedged after the first hang, and occasional +full system crashes, whenever a job overflows the initial binner slot. + +The bug dates back to the conversion from a dedicated overflow BO (where +writing the full BO size was correct) to the slotted binner BO. + +Fixes: 553c942f8b2c ("drm/vc4: Allow using more than 256MB of CMA memory.") +Cc: stable@vger.kernel.org +Assisted-by: Claude:claude-opus-4.8 +Signed-off-by: Jose Maria Casanova Crespo +Reviewed-by: Maíra Canal +Reviewed-by: Iago Toral Quiroga +Link: https://patch.msgid.link/20260727-vc4-bin-oom-fixes-v2-1-0d8a5eddc7c9@igalia.com +Signed-off-by: Maíra Canal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/vc4/vc4_irq.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/gpu/drm/vc4/vc4_irq.c ++++ b/drivers/gpu/drm/vc4/vc4_irq.c +@@ -104,7 +104,7 @@ vc4_overflow_mem_work(struct work_struct + vc4->bin_alloc_overflow = BIT(bin_bo_slot); + + V3D_WRITE(V3D_BPOA, bo->base.dma_addr + bin_bo_slot * vc4->bin_alloc_size); +- V3D_WRITE(V3D_BPOS, bo->base.base.size); ++ V3D_WRITE(V3D_BPOS, vc4->bin_alloc_size); + V3D_WRITE(V3D_INTCTL, V3D_INT_OUTOMEM); + V3D_WRITE(V3D_INTENA, V3D_INT_OUTOMEM); + spin_unlock_irqrestore(&vc4->job_lock, irqflags); diff --git a/queue-6.12/drm-vc4-zero-the-tile-state-data-array-before-each-bin-job.patch b/queue-6.12/drm-vc4-zero-the-tile-state-data-array-before-each-bin-job.patch new file mode 100644 index 0000000000..a3def58870 --- /dev/null +++ b/queue-6.12/drm-vc4-zero-the-tile-state-data-array-before-each-bin-job.patch @@ -0,0 +1,95 @@ +From 48a570c964d8e37d353381e4195106277e17f5cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ma=C3=ADra=20Canal?= +Date: Mon, 27 Jul 2026 11:32:29 -0300 +Subject: drm/vc4: Zero the tile state data array before each BIN job +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maíra Canal + +commit 48a570c964d8e37d353381e4195106277e17f5cb upstream. + +The binner BO is a single 16MB buffer split into 512KB slots that are +handed out to jobs at submission time and recycled as jobs complete, +without ever being cleared. Each slot holds the job's Tile State Data +Array (TSDA) at its start, followed by the tile allocation pool. + +While the tile allocation pool is only walked by the render thread +through branches the binner generated during the current job, the +TSDA is the PTB's own per-tile bookkeeping and is consumed by the +hardware itself. Although the kernel sets the "Auto-initialise Tile +State Data Array" flag in the tile binning mode configuration, the +PTB demonstrably still acts on stale tile state left by the slot's +previous user: the binner ends up creating invalid command streams +with invalid primitive streams and branches, which can cause GPU hangs +as observed in [1][2]. + +Zero the TSDA when the job's binning slot is configured. This clears +48 bytes per tile (~24KB for a 1080p frame) in the submission path, and +guarantees the PTB never sees another job's tile state. + +The tile count is only checked for being non-zero today, so the 8-bit +fields it comes from can describe a tile state array almost six times +larger than the slot it has to live in. Bound it before the slot is +handed out, since such size decides how much of the slot is left for +the tile alloc pool. + +Link: https://github.com/raspberrypi/linux/issues/3221 [1] +Link: https://github.com/raspberrypi/linux/issues/5780 [2] +Fixes: 553c942f8b2c ("drm/vc4: Allow using more than 256MB of CMA memory.") +Cc: stable@vger.kernel.org +Reviewed-by: Iago Toral Quiroga +Link: https://patch.msgid.link/20260727-vc4-bin-oom-fixes-v2-2-0d8a5eddc7c9@igalia.com +Signed-off-by: Maíra Canal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/vc4/vc4_validate.c | 29 +++++++++++++++++++++++------ + 1 file changed, 23 insertions(+), 6 deletions(-) + +--- a/drivers/gpu/drm/vc4/vc4_validate.c ++++ b/drivers/gpu/drm/vc4/vc4_validate.c +@@ -387,6 +387,23 @@ validate_tile_binning_config(VALIDATE_AR + return -EINVAL; + } + ++ /* The tile state data array is 48 bytes per tile, and we put it at ++ * the start of a BO containing both it and the tile alloc. ++ */ ++ tile_state_size = 48 * tile_count; ++ ++ /* Since the tile alloc array will follow us, align. */ ++ tile_state_size = roundup(tile_state_size, 4096); ++ ++ /* Reject configurations whose tile state would leave no room for ++ * the tile alloc pool that follows it in the slot. ++ */ ++ if (tile_state_size >= vc4->bin_alloc_size) { ++ DRM_DEBUG("Tile binning config of %dx%d too large\n", ++ exec->bin_tiles_x, exec->bin_tiles_y); ++ return -EINVAL; ++ } ++ + bin_slot = vc4_v3d_get_bin_slot(vc4); + if (bin_slot < 0) { + if (bin_slot != -EINTR && bin_slot != -ERESTARTSYS) { +@@ -402,13 +419,13 @@ validate_tile_binning_config(VALIDATE_AR + exec->bin_slots |= BIT(bin_slot); + bin_addr = vc4->bin_bo->base.dma_addr + bin_slot * vc4->bin_alloc_size; + +- /* The tile state data array is 48 bytes per tile, and we put it at +- * the start of a BO containing both it and the tile alloc. +- */ +- tile_state_size = 48 * tile_count; ++ exec->tile_alloc_offset = bin_addr + tile_state_size; + +- /* Since the tile alloc array will follow us, align. */ +- exec->tile_alloc_offset = bin_addr + roundup(tile_state_size, 4096); ++ /* The TSDA area must be zeroed out before use, otherwise the PTB might ++ * consume a stale tile state. ++ */ ++ memset(vc4->bin_bo->base.vaddr + bin_slot * vc4->bin_alloc_size, 0, ++ tile_state_size); + + *(uint8_t *)(validated + 14) = + ((flags & ~(VC4_BIN_CONFIG_ALLOC_INIT_BLOCK_SIZE_MASK | diff --git a/queue-6.12/series b/queue-6.12/series index 8b5f2664f7..3cecfac360 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -224,3 +224,29 @@ i2c-jz4780-cache-host-clock-rate-at-probe-to-prevent-ccf-prepare_lock-deadlock.p i2c-iproc-reset-bus-after-timeout-if-start_busy-is-stuck.patch i2c-imx-fix-slave-registration-race-and-error-handling.patch i2c-imx-cancel-hrtimer-before-clearing-slave-pointer.patch +can-c_can-c_can_chip_config-keep-controller-in-init-mode-until-bittiming-is-configured.patch +can-ems_usb-validate-cpc-message-lengths.patch +can-etas_es58x-es58x_read_bulk_callback-fix-rx-buffer-leak-on-urb-resubmit-failure.patch +can-gs_usb-gs_usb_receive_bulk_callback-resubmit-urb-on-skb-allocation-failure.patch +can-j1939-transport-j1939_session_fresh_new-initialize-receive-buffer.patch +can-j1939-use-netdevice_tracker-for-j1939_-priv-session-ecu-tracking.patch +can-kvaser_usb-kvaser_usb_hydra_get_busparams-fix-memory-leak-in-kvaser_usb_hydra_get_busparams.patch +can-kvaser_usb_leaf-kvaser_usb_leaf_wait_cmd-validate-received-command-extents.patch +can-softing-fw_parse-validate-firmware-record-spans.patch +can-peak_usb-add-bounds-check-for-usb-channel-index.patch +can-peak_usb-peak_usb_start-fix-double-free-of-transfer-buffer-on-urb-submit-error.patch +can-peak_usb-validate-ucan-receive-record-lengths.patch +can-ctucanfd-add-missing-module_device_table.patch +drm-amd-display-add-av-mute-wait-frames-to-dce110_set_avmute.patch +can-ctucanfd-use-self-test-mode-for-presume_ack.patch +can-ctucanfd-unmap-bar0-using-base-address.patch +can-ctucanfd-handle-bus-error-interrupts.patch +can-ctucanfd-mark-error-active-controller-status-valid.patch +drm-dp-read-the-pcon-max-frl-bandwidth-only-for-hdmi-dfps.patch +drm-vc4-supply-the-overflow-slot-size-in-bpos-not-the-whole-bin-bo-size.patch +drm-vc4-zero-the-tile-state-data-array-before-each-bin-job.patch +drm-panthor-reject-firmware-sections-with-oversized-data.patch +drm-panthor-validate-firmware-interface-structure-sizes.patch +drm-mediatek-ovl_adaptor-balance-component-registrations.patch +drm-amdgpu-restore-umd-profile-pstate-after-runtime-resume.patch +drm-amdgpu-cap-gtt-size-to-physical-ram-on-apus.patch