aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/uio
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@aristanetworks.com>2010-09-14 14:36:27 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:16:43 -0400
commit3d4f9d76b0641b7984f95982e390927fc5998ad6 (patch)
tree7f57194438afcfe364fc507b359840b65c63d203 /drivers/uio
parente52eec13cd6b7f30ab19081b387813e03e592ae5 (diff)
uio: Fix lack of locking in init_uio_class
There is no locking in init_uio_class so multiple drivers can race and create multiple uio classes. Fix this by simplifying the code. In particular always register the uio class during module_init and make things simpler. Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Hans J. Koch <hjk@linutronix.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/uio')
-rw-r--r--drivers/uio/uio.c58
1 files changed, 15 insertions, 43 deletions
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bff1afbde5a4..bc774cce0a4d 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -45,10 +45,7 @@ static DEFINE_IDR(uio_idr);
45static const struct file_operations uio_fops; 45static const struct file_operations uio_fops;
46 46
47/* UIO class infrastructure */ 47/* UIO class infrastructure */
48static struct uio_class { 48static struct class *uio_class;
49 struct kref kref;
50 struct class *class;
51} *uio_class;
52 49
53/* Protect idr accesses */ 50/* Protect idr accesses */
54static DEFINE_MUTEX(minor_lock); 51static DEFINE_MUTEX(minor_lock);
@@ -757,55 +754,35 @@ static void uio_major_cleanup(void)
757 754
758static int init_uio_class(void) 755static int init_uio_class(void)
759{ 756{
760 int ret = 0; 757 struct class *class;
761 758 int ret;
762 if (uio_class != NULL) {
763 kref_get(&uio_class->kref);
764 goto exit;
765 }
766 759
767 /* This is the first time in here, set everything up properly */ 760 /* This is the first time in here, set everything up properly */
768 ret = uio_major_init(); 761 ret = uio_major_init();
769 if (ret) 762 if (ret)
770 goto exit; 763 goto exit;
771 764
772 uio_class = kzalloc(sizeof(*uio_class), GFP_KERNEL); 765 class = class_create(THIS_MODULE, "uio");
773 if (!uio_class) { 766 if (IS_ERR(class)) {
774 ret = -ENOMEM; 767 ret = IS_ERR(class);
775 goto err_kzalloc;
776 }
777
778 kref_init(&uio_class->kref);
779 uio_class->class = class_create(THIS_MODULE, "uio");
780 if (IS_ERR(uio_class->class)) {
781 ret = IS_ERR(uio_class->class);
782 printk(KERN_ERR "class_create failed for uio\n"); 768 printk(KERN_ERR "class_create failed for uio\n");
783 goto err_class_create; 769 goto err_class_create;
784 } 770 }
771 uio_class = class;
785 return 0; 772 return 0;
786 773
787err_class_create: 774err_class_create:
788 kfree(uio_class);
789 uio_class = NULL;
790err_kzalloc:
791 uio_major_cleanup(); 775 uio_major_cleanup();
792exit: 776exit:
793 return ret; 777 return ret;
794} 778}
795 779
796static void release_uio_class(struct kref *kref) 780static void release_uio_class(void)
797{ 781{
798 /* Ok, we cheat as we know we only have one uio_class */ 782 /* Ok, we cheat as we know we only have one uio_class */
799 class_destroy(uio_class->class); 783 class_destroy(uio_class);
800 kfree(uio_class);
801 uio_major_cleanup();
802 uio_class = NULL; 784 uio_class = NULL;
803} 785 uio_major_cleanup();
804
805static void uio_class_destroy(void)
806{
807 if (uio_class)
808 kref_put(&uio_class->kref, release_uio_class);
809} 786}
810 787
811/** 788/**
@@ -828,10 +805,6 @@ int __uio_register_device(struct module *owner,
828 805
829 info->uio_dev = NULL; 806 info->uio_dev = NULL;
830 807
831 ret = init_uio_class();
832 if (ret)
833 return ret;
834
835 idev = kzalloc(sizeof(*idev), GFP_KERNEL); 808 idev = kzalloc(sizeof(*idev), GFP_KERNEL);
836 if (!idev) { 809 if (!idev) {
837 ret = -ENOMEM; 810 ret = -ENOMEM;
@@ -847,7 +820,7 @@ int __uio_register_device(struct module *owner,
847 if (ret) 820 if (ret)
848 goto err_get_minor; 821 goto err_get_minor;
849 822
850 idev->dev = device_create(uio_class->class, parent, 823 idev->dev = device_create(uio_class, parent,
851 MKDEV(uio_major, idev->minor), idev, 824 MKDEV(uio_major, idev->minor), idev,
852 "uio%d", idev->minor); 825 "uio%d", idev->minor);
853 if (IS_ERR(idev->dev)) { 826 if (IS_ERR(idev->dev)) {
@@ -874,13 +847,12 @@ int __uio_register_device(struct module *owner,
874err_request_irq: 847err_request_irq:
875 uio_dev_del_attributes(idev); 848 uio_dev_del_attributes(idev);
876err_uio_dev_add_attributes: 849err_uio_dev_add_attributes:
877 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); 850 device_destroy(uio_class, MKDEV(uio_major, idev->minor));
878err_device_create: 851err_device_create:
879 uio_free_minor(idev); 852 uio_free_minor(idev);
880err_get_minor: 853err_get_minor:
881 kfree(idev); 854 kfree(idev);
882err_kzalloc: 855err_kzalloc:
883 uio_class_destroy();
884 return ret; 856 return ret;
885} 857}
886EXPORT_SYMBOL_GPL(__uio_register_device); 858EXPORT_SYMBOL_GPL(__uio_register_device);
@@ -907,9 +879,8 @@ void uio_unregister_device(struct uio_info *info)
907 uio_dev_del_attributes(idev); 879 uio_dev_del_attributes(idev);
908 880
909 dev_set_drvdata(idev->dev, NULL); 881 dev_set_drvdata(idev->dev, NULL);
910 device_destroy(uio_class->class, MKDEV(uio_major, idev->minor)); 882 device_destroy(uio_class, MKDEV(uio_major, idev->minor));
911 kfree(idev); 883 kfree(idev);
912 uio_class_destroy();
913 884
914 return; 885 return;
915} 886}
@@ -917,11 +888,12 @@ EXPORT_SYMBOL_GPL(uio_unregister_device);
917 888
918static int __init uio_init(void) 889static int __init uio_init(void)
919{ 890{
920 return 0; 891 return init_uio_class();
921} 892}
922 893
923static void __exit uio_exit(void) 894static void __exit uio_exit(void)
924{ 895{
896 release_uio_class();
925} 897}
926 898
927module_init(uio_init) 899module_init(uio_init)