Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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.de
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Hannes Reinecke and committed by
Martin K. Petersen
1c7ce4bc 66167283

+11 -4
+11 -4
drivers/scsi/ch.c
··· 606 606 mutex_unlock(&ch_mutex); 607 607 return -ENXIO; 608 608 } 609 + /* Synchronize with ch_probe() */ 610 + mutex_lock(&ch->lock); 609 611 file->private_data = ch; 612 + mutex_unlock(&ch->lock); 610 613 mutex_unlock(&ch_mutex); 611 614 return 0; 612 615 } ··· 952 949 goto remove_idr; 953 950 } 954 951 952 + mutex_init(&ch->lock); 953 + kref_init(&ch->ref); 954 + ch->device = sd; 955 955 class_dev = device_create(ch_sysfs_class, dev, 956 956 MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, 957 957 "s%s", ch->name); ··· 965 959 goto put_device; 966 960 } 967 961 968 - mutex_init(&ch->lock); 969 - kref_init(&ch->ref); 970 - ch->device = sd; 962 + mutex_lock(&ch->lock); 971 963 ret = ch_readconfig(ch); 972 - if (ret) 964 + if (ret) { 965 + mutex_unlock(&ch->lock); 973 966 goto destroy_dev; 967 + } 974 968 if (init) 975 969 ch_init_elem(ch); 976 970 971 + mutex_unlock(&ch->lock); 977 972 dev_set_drvdata(dev, ch); 978 973 sdev_printk(KERN_INFO, sd, "Attached scsi changer %s\n", ch->name); 979 974