The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer()
@ 2026-05-13 15:52 Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 2/8] usb: typec: altmodes/displayport: validate count before reading Status Update VDO Greg Kroah-Hartman
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb; +Cc: linux-kernel, Greg Kroah-Hartman, Heikki Krogerus, stable

wcove_read_rx_buffer() copies the PD RX FIFO into the caller's
struct pd_message with

	for (i = 0; i < USBC_RXINFO_RXBYTES(info); i++)
		regmap_read(wcove->regmap, USBC_RX_DATA + i, msg + i);

which has two problems:

USBC_RXINFO_RXBYTES() is a 5-bit field (max 31) while struct pd_message
is 30 bytes (__le16 header + __le32 payload[PD_MAX_PAYLOAD], packed).
The byte count latched in RXINFO is the number of bytes the port partner
put on the wire, so a malicious partner that transmits a 31-byte frame
can drive the loop one byte past the destination if the WCOVE BMC
receiver does not enforce the PD object-count limit in hardware. The
existing FIXME flagged this as unverified.

Independently, regmap_read() takes an unsigned int * and stores a full
unsigned int at the destination. Passing the byte pointer msg + i means
each iteration writes four bytes; the high three are zero (val_bits is
8) and are normally overwritten by the next iteration, but the final
iteration's high bytes are not. With RXBYTES == 30 the i == 29 iteration
already writes three zero bytes past msg, which sits on the IRQ thread's
stack in wcove_typec_irq().

Clamp the loop to sizeof(struct pd_message) and read each register into
a local before storing only its low byte, so the copy can never exceed
the destination regardless of what RXINFO reports.

Assisted-by: gkh_clanker_t1000
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/tcpm/wcove.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
index 759c982bb16a..0e5a3e277c3e 100644
--- a/drivers/usb/typec/tcpm/wcove.c
+++ b/drivers/usb/typec/tcpm/wcove.c
@@ -444,9 +444,11 @@ static int wcove_start_toggling(struct tcpc_dev *tcpc,
 	return regmap_write(wcove->regmap, USBC_CONTROL1, usbc_ctrl);
 }
 
-static int wcove_read_rx_buffer(struct wcove_typec *wcove, void *msg)
+static int wcove_read_rx_buffer(struct wcove_typec *wcove,
+				struct pd_message *msg)
 {
-	unsigned int info;
+	unsigned int info, val, len;
+	u8 *buf = (u8 *)msg;
 	int ret;
 	int i;
 
@@ -454,12 +456,13 @@ static int wcove_read_rx_buffer(struct wcove_typec *wcove, void *msg)
 	if (ret)
 		return ret;
 
-	/* FIXME: Check that USBC_RXINFO_RXBYTES(info) matches the header */
+	len = min(USBC_RXINFO_RXBYTES(info), sizeof(*msg));
 
-	for (i = 0; i < USBC_RXINFO_RXBYTES(info); i++) {
-		ret = regmap_read(wcove->regmap, USBC_RX_DATA + i, msg + i);
+	for (i = 0; i < len; i++) {
+		ret = regmap_read(wcove->regmap, USBC_RX_DATA + i, &val);
 		if (ret)
 			return ret;
+		buf[i] = val;
 	}
 
 	return regmap_write(wcove->regmap, USBC_RXSTATUS,
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/8] usb: typec: altmodes/displayport: validate count before reading Status Update VDO
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 3/8] usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT Greg Kroah-Hartman
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb; +Cc: linux-kernel, Greg Kroah-Hartman, Heikki Krogerus, stable

A broken/malicious device can send the incorrect count for a status
update VDO, which will cause the kernel to read uninitialized stack data
and send it off elsewhere.

Fix this up by correctly verifying the count for the update object.

Assisted-by: gkh_clanker_t1000
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/altmodes/displayport.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 35d9c3086990..263a89c5f324 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -405,6 +405,8 @@ static int dp_altmode_vdm(struct typec_altmode *alt,
 				dp->state = DP_STATE_EXIT_PRIME;
 			break;
 		case DP_CMD_STATUS_UPDATE:
+			if (count < 2)
+				break;
 			dp->data.status = *vdo;
 			ret = dp_altmode_status_update(dp);
 			break;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/8] usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 2/8] usb: typec: altmodes/displayport: validate count before reading Status Update VDO Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 4/8] usb: typec: tcpm: validate VDO count in Discover Identity ACK handlers Greg Kroah-Hartman
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Heikki Krogerus,
	André Draszik, Badhri Jagan Sridharan, Amit Sunil Dhamne,
	stable

A broken/malicious port can transmit a CRC-valid frame whose header
advertises up to seven data objects but whose body carries fewer than
that.  Check for this, and rightfully reject the message, instead of
reading from uninitialized stack memory.

Assisted-by: gkh_clanker_t1000
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: "André Draszik" <andre.draszik@linaro.org>
Cc: Badhri Jagan Sridharan <badhri@google.com>
Cc: Amit Sunil Dhamne <amitsd@google.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/tcpm/tcpci_maxim_core.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpci_maxim_core.c b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
index c0ee7e6959ed..7324139d51c8 100644
--- a/drivers/usb/typec/tcpm/tcpci_maxim_core.c
+++ b/drivers/usb/typec/tcpm/tcpci_maxim_core.c
@@ -181,6 +181,15 @@ static void process_rx(struct max_tcpci_chip *chip, u16 status)
 	rx_buf_ptr = rx_buf + TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET;
 	msg.header = cpu_to_le16(*(u16 *)rx_buf_ptr);
 	rx_buf_ptr = rx_buf_ptr + sizeof(msg.header);
+
+	if (count < TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET + sizeof(msg.header) +
+		    pd_header_cnt_le(msg.header) * sizeof(msg.payload[0])) {
+		max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
+		dev_err(chip->dev, "Invalid TCPC_RX_BYTE_CNT %d for header cnt %d\n",
+			count, pd_header_cnt_le(msg.header));
+		return;
+	}
+
 	for (payload_index = 0; payload_index < pd_header_cnt_le(msg.header); payload_index++,
 	     rx_buf_ptr += sizeof(msg.payload[0]))
 		msg.payload[payload_index] = cpu_to_le32(*(u32 *)rx_buf_ptr);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/8] usb: typec: tcpm: validate VDO count in Discover Identity ACK handlers
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 2/8] usb: typec: altmodes/displayport: validate count before reading Status Update VDO Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 3/8] usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 5/8] usb: typec: tcpm: validate VDO count before reading Attention status VDO Greg Kroah-Hartman
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Heikki Krogerus, stable

Properly validate the count passed from a device when calling
svdm_consume_identity() or svdm_consume_identity_sop_prime() as the
device-controlled value could index off of the static arrays, which
could leak data.

Assisted-by: gkh_clanker_t1000
Cc: Badhri Jagan Sridharan <badhri@google.com>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/tcpm/tcpm.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 55fee96d3342..44dab6c32c33 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -1855,6 +1855,9 @@ static void svdm_consume_identity(struct tcpm_port *port, const u32 *p, int cnt)
 	u32 vdo = p[VDO_INDEX_IDH];
 	u32 product = p[VDO_INDEX_PRODUCT];
 
+	if (cnt <= VDO_INDEX_PRODUCT)
+		return;
+
 	memset(&port->mode_data, 0, sizeof(port->mode_data));
 
 	port->partner_ident.id_header = vdo;
@@ -1875,6 +1878,9 @@ static void svdm_consume_identity_sop_prime(struct tcpm_port *port, const u32 *p
 	u32 product = p[VDO_INDEX_PRODUCT];
 	int svdm_version;
 
+	if (cnt <= VDO_INDEX_CABLE_1)
+		return;
+
 	/*
 	 * Attempt to consume identity only if cable currently is not set
 	 */
@@ -1898,7 +1904,7 @@ static void svdm_consume_identity_sop_prime(struct tcpm_port *port, const u32 *p
 	switch (port->negotiated_rev_prime) {
 	case PD_REV30:
 		port->cable_desc.pd_revision = 0x0300;
-		if (port->cable_desc.active)
+		if (port->cable_desc.active && cnt > VDO_INDEX_CABLE_2)
 			port->cable_ident.vdo[1] = p[VDO_INDEX_CABLE_2];
 		break;
 	case PD_REV20:
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/8] usb: typec: tcpm: validate VDO count before reading Attention status VDO
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
                   ` (2 preceding siblings ...)
  2026-05-13 15:52 ` [PATCH 4/8] usb: typec: tcpm: validate VDO count in Discover Identity ACK handlers Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 6/8] usb: typec: tcpm: bound altmode_desc[] per iteration in svdm_consume_modes() Greg Kroah-Hartman
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Heikki Krogerus, stable

A broken/malicious device can send the incorrect count for an attention
status VDO, which will cause the kernel to read uninitialized stack data
and send it off elsewhere.

Fix this up by correctly verifying the count for the attention object.

Assisted-by: gkh_clanker_t1000
Cc: Badhri Jagan Sridharan <badhri@google.com>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/tcpm/tcpm.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 44dab6c32c33..2cab74ed71a7 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -2639,6 +2639,8 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
 			}
 			break;
 		case ADEV_ATTENTION:
+			if (cnt < 2)
+				break;
 			if (typec_altmode_attention(adev, p[1]))
 				tcpm_log(port, "typec_altmode_attention no port partner altmode");
 			break;
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/8] usb: typec: tcpm: bound altmode_desc[] per iteration in svdm_consume_modes()
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
                   ` (3 preceding siblings ...)
  2026-05-13 15:52 ` [PATCH 5/8] usb: typec: tcpm: validate VDO count before reading Attention status VDO Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 7/8] usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change() Greg Kroah-Hartman
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Badhri Jagan Sridharan,
	Heikki Krogerus, stable

svdm_consume_modes() checks pmdata->altmodes against the array size once
before the loop over the count, but forgot to check the bound at every
point in the loop.

In the well-behaved SVDM discovery flow this is harmless because each of
at most SVID_DISCOVERY_MAX SVIDs contributes at most MODE_DISCOVERY_MAX
modes, exactly filling altmode_desc[ALTMODE_DISCOVERY_MAX].  But the
CMDT_RSP_ACK handler in tcpm_pd_svdm() does not correlate an incoming
ACK with any request the port actually sent.  Once port->partner is set,
an unsolicited Discover Modes ACK is consumed unconditionally.  A broken
or malicious port partner can therefore drive altmodes to
ALTMODE_DISCOVERY_MAX - 1 via the normal flow, and then send one extra
Discover Modes ACK with seven VDOs.  Because the pre-loop check passes,
the loop could then writes up to five entries past altmode_desc[].  For
mode_data_prime the next field in struct tcpm_port is the
partner_altmode[] pointer array, which then receives partner-chosen
SVID/VDO bytes.

Move the bound check inside the loop so the array can never be indexed
past ALTMODE_DISCOVERY_MAX regardless of how many VDOs the partner
supplies or how the function was reached.

Assisted-by: gkh_clanker_t1000
Cc: Badhri Jagan Sridharan <badhri@google.com>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/tcpm/tcpm.c | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 2cab74ed71a7..8d904a9013fb 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -1992,23 +1992,19 @@ static void svdm_consume_modes(struct tcpm_port *port, const u32 *p, int cnt,
 	switch (rx_sop_type) {
 	case TCPC_TX_SOP_PRIME:
 		pmdata = &port->mode_data_prime;
-		if (pmdata->altmodes >= ARRAY_SIZE(port->plug_prime_altmode)) {
-			/* Already logged in svdm_consume_svids() */
-			return;
-		}
 		break;
 	case TCPC_TX_SOP:
 		pmdata = &port->mode_data;
-		if (pmdata->altmodes >= ARRAY_SIZE(port->partner_altmode)) {
-			/* Already logged in svdm_consume_svids() */
-			return;
-		}
 		break;
 	default:
 		return;
 	}
 
 	for (i = 1; i < cnt; i++) {
+		if (pmdata->altmodes >= ALTMODE_DISCOVERY_MAX) {
+			/* Already logged in svdm_consume_svids() */
+			return;
+		}
 		paltmode = &pmdata->altmode_desc[pmdata->altmodes];
 		memset(paltmode, 0, sizeof(*paltmode));
 
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/8] usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
                   ` (4 preceding siblings ...)
  2026-05-13 15:52 ` [PATCH 6/8] usb: typec: tcpm: bound altmode_desc[] per iteration in svdm_consume_modes() Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 15:52 ` [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change() Greg Kroah-Hartman
  6 siblings, 0 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Heikki Krogerus, Pooja Katiyar,
	Johan Hovold, stable

ucsi_displayport_vdm() handles a DP_CMD_CONFIGURE by copying the first
payload VDO from data[], but unlike the equivalent handler in
altmodes/displayport.c it does not check that count covers a VDO beyond
the header.  A header-only Configure VDM (count == 1) would read one u32
past the caller's array.

In the normal UCSI path the caller controls count, so this is hardening
for non-standard delivery paths.  NAK and bail when no configuration VDO
is present, matching the generic DP altmode driver's existing guard.

Assisted-by: gkh_clanker_t1000
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Pooja Katiyar <pooja.katiyar@intel.com>
Cc: Johan Hovold <johan@kernel.org>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/ucsi/displayport.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c
index 8aae80b457d7..67a0991a7b76 100644
--- a/drivers/usb/typec/ucsi/displayport.c
+++ b/drivers/usb/typec/ucsi/displayport.c
@@ -240,6 +240,10 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,
 				dp->header |= VDO_CMDT(CMDT_RSP_ACK);
 			break;
 		case DP_CMD_CONFIGURE:
+			if (count < 2) {
+				dp->header |= VDO_CMDT(CMDT_RSP_NAK);
+				break;
+			}
 			dp->data.conf = *data;
 			if (ucsi_displayport_configure(dp)) {
 				dp->header |= VDO_CMDT(CMDT_RSP_NAK);
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change()
  2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
                   ` (5 preceding siblings ...)
  2026-05-13 15:52 ` [PATCH 7/8] usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO Greg Kroah-Hartman
@ 2026-05-13 15:52 ` Greg Kroah-Hartman
  2026-05-13 16:03   ` Benson Leung
  2026-05-13 16:13   ` Abel Vesa
  6 siblings, 2 replies; 10+ messages in thread
From: Greg Kroah-Hartman @ 2026-05-13 15:52 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, Greg Kroah-Hartman, Heikki Krogerus, Benson Leung,
	Jameson Thies, Nathan Rebello, Johan Hovold, Pooja Katiyar,
	Hsin-Te Yuan, Abel Vesa, stable

The connector number in a UCSI CCI notification is a 7-bit field
supplied by the PPM.  ucsi_connector_change() uses it to index the
ucsi->connector[] array without checking it against the number of
connectors the PPM reported at init time, so a buggy or malicious PPM
(EC firmware, or an I2C-attached UCSI controller on the ccg / stm32g0 /
glink transports) can drive schedule_work() on memory past the end of
the array.

Reject connector numbers that are zero or exceed cap.num_connectors
before dereferencing the array.

Assisted-by: gkh_clanker_t1000
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: Benson Leung <bleung@chromium.org>
Cc: Jameson Thies <jthies@google.com>
Cc: Nathan Rebello <nathan.c.rebello@gmail.com>
Cc: Johan Hovold <johan@kernel.org>
Cc: Pooja Katiyar <pooja.katiyar@intel.com>
Cc: Hsin-Te Yuan <yuanhsinte@chromium.org>
Cc: Abel Vesa <abelvesa@kernel.org>
Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/usb/typec/ucsi/ucsi.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 5b7ad9e99cb9..539dc706798d 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1380,13 +1380,22 @@ static void ucsi_handle_connector_change(struct work_struct *work)
  */
 void ucsi_connector_change(struct ucsi *ucsi, u8 num)
 {
-	struct ucsi_connector *con = &ucsi->connector[num - 1];
+	struct ucsi_connector *con;
 
 	if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
 		dev_dbg(ucsi->dev, "Early connector change event\n");
 		return;
 	}
 
+	if (!num || num > ucsi->cap.num_connectors) {
+		dev_warn_ratelimited(ucsi->dev,
+				     "Bogus connector change on %u (max %u)\n",
+				     num, ucsi->cap.num_connectors);
+		return;
+	}
+
+	con = &ucsi->connector[num - 1];
+
 	if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
 		schedule_work(&con->work);
 }
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change()
  2026-05-13 15:52 ` [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change() Greg Kroah-Hartman
@ 2026-05-13 16:03   ` Benson Leung
  2026-05-13 16:13   ` Abel Vesa
  1 sibling, 0 replies; 10+ messages in thread
From: Benson Leung @ 2026-05-13 16:03 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Heikki Krogerus, Benson Leung,
	Jameson Thies, Nathan Rebello, Johan Hovold, Pooja Katiyar,
	Hsin-Te Yuan, Abel Vesa, stable

[-- Attachment #1: Type: text/plain, Size: 2280 bytes --]

On Wed, May 13, 2026 at 05:52:55PM +0200, Greg Kroah-Hartman wrote:
> The connector number in a UCSI CCI notification is a 7-bit field
> supplied by the PPM.  ucsi_connector_change() uses it to index the
> ucsi->connector[] array without checking it against the number of
> connectors the PPM reported at init time, so a buggy or malicious PPM
> (EC firmware, or an I2C-attached UCSI controller on the ccg / stm32g0 /
> glink transports) can drive schedule_work() on memory past the end of
> the array.
> 
> Reject connector numbers that are zero or exceed cap.num_connectors
> before dereferencing the array.
> 
> Assisted-by: gkh_clanker_t1000
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Jameson Thies <jthies@google.com>
> Cc: Nathan Rebello <nathan.c.rebello@gmail.com>
> Cc: Johan Hovold <johan@kernel.org>
> Cc: Pooja Katiyar <pooja.katiyar@intel.com>
> Cc: Hsin-Te Yuan <yuanhsinte@chromium.org>
> Cc: Abel Vesa <abelvesa@kernel.org>
> Cc: stable <stable@kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>


Reviewed-by: Benson Leung <bleung@chromium.org>


> ---
>  drivers/usb/typec/ucsi/ucsi.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
> index 5b7ad9e99cb9..539dc706798d 100644
> --- a/drivers/usb/typec/ucsi/ucsi.c
> +++ b/drivers/usb/typec/ucsi/ucsi.c
> @@ -1380,13 +1380,22 @@ static void ucsi_handle_connector_change(struct work_struct *work)
>   */
>  void ucsi_connector_change(struct ucsi *ucsi, u8 num)
>  {
> -	struct ucsi_connector *con = &ucsi->connector[num - 1];
> +	struct ucsi_connector *con;
>  
>  	if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
>  		dev_dbg(ucsi->dev, "Early connector change event\n");
>  		return;
>  	}
>  
> +	if (!num || num > ucsi->cap.num_connectors) {
> +		dev_warn_ratelimited(ucsi->dev,
> +				     "Bogus connector change on %u (max %u)\n",
> +				     num, ucsi->cap.num_connectors);
> +		return;
> +	}
> +
> +	con = &ucsi->connector[num - 1];
> +
>  	if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
>  		schedule_work(&con->work);
>  }
> -- 
> 2.54.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change()
  2026-05-13 15:52 ` [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change() Greg Kroah-Hartman
  2026-05-13 16:03   ` Benson Leung
@ 2026-05-13 16:13   ` Abel Vesa
  1 sibling, 0 replies; 10+ messages in thread
From: Abel Vesa @ 2026-05-13 16:13 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, Heikki Krogerus, Benson Leung,
	Jameson Thies, Nathan Rebello, Johan Hovold, Pooja Katiyar,
	Hsin-Te Yuan, Abel Vesa, stable

On 26-05-13 17:52:55, Greg Kroah-Hartman wrote:
> The connector number in a UCSI CCI notification is a 7-bit field
> supplied by the PPM.  ucsi_connector_change() uses it to index the
> ucsi->connector[] array without checking it against the number of
> connectors the PPM reported at init time, so a buggy or malicious PPM
> (EC firmware, or an I2C-attached UCSI controller on the ccg / stm32g0 /
> glink transports) can drive schedule_work() on memory past the end of
> the array.
> 
> Reject connector numbers that are zero or exceed cap.num_connectors
> before dereferencing the array.
> 
> Assisted-by: gkh_clanker_t1000
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: Benson Leung <bleung@chromium.org>
> Cc: Jameson Thies <jthies@google.com>
> Cc: Nathan Rebello <nathan.c.rebello@gmail.com>
> Cc: Johan Hovold <johan@kernel.org>
> Cc: Pooja Katiyar <pooja.katiyar@intel.com>
> Cc: Hsin-Te Yuan <yuanhsinte@chromium.org>
> Cc: Abel Vesa <abelvesa@kernel.org>
> Cc: stable <stable@kernel.org>
> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-05-13 16:13 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-13 15:52 [PATCH 1/8] usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer() Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 2/8] usb: typec: altmodes/displayport: validate count before reading Status Update VDO Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 3/8] usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 4/8] usb: typec: tcpm: validate VDO count in Discover Identity ACK handlers Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 5/8] usb: typec: tcpm: validate VDO count before reading Attention status VDO Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 6/8] usb: typec: tcpm: bound altmode_desc[] per iteration in svdm_consume_modes() Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 7/8] usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO Greg Kroah-Hartman
2026-05-13 15:52 ` [PATCH 8/8] usb: typec: ucsi: validate connector number in ucsi_connector_change() Greg Kroah-Hartman
2026-05-13 16:03   ` Benson Leung
2026-05-13 16:13   ` Abel Vesa

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox