V4L/DVB (5244): Dvbdev: fix illegal re-usage of fileoperations struct
authorMarcel Siegert <mws@linuxtv.org>
Tue, 13 Feb 2007 12:46:55 +0000 (09:46 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 21 Feb 2007 15:35:31 +0000 (13:35 -0200)
Arjan van de Ven <arjan@infradead.org> reported an illegal re-usage of
the fileoperations struct if more than one dvb device (e.g. frontend) is
present.

This patch fixes this issue.

It allocates a new fileoperations struct each time a device is
registered and copies the default template fileops.

Signed-off-by: Marcel Siegert <mws@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
drivers/media/dvb/dvb-core/dvbdev.c

index 826b47f155a02cfae38471272360024da72d37f7..490337b5ee3e2ec9c8007c536d8eec1b1fa783d9 100644 (file)
@@ -199,12 +199,14 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
                        const struct dvb_device *template, void *priv, int type)
 {
        struct dvb_device *dvbdev;
+       struct file_operations *dvbdevfops;
+
        int id;
 
        if (mutex_lock_interruptible(&dvbdev_register_lock))
                return -ERESTARTSYS;
 
-       if ((id = dvbdev_get_free_id (adap, type)) < 0) {
+       if ((id = dvbdev_get_free_id (adap, type)) < 0){
                mutex_unlock(&dvbdev_register_lock);
                *pdvbdev = NULL;
                printk ("%s: could get find free device id...\n", __FUNCTION__);
@@ -213,7 +215,15 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 
        *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
 
-       if (!dvbdev) {
+       if (!dvbdev){
+               mutex_unlock(&dvbdev_register_lock);
+               return -ENOMEM;
+       }
+
+       dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
+
+       if (!dvbdevfops){
+               kfree (dvbdev);
                mutex_unlock(&dvbdev_register_lock);
                return -ENOMEM;
        }
@@ -223,7 +233,9 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
        dvbdev->id = id;
        dvbdev->adapter = adap;
        dvbdev->priv = priv;
+       dvbdev->fops = dvbdevfops;
 
+       memcpy(dvbdev->fops, template->fops, sizeof(struct file_operations));
        dvbdev->fops->owner = adap->module;
 
        list_add_tail (&dvbdev->list_head, &adap->device_list);
@@ -251,6 +263,7 @@ void dvb_unregister_device(struct dvb_device *dvbdev)
                                        dvbdev->type, dvbdev->id)));
 
        list_del (&dvbdev->list_head);
+       kfree (dvbdev->fops);
        kfree (dvbdev);
 }
 EXPORT_SYMBOL(dvb_unregister_device);