[PATCH v2 2/3] mISDN: socket: drop temporary references from get_mdevice()

From: Shuvam Pandey

Date: Fri Apr 17 2026 - 13:53:04 EST


IMGETDEVINFO and IMSETDEVNAME only use get_mdevice() for a temporary
lookup, but neither path drops the reference returned by
class_find_device().

Drop the temporary reference once the ioctl finishes. Serialize the name
read and rename paths with device_lock() while doing so, and reject
lookups that raced with unregister after device_del().

Fixes: b36b654a7e82 ("mISDN: Create /sys/class/mISDN")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:GPT-5.3-Codex
Signed-off-by: Shuvam Pandey <shuvampandey1@xxxxxxxxx>
---
drivers/isdn/mISDN/socket.c | 31 ++++++++++++++++++++++++++++---
1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index bf3ad0a2a42bc..42cda5b8bbe16 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -484,6 +484,13 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (dev) {
struct mISDN_devinfo di;

+ device_lock(&dev->dev);
+ if (!device_is_registered(&dev->dev)) {
+ device_unlock(&dev->dev);
+ put_device(&dev->dev);
+ err = -ENODEV;
+ break;
+ }
memset(&di, 0, sizeof(di));
di.id = dev->id;
di.Dprotocols = dev->Dprotocols;
@@ -493,8 +500,10 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
sizeof(di.channelmap));
di.nrbchan = dev->nrbchan;
strscpy(di.name, dev_name(&dev->dev), sizeof(di.name));
+ device_unlock(&dev->dev);
if (copy_to_user((void __user *)arg, &di, sizeof(di)))
err = -EFAULT;
+ put_device(&dev->dev);
} else
err = -ENODEV;
break;
@@ -802,6 +811,13 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
if (dev) {
struct mISDN_devinfo di;

+ device_lock(&dev->dev);
+ if (!device_is_registered(&dev->dev)) {
+ device_unlock(&dev->dev);
+ put_device(&dev->dev);
+ err = -ENODEV;
+ break;
+ }
memset(&di, 0, sizeof(di));
di.id = dev->id;
di.Dprotocols = dev->Dprotocols;
@@ -811,8 +827,10 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
sizeof(di.channelmap));
di.nrbchan = dev->nrbchan;
strscpy(di.name, dev_name(&dev->dev), sizeof(di.name));
+ device_unlock(&dev->dev);
if (copy_to_user((void __user *)arg, &di, sizeof(di)))
err = -EFAULT;
+ put_device(&dev->dev);
} else
err = -ENODEV;
break;
@@ -826,10 +844,17 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
}
dn.name[sizeof(dn.name) - 1] = '\0';
dev = get_mdevice(dn.id);
- if (dev)
- err = device_rename(&dev->dev, dn.name);
- else
+ if (dev) {
+ device_lock(&dev->dev);
+ if (!device_is_registered(&dev->dev))
+ err = -ENODEV;
+ else
+ err = device_rename(&dev->dev, dn.name);
+ device_unlock(&dev->dev);
+ put_device(&dev->dev);
+ } else {
err = -ENODEV;
+ }
}
break;
default:
--
2.50.1 (Apple Git-155)