lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20251016055332.914106-1-acelan.kao@canonical.com>
Date: Thu, 16 Oct 2025 13:53:32 +0800
From: "Chia-Lin Kao (AceLan)" <acelan.kao@...onical.com>
To: Heikki Krogerus <heikki.krogerus@...ux.intel.com>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Dmitry Baryshkov <dmitry.baryshkov@....qualcomm.com>,
	Fedor Pchelkin <boddah8794@...il.com>,
	Andrei Kuchynski <akuchynski@...omium.org>,
	Venkat Jayaraman <venkat.jayaraman@...el.com>,
	Myrrh Periwinkle <myrrhperiwinkle@...labs.xyz>,
	"Chia-Lin Kao (AceLan)" <acelan.kao@...onical.com>,
	linux-usb@...r.kernel.org,
	linux-kernel@...r.kernel.org
Subject: [PATCH] usb: typec: ucsi: Detect and skip duplicate altmodes from buggy firmware

Some firmware implementations incorrectly return the same altmode
multiple times at different offsets when queried via UCSI_GET_ALTERNATE_MODES.
This causes sysfs duplicate filename errors and kernel call traces when
the driver attempts to register the same altmode twice:

  sysfs: cannot create duplicate filename '/devices/.../typec/port0/port0.0/partner'
  typec-thunderbolt port0-partner.1: failed to create symlinks
  typec-thunderbolt port0-partner.1: probe with driver typec-thunderbolt failed with error -17

Detect duplicate altmodes by comparing SVID and VDO before registration.
If a duplicate is detected, skip it and print a single clean warning
message instead of generating a kernel call trace:

  ucsi_acpi USBC000:00: con0: Firmware bug: duplicate partner altmode SVID 0x8087 at offset 1, ignoring. Please update your system firmware.

This makes the error handling more user-friendly while still alerting
users to the firmware bug.

The fix applies to all three recipient types: partner (SOP), port (CON),
and plug (SOP_P) altmodes.

Fixes: a79f16efcd00 ("usb: typec: ucsi: Add support for the partner USB Modes")
Cc: stable@...r.kernel.org
Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@...onical.com>
---
 drivers/usb/typec/ucsi/ucsi.c | 81 +++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 3f568f790f39..ebe7e0a223d7 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -602,9 +602,90 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
 		i += num;
 
 		for (j = 0; j < num; j++) {
+			bool duplicate = false;
+			int k;
+
 			if (!alt[j].svid)
 				return 0;
 
+			/*
+			 * Check if this altmode is already registered or is a duplicate
+			 * within the current batch.
+			 * Some firmware implementations incorrectly return the same
+			 * altmode multiple times, either:
+			 * 1. At different offsets in separate queries
+			 * 2. Within the same query response (in alt[] array)
+			 * Both cause sysfs duplicate errors during registration.
+			 *
+			 * We check for duplicates by comparing SVID and VDO (mid),
+			 * which uniquely identify an altmode. If we find a match,
+			 * skip registration to avoid kernel errors.
+			 */
+
+			/* Check for duplicates in current batch first */
+			for (k = 0; k < j; k++) {
+				if (alt[k].svid == alt[j].svid && alt[k].mid == alt[j].mid) {
+					dev_warn_once(con->ucsi->dev,
+						      "con%d: Firmware bug: duplicate altmode SVID 0x%04x in same response at offset %d, ignoring. Please update your system firmware.\n",
+						      con->num, alt[j].svid, i - num + j);
+					duplicate = true;
+					break;
+				}
+			}
+
+			if (duplicate)
+				continue;
+
+			/* Check for duplicates in already registered altmodes */
+			if (recipient == UCSI_RECIPIENT_SOP) {
+				for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+					if (!con->partner_altmode[k])
+						break;
+					/*
+					 * Some buggy firmware returns the same SVID multiple times
+					 * with different VDOs. This causes duplicate device registration
+					 * and sysfs errors. Check SVID only for partner altmodes.
+					 */
+					if (con->partner_altmode[k]->svid == alt[j].svid) {
+						dev_warn(con->ucsi->dev,
+							 "con%d: Firmware bug: duplicate partner altmode SVID 0x%04x (VDO 0x%08x vs 0x%08x) at offset %d, ignoring. Please update your system firmware.\n",
+							 con->num, alt[j].svid, con->partner_altmode[k]->vdo,
+							 alt[j].mid, i - num + j);
+						duplicate = true;
+						break;
+					}
+				}
+			} else if (recipient == UCSI_RECIPIENT_CON) {
+				for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+					if (!con->port_altmode[k])
+						break;
+					if (con->port_altmode[k]->svid == alt[j].svid &&
+					    con->port_altmode[k]->vdo == alt[j].mid) {
+						dev_warn_once(con->ucsi->dev,
+							      "con%d: Firmware bug: duplicate port altmode SVID 0x%04x at offset %d, ignoring. Please update your system firmware.\n",
+							      con->num, alt[j].svid, i - num + j);
+						duplicate = true;
+						break;
+					}
+				}
+			} else if (recipient == UCSI_RECIPIENT_SOP_P) {
+				for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+					if (!con->plug_altmode[k])
+						break;
+					if (con->plug_altmode[k]->svid == alt[j].svid &&
+					    con->plug_altmode[k]->vdo == alt[j].mid) {
+						dev_warn_once(con->ucsi->dev,
+							      "con%d: Firmware bug: duplicate plug altmode SVID 0x%04x at offset %d, ignoring. Please update your system firmware.\n",
+							      con->num, alt[j].svid, i - num + j);
+						duplicate = true;
+						break;
+					}
+				}
+			}
+
+			if (duplicate)
+				continue;
+
 			memset(&desc, 0, sizeof(desc));
 			desc.vdo = alt[j].mid;
 			desc.svid = alt[j].svid;
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ