Input: reset name, phys and uniq when unregistering
authorDmitry Torokhov <dtor_core@ameritech.net>
Mon, 26 Jun 2006 05:48:36 +0000 (01:48 -0400)
committerDmitry Torokhov <dtor_core@ameritech.net>
Mon, 26 Jun 2006 05:48:36 +0000 (01:48 -0400)
Name, phys and uniq are quite often constant strings in moules implementing
particular input device. If a module unregisters input device and then gets
unloaded, the device could still be present in memory (pinned via sysfs),
but aforementioned members would point to some random memory. Set them all
to NULL when unregistering so sysfs handlers won't try dereferencing them.

Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
drivers/input/input.c
include/linux/input.h

index b149c943484990629bd7183125084cf941980bc7..d3cdb139e96213d7ea38de3b2c793e4ac8aa8e49 100644 (file)
@@ -29,6 +29,7 @@ MODULE_DESCRIPTION("Input core");
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(input_allocate_device);
+EXPORT_SYMBOL(input_free_device);
 EXPORT_SYMBOL(input_register_device);
 EXPORT_SYMBOL(input_unregister_device);
 EXPORT_SYMBOL(input_register_handler);
@@ -872,6 +873,7 @@ struct input_dev *input_allocate_device(void)
                dev->dynalloc = 1;
                dev->cdev.class = &input_class;
                class_device_initialize(&dev->cdev);
+               mutex_init(&dev->mutex);
                INIT_LIST_HEAD(&dev->h_list);
                INIT_LIST_HEAD(&dev->node);
        }
@@ -879,6 +881,18 @@ struct input_dev *input_allocate_device(void)
        return dev;
 }
 
+void input_free_device(struct input_dev *dev)
+{
+       if (dev) {
+
+               mutex_lock(&dev->mutex);
+               dev->name = dev->phys = dev->uniq = NULL;
+               mutex_unlock(&dev->mutex);
+
+               input_put_device(dev);
+       }
+}
+
 int input_register_device(struct input_dev *dev)
 {
        static atomic_t input_no = ATOMIC_INIT(0);
@@ -895,7 +909,6 @@ int input_register_device(struct input_dev *dev)
                return -EINVAL;
        }
 
-       mutex_init(&dev->mutex);
        set_bit(EV_SYN, dev->evbit);
 
        /*
@@ -979,6 +992,10 @@ void input_unregister_device(struct input_dev *dev)
        sysfs_remove_group(&dev->cdev.kobj, &input_dev_attr_group);
        class_device_unregister(&dev->cdev);
 
+       mutex_lock(&dev->mutex);
+       dev->name = dev->phys = dev->uniq = NULL;
+       mutex_unlock(&dev->mutex);
+
        input_wakeup_procfs_readers();
 }
 
index b32c2b6e53f6947ed7233bfd4013e1c462273d55..8d2b874d9e723d2356c62a3bd44cb85a3f361b1e 100644 (file)
@@ -1005,6 +1005,7 @@ static inline void init_input_dev(struct input_dev *dev)
 }
 
 struct input_dev *input_allocate_device(void);
+void input_free_device(struct input_dev *dev);
 
 static inline struct input_dev *input_get_device(struct input_dev *dev)
 {
@@ -1016,12 +1017,6 @@ static inline void input_put_device(struct input_dev *dev)
        class_device_put(&dev->cdev);
 }
 
-static inline void input_free_device(struct input_dev *dev)
-{
-       if (dev)
-               input_put_device(dev);
-}
-
 int input_register_device(struct input_dev *);
 void input_unregister_device(struct input_dev *);