usb: typec: ucsi: Fix null pointer dereference in ucsi_sync_control_common
Subsystems (3)
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]
---
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
@@ -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
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 fromucsi_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")Reviewed-by Heikki Krogerus <[email protected]>Signed-off-by Mario Limonciello (AMD) <[email protected]>---
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
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