Skip to contentSkip to conversation

uio: Fix uio driver to refcount device

PATCH Superseded Brian Russell 1 participant 2 messages Mar 13, 2015 – Mar 18, 2015 Userspace I/O (UIO)

v2 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 uio: Fix uio driver to refcount device

Protect uio driver from crashing if its owner is hot unplugged while there are open fds.

---
 drivers/uio/uio.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/uio/uio.c +7 -1
index 6276f13..70ce015 100644
@@ -434,9 +434,11 @@ static int uio_open(struct inode *inode, struct file *filep)
 		goto out;
 	}
 
+	get_device(idev);
+
 	if (!try_module_get(idev->owner)) {
 		ret = -ENODEV;
-		goto out;
+		goto err_module_get;
 	}
 
 	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
@@ -462,6 +464,9 @@ err_infoopen:
 err_alloc_listener:
 	module_put(idev->owner);
 
+err_module_get:
+	put_device(idev);
+
 out:
 	return ret;
 }
@@ -485,6 +490,7 @@ static int uio_release(struct inode *inode, struct file *filep)
 
 	module_put(idev->owner);
 	kfree(listener);
+	put_device(idev);
 	return ret;
 }
 
Signature · 1 line
2.1.4
#1 lore raw

Responding to myself ...

Quoted 13 lines · Brian Russell

Protect uio driver from crashing if its owner is hot unplugged while there are open fds.

---
 drivers/uio/uio.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/uio/uio.c +0 -0
index 6276f13..70ce015 100644

drivers/uio/uio.c static int uio_open(struct inode *inode, struct file *filep) · line 438

Quoted 5 lines
drivers/uio/uio.c +2 -0
@@ -434,9 +434,11 @@ static int uio_open(struct inode *inode, struct file *filep)
 		goto out;
 	}
 
+	get_device(idev);
+

This is bogus, idev is uio_device *, not device *. Turns out this patch only masked the crash I was seeing, so please ignore. Updated version to follow ...

Thanks,

Brian

Quoted 26 lines
drivers/uio/uio.c +5 -1
 	if (!try_module_get(idev->owner)) {
 		ret = -ENODEV;
-		goto out;
+		goto err_module_get;
 	}
 
 	listener = kmalloc(sizeof(*listener), GFP_KERNEL);
@@ -462,6 +464,9 @@ err_infoopen:
 err_alloc_listener:
 	module_put(idev->owner);
 
+err_module_get:
+	put_device(idev);
+
 out:
 	return ret;
 }
@@ -485,6 +490,7 @@ static int uio_release(struct inode *inode, struct file *filep)
 
 	module_put(idev->owner);
 	kfree(listener);
+	put_device(idev);
 	return ret;
 }