Skip to contentSkip to conversation

usb: typec: ucsi: Fix null pointer dereference in ucsi_sync_control_common

PATCH In review Mario Limonciello (AMD) 2 participants 2 messages Dec 16, 2025 – Dec 22, 2025

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 usb: typec: ucsi: Fix null pointer dereference in ucsi_sync_control_common

Add missing null check for cci parameter before dereferencing it in ucsi_sync_control_common(). The function can be called with cci=NULL from ucsi_acknowledge(), which leads to a null pointer dereference when accessing *cci in the condition check.

The crash occurs because the code checks if cci is not null before calling ucsi->ops->read_cci(ucsi, cci), but then immediately dereferences cci without a null check in the following condition:
(*cci & UCSI_CCI_COMMAND_COMPLETE).

KASAN trace:

  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
  RIP: 0010:ucsi_sync_control_common+0x2ae/0x4e0 [typec_ucsi]
Fixes 667ecac55861 ("usb: typec: ucsi: return CCI and message from sync_control callback")

---
v2:
* Add stable tag
* Add Heikki's tag

---
 drivers/usb/typec/ucsi/ucsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +1 -1
index 9b3df776137a1..7129973f19e7e 100644
@@ -97,7 +97,7 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
 	if (!ret && cci)
 		ret = ucsi->ops->read_cci(ucsi, cci);
 
-	if (!ret && ucsi->message_in_size > 0 &&
+	if (!ret && cci && ucsi->message_in_size > 0 &&
 	    (*cci & UCSI_CCI_COMMAND_COMPLETE))
 		ret = ucsi->ops->read_message_in(ucsi, ucsi->message_in,
 						 ucsi->message_in_size);
Signature · 1 line
2.43.0
#1 lore raw
Quoted 31 lines · Mario Limonciello (AMD)

Add missing null check for cci parameter before dereferencing it in ucsi_sync_control_common(). The function can be called with cci=NULL from ucsi_acknowledge(), which leads to a null pointer dereference when accessing *cci in the condition check.

The crash occurs because the code checks if cci is not null before calling ucsi->ops->read_cci(ucsi, cci), but then immediately dereferences cci without a null check in the following condition:
(*cci & UCSI_CCI_COMMAND_COMPLETE).

KASAN trace:

  KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
  RIP: 0010:ucsi_sync_control_common+0x2ae/0x4e0 [typec_ucsi]
Fixes 667ecac55861 ("usb: typec: ucsi: return CCI and message from sync_control callback")

---
v2:
* Add stable tag
* Add Heikki's tag

---
 drivers/usb/typec/ucsi/ucsi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +0 -0
index 9b3df776137a1..7129973f19e7e 100644

drivers/usb/typec/ucsi/ucsi.c int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci) · line 103

Quoted 8 lines
drivers/usb/typec/ucsi/ucsi.c +1 -1
@@ -97,7 +97,7 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command, u32 *cci)
 	if (!ret && cci)
 		ret = ucsi->ops->read_cci(ucsi, cci);
 
-	if (!ret && ucsi->message_in_size > 0 &&
+	if (!ret && cci && ucsi->message_in_size > 0 &&
 	    (*cci & UCSI_CCI_COMMAND_COMPLETE))
 		ret = ucsi->ops->read_message_in(ucsi, ucsi->message_in,
 						 ucsi->message_in_size);

No, this is just papering over the NULL pointer dereference while leaving the UCSI driver broken.

The problem is the new buffer management code which clearly has not been tested properly. It completely ignores concurrency so that another thread can update the ucsi->message_in_size above while an ack is being processed (with cci being NULL).

As fixing this requires going back to the drawing board I've just send a revert of this mess to fix the regression:

	https://lore.kernel.org/lkml/[email protected]/

Johan