[PATCH 2/2] firewire: cdev: fix client refcount leak in iso_resource_auto_work()

From: Takashi Sakamoto

Date: Wed Sep 23 2026 - 13:33:28 EST


The client reference leaks when the pending work is cancelled because an
additional reference was taken when scheduling the work.

The reference held by the fw_iso_resource_auto object already ensures
that the client structure remains valid for the lifetime of the object.
Therefore, the additional reference taken when scheduling the work is
unnecessary.

Remove the additional reference.

Reported-by: Dingisoul <dingiso.kernel@xxxxxxxxx>
Link: https://sourceforge.net/p/linux1394/mailman/message/59317811/
Signed-off-by: Takashi Sakamoto <o-takashi@xxxxxxxxxxxxx>
---
drivers/firewire/core-cdev.c | 14 +++++---------
1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c
index 9964c66f2989..a626468b4b0f 100644
--- a/drivers/firewire/core-cdev.c
+++ b/drivers/firewire/core-cdev.c
@@ -196,9 +196,7 @@ static int is_outbound_transaction_resource(const struct client_resource *resour

static void schedule_iso_resource_auto(struct iso_resource_auto *r, unsigned long delay)
{
- client_get(r->client);
- if (!queue_delayed_work(fw_workqueue, &r->work, delay))
- client_put(r->client);
+ queue_delayed_work(fw_workqueue, &r->work, delay);
}

/*
@@ -1369,13 +1367,13 @@ static void iso_resource_auto_work(struct work_struct *work)
// Allow 1000ms grace period for other reallocations.
if (time_is_after_jiffies64(reset_jiffies + secs_to_jiffies(1))) {
schedule_iso_resource_auto(r, msecs_to_jiffies(333));
- goto out;
+ return;
}
break;
case ISO_RES_AUTO_REALLOC:
// We could be called twice within the same generation.
if (resource_generation == current_generation)
- goto out;
+ return;
break;
case ISO_RES_AUTO_DEALLOC:
default:
@@ -1397,7 +1395,7 @@ static void iso_resource_auto_work(struct work_struct *work)
// Is this generation outdated already? As long as this resource sticks in the
// xarray, it will be scheduled again for a newer generation or at shutdown.
if (channel == -EAGAIN)
- goto out;
+ return;

bool success = channel >= 0 || bandwidth > 0;

@@ -1415,7 +1413,7 @@ static void iso_resource_auto_work(struct work_struct *work)

if (todo == ISO_RES_AUTO_REALLOC) {
if (success)
- goto out;
+ return;

// Notify the userspace client of the failure through a deallocation event.
e = r->e_dealloc;
@@ -1450,8 +1448,6 @@ static void iso_resource_auto_work(struct work_struct *work)
// For the incrementation by ioctl_allocate_iso_resource().
client_put(client);
}
- out:
- client_put(client);
}

static void release_iso_resource_auto(struct client *client, struct client_resource *resource)
--
2.53.0