summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernard Pidoux <bernard.f6bvp@gmail.com>2026-05-28 19:11:55 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-06-27 11:07:40 +0100
commit4f9aa720a80f1a23b26a04d8bc9d403f96770d09 (patch)
tree1ccc81db894e5c0f87aa802d62dc5ad1adeb4e10
parent35ed67c5f66dcfba53a184263bafc7c5bd542558 (diff)
downloadlinux-4f9aa720a80f1a23b26a04d8bc9d403f96770d09.tar.gz
linux-4f9aa720a80f1a23b26a04d8bc9d403f96770d09.zip
rose: fix netdev double-hold in rose_make_new()
commit b9fb21ceb4f0d043767a1eba60786ec84809033b upstream. rose_make_new() copies orose->device from the listener socket and calls netdev_hold(), storing the tracker in rose->dev_tracker. The only caller, rose_rx_call_request(), then overwrites both make_rose->device and make_rose->dev_tracker with a fresh netdev_hold() for the actual incoming-call device. This orphans the tracker allocated by rose_make_new(): it remains in the device's refcount_tracker list but no pointer exists to free it via netdev_put(). The result is one spurious outstanding reference per accepted CALL_REQUEST, visible at rmmod time as: ref_tracker: netdev@X has 2/2 users at rose_rx_call_request+0xba3/0x1d50 [rose] rose_loopback_timer+0x3eb/0x670 [rose] The second entry is the orphaned tracker from rose_make_new(); the first is the correctly-managed socket reference from rose_rx_call_request(). Fix: initialise rose->device to NULL in rose_make_new() and let rose_rx_call_request() -- the sole caller -- assign the correct device and take the sole netdev_hold() as it already does. Signed-off-by: Bernard Pidoux <bernard.f6bvp@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/rose/af_rose.c4
1 files changed, 1 insertions, 3 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index 35099cd6ee19..1f641516e03e 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -631,9 +631,7 @@ static struct sock *rose_make_new(struct sock *osk)
rose->hb = orose->hb;
rose->idle = orose->idle;
rose->defer = orose->defer;
- rose->device = orose->device;
- if (rose->device)
- netdev_hold(rose->device, &rose->dev_tracker, GFP_ATOMIC);
+ rose->device = NULL; /* rose_rx_call_request() sets this */
rose->qbitincl = orose->qbitincl;
return sk;