[PATCH AUTOSEL 6.18-5.10] thunderbolt: Set tb->root_switch to NULL when domain is stopped

Sasha Levin posted 1 patch 3 weeks, 5 days ago
drivers/thunderbolt/tb.c      | 1 +
drivers/thunderbolt/xdomain.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
[PATCH AUTOSEL 6.18-5.10] thunderbolt: Set tb->root_switch to NULL when domain is stopped
Posted by Sasha Levin 3 weeks, 5 days ago
From: Mika Westerberg <mika.westerberg@linux.intel.com>

[ Upstream commit e56249d8a68e712f3b60e1f3fdbb5b4fea146468 ]

Similarly what we do with the firmware connection manager. This makes
tb_xdp_handle_request() return error to the remote host. However, we
need to make sure we keep the uuid alive so that we can reply until the
whole domain is released.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

The background `git branch -a --contains` lookup timed out — this repo
has too many branches for that to finish quickly.

The analysis itself is complete. **Verdict: YES** for backport to this
tree (`linux-6.18.y` at v6.18.43).

The fix is missing from your current checkout and from
`stable/linux-6.18.y`, but is already present in mainline
(`origin/master`). It's a small teardown fix: `tb_stop()` leaves a
dangling `tb->root_switch` after switch removal, which can cause a UAF
crash when in-flight XDomain request work runs during driver unload. The
patch mirrors what `icm_stop()` already does and applies cleanly
here.The `git branch -a --contains e56249d8a68e7` lookup timed out again
— too many branches in this repo for that to finish in a reasonable
time.

I checked the important branches directly instead: the fix is **not** in
your current `6.18.43` checkout or `stable/linux-6.18.y`, but **is** in
`origin/master`. That supports the earlier **YES** backport verdict.

 drivers/thunderbolt/tb.c      | 1 +
 drivers/thunderbolt/xdomain.c | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 041a4c8e10fb9..b516b1ad83a19 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -2952,6 +2952,7 @@ static void tb_stop(struct tb *tb)
 		tb_tunnel_put(tunnel);
 	}
 	tb_switch_remove(tb->root_switch);
+	tb->root_switch = NULL;
 	tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */
 }
 
diff --git a/drivers/thunderbolt/xdomain.c b/drivers/thunderbolt/xdomain.c
index fed0fae2a6299..1eb149445fa05 100644
--- a/drivers/thunderbolt/xdomain.c
+++ b/drivers/thunderbolt/xdomain.c
@@ -756,7 +756,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
 
 	mutex_lock(&tb->lock);
 	if (tb->root_switch)
-		uuid = tb->root_switch->uuid;
+		uuid = kmemdup(tb->root_switch->uuid, sizeof(*uuid), GFP_KERNEL);
 	else
 		uuid = NULL;
 	mutex_unlock(&tb->lock);
@@ -870,6 +870,7 @@ static void tb_xdp_handle_request(struct work_struct *work)
 	}
 
 out:
+	kfree(uuid);
 	kfree(xw->pkg);
 	kfree(xw);
 
@@ -2344,6 +2345,9 @@ static struct tb_xdomain *switch_find_xdomain(struct tb_switch *sw,
 {
 	struct tb_port *port;
 
+	if (!sw)
+		return NULL;
+
 	tb_switch_for_each_port(sw, port) {
 		struct tb_xdomain *xd;
 
-- 
2.53.0