[PATCH] thunderbolt: Fix tunnel reference leak in tb_dp_dprx_start()

From: Wentao Liang

Date: Thu Sep 17 2026 - 12:06:11 EST


The extra tunnel reference taken to keep the tunnel around while
tunnel->dprx_work is pending is only dropped in tb_dp_dprx_stop() when
cancel_delayed_work() reports that it canceled a pending work. For
tunnels created by tb_tunnel_discover_dp() there is no callback, so no
work is queued and that condition is never true, leaking the reference
on every activation.

Only take the reference when the delayed work is actually queued.

Fixes: 67600ccfc4f3 ("thunderbolt: Fix use-after-free in tb_dp_dprx_work")
Signed-off-by: Wentao Liang <vulab@xxxxxxxxxxx>
---
drivers/thunderbolt/tunnel.c | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/thunderbolt/tunnel.c b/drivers/thunderbolt/tunnel.c
index f38f7753b6e4..696a7e06d940 100644
--- a/drivers/thunderbolt/tunnel.c
+++ b/drivers/thunderbolt/tunnel.c
@@ -1078,15 +1078,16 @@ static void tb_dp_dprx_work(struct work_struct *work)

static int tb_dp_dprx_start(struct tb_tunnel *tunnel)
{
- /*
- * Bump up the reference to keep the tunnel around. It will be
- * dropped in tb_dp_dprx_stop() once the tunnel is deactivated.
- */
- tb_tunnel_get(tunnel);
-
tunnel->dprx_started = true;

if (tunnel->callback) {
+ /*
+ * Bump up the reference to keep the tunnel around while
+ * the delayed work is pending. It is dropped either in
+ * tb_dp_dprx_stop() when the work was canceled, or by the
+ * work itself.
+ */
+ tb_tunnel_get(tunnel);
tunnel->dprx_timeout = dprx_timeout_to_ktime(dprx_timeout);
queue_delayed_work(tunnel->tb->wq, &tunnel->dprx_work, 0);
return -EINPROGRESS;
--
2.34.1