[PATCH 048/139] pps: Fix a use-after free bug when unregistering a source.
From: Luis Henriques
Date: Thu Feb 28 2013 - 10:12:54 EST
126.96.36.199 -stable review patch. If anyone has any objections, please let me know.
From: George Spelvin <linux@xxxxxxxxxxx>
commit d953e0e837e65ecc1ddaa4f9560f7925878a0de6 upstream.
Remove the cdev from the system (with cdev_del) *before* deallocating it
(in pps_device_destruct, called via kobject_put from device_destroy).
Also prevent deallocating a device with open file handles.
A better long-term fix is probably to remove the cdev from the pps_device
entirely, and instead have all devices reference one global cdev. Then
the deallocation ordering becomes simpler.
But that's more complex and invasive change, so we leave that
Signed-off-by: George Spelvin <linux@xxxxxxxxxxx>
Acked-by: Rodolfo Giometti <giometti@xxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
[ luis: adjust context ]
Signed-off-by: Luis Henriques <luis.henriques@xxxxxxxxxxxxx>
drivers/pps/pps.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/pps/pps.c b/drivers/pps/pps.c
index c50a556..f129f4d 100644
@@ -247,12 +247,15 @@ static int pps_cdev_open(struct inode *inode, struct file *file)
struct pps_device *pps = container_of(inode->i_cdev,
struct pps_device, cdev);
file->private_data = pps;
static int pps_cdev_release(struct inode *inode, struct file *file)
+ struct pps_device *pps = container_of(inode->i_cdev,
+ struct pps_device, cdev);
@@ -274,8 +277,10 @@ static void pps_device_destruct(struct device *dev)
struct pps_device *pps = dev_get_drvdata(dev);
- /* release id here to protect others from using it while it's
- * still in use */
+ /* Now we can release the ID for re-use */
+ pr_debug("deallocating pps%d\n", pps->id);
@@ -330,6 +335,7 @@ int pps_register_cdev(struct pps_device *pps)
+ /* Override the release function with our own */
pps->dev->release = pps_device_destruct;
pr_debug("source %s got cdev (%d:%d)\n", pps->info.name,
@@ -350,9 +356,9 @@ free_idr:
void pps_unregister_cdev(struct pps_device *pps)
+ pr_debug("unregistering pps%d\n", pps->id);
pps->lookup_cookie = NULL;
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/