From fb1a0811d58fdbf564fa22b7fb268969c40af175 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 8 Jan 2009 23:28:09 -0200 Subject: backport changeset f41ced8f108cc80f16509b907cd7ac93944459bc From: Mauro Carvalho Chehab Author: Laurent Pinchart Check fops_get() return value Several subsystem open handlers dereference the fops_get() return value without checking it for nullness. This opens a race condition between the open handler and module unloading. A module can be marked as being unloaded (MODULE_STATE_GOING) before its exit function is called and gets the chance to unregister the driver. During that window open handlers can still be called, and fops_get() will fail in try_module_get() and return a NULL pointer. This change checks the fops_get() return value and returns -ENODEV if NULL. kernel-sync: Signed-off-by: Mauro Carvalho Chehab --- linux/drivers/media/dvb/dvb-core/dvbdev.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'linux/drivers/media/dvb') diff --git a/linux/drivers/media/dvb/dvb-core/dvbdev.c b/linux/drivers/media/dvb/dvb-core/dvbdev.c index 4267b2b87..940114768 100644 --- a/linux/drivers/media/dvb/dvb-core/dvbdev.c +++ b/linux/drivers/media/dvb/dvb-core/dvbdev.c @@ -84,6 +84,10 @@ static int dvb_device_open(struct inode *inode, struct file *file) file->private_data = dvbdev; old_fops = file->f_op; file->f_op = fops_get(dvbdev->fops); + if (file->f_op == NULL) { + file->f_op = old_fops; + goto fail; + } if(file->f_op->open) err = file->f_op->open(inode,file); if (err) { @@ -95,6 +99,7 @@ static int dvb_device_open(struct inode *inode, struct file *file) unlock_kernel(); return err; } +fail: up_read(&minor_rwsem); unlock_kernel(); return -ENODEV; -- cgit v1.2.3