Commit 1c7ce4bc authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: ch: synchronize ch_probe() and ch_open()

The 'ch' device node is created before the configuration is being read in,
which leads to a race window when ch_open() is called before that.

To avoid any races we should be taking the device mutex during
ch_readconfig() and ch_init_elem(), and also during ch_open().
That ensures ch_probe is finished before ch_open() completes.

Link: https://lore.kernel.org/r/20200213153207.123357-3-hare@suse.deReviewed-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarHannes Reinecke <hare@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 66167283
...@@ -606,7 +606,10 @@ ch_open(struct inode *inode, struct file *file) ...@@ -606,7 +606,10 @@ ch_open(struct inode *inode, struct file *file)
mutex_unlock(&ch_mutex); mutex_unlock(&ch_mutex);
return -ENXIO; return -ENXIO;
} }
/* Synchronize with ch_probe() */
mutex_lock(&ch->lock);
file->private_data = ch; file->private_data = ch;
mutex_unlock(&ch->lock);
mutex_unlock(&ch_mutex); mutex_unlock(&ch_mutex);
return 0; return 0;
} }
...@@ -949,6 +952,9 @@ static int ch_probe(struct device *dev) ...@@ -949,6 +952,9 @@ static int ch_probe(struct device *dev)
goto remove_idr; goto remove_idr;
} }
mutex_init(&ch->lock);
kref_init(&ch->ref);
ch->device = sd;
class_dev = device_create(ch_sysfs_class, dev, class_dev = device_create(ch_sysfs_class, dev,
MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch,
"s%s", ch->name); "s%s", ch->name);
...@@ -959,15 +965,16 @@ static int ch_probe(struct device *dev) ...@@ -959,15 +965,16 @@ static int ch_probe(struct device *dev)
goto put_device; goto put_device;
} }
mutex_init(&ch->lock); mutex_lock(&ch->lock);
kref_init(&ch->ref);
ch->device = sd;
ret = ch_readconfig(ch); ret = ch_readconfig(ch);
if (ret) if (ret) {
mutex_unlock(&ch->lock);
goto destroy_dev; goto destroy_dev;
}
if (init) if (init)
ch_init_elem(ch); ch_init_elem(ch);
mutex_unlock(&ch->lock);
dev_set_drvdata(dev, ch); dev_set_drvdata(dev, ch);
sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment