Merge "Prevent potential double frees in sg driver"

This commit is contained in:
Linux Build Service Account 2017-11-21 06:44:56 -08:00 committed by Gerrit - the friendly Code Review server
commit c4f4e49994

View file

@ -510,7 +510,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
old_hdr->result = EIO; old_hdr->result = EIO;
break; break;
case DID_ERROR: case DID_ERROR:
old_hdr->result = (srp->sense_b[0] == 0 && old_hdr->result = (srp->sense_b[0] == 0 &&
hp->masked_status == GOOD) ? 0 : EIO; hp->masked_status == GOOD) ? 0 : EIO;
break; break;
default: default:
@ -898,8 +898,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
return -ENXIO; return -ENXIO;
if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR)) if (!access_ok(VERIFY_WRITE, p, SZ_SG_IO_HDR))
return -EFAULT; return -EFAULT;
mutex_lock(&sfp->parentdp->open_rel_lock);
result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR, result = sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
1, read_only, 1, &srp); 1, read_only, 1, &srp);
mutex_unlock(&sfp->parentdp->open_rel_lock);
if (result < 0) if (result < 0)
return result; return result;
result = wait_event_interruptible(sfp->read_wait, result = wait_event_interruptible(sfp->read_wait,
@ -939,8 +941,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
sfp->low_dma = 1; sfp->low_dma = 1;
if ((0 == sfp->low_dma) && !sfp->res_in_use) { if ((0 == sfp->low_dma) && !sfp->res_in_use) {
val = (int) sfp->reserve.bufflen; val = (int) sfp->reserve.bufflen;
mutex_lock(&sfp->parentdp->open_rel_lock);
sg_remove_scat(sfp, &sfp->reserve); sg_remove_scat(sfp, &sfp->reserve);
sg_build_reserve(sfp, val); sg_build_reserve(sfp, val);
mutex_unlock(&sfp->parentdp->open_rel_lock);
} }
} else { } else {
if (atomic_read(&sdp->detaching)) if (atomic_read(&sdp->detaching))
@ -1009,8 +1013,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
result = get_user(val, ip); result = get_user(val, ip);
if (result) if (result)
return result; return result;
if (val < 0) if (val < 0)
return -EINVAL; return -EINVAL;
val = min_t(int, val, val = min_t(int, val,
max_sectors_bytes(sdp->device->request_queue)); max_sectors_bytes(sdp->device->request_queue));
mutex_lock(&sfp->f_mutex); mutex_lock(&sfp->f_mutex);
@ -1020,9 +1024,10 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
mutex_unlock(&sfp->f_mutex); mutex_unlock(&sfp->f_mutex);
return -EBUSY; return -EBUSY;
} }
mutex_lock(&sfp->parentdp->open_rel_lock);
sg_remove_scat(sfp, &sfp->reserve); sg_remove_scat(sfp, &sfp->reserve);
sg_build_reserve(sfp, val); sg_build_reserve(sfp, val);
mutex_unlock(&sfp->parentdp->open_rel_lock);
} }
mutex_unlock(&sfp->f_mutex); mutex_unlock(&sfp->f_mutex);
return 0; return 0;
@ -1149,14 +1154,14 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon
return -ENXIO; return -ENXIO;
sdev = sdp->device; sdev = sdp->device;
if (sdev->host->hostt->compat_ioctl) { if (sdev->host->hostt->compat_ioctl) {
int ret; int ret;
ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg); ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
return ret; return ret;
} }
return -ENOIOCTLCMD; return -ENOIOCTLCMD;
} }
#endif #endif
@ -1646,7 +1651,7 @@ init_sg(void)
else else
def_reserved_size = sg_big_buff; def_reserved_size = sg_big_buff;
rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
SG_MAX_DEVS, "sg"); SG_MAX_DEVS, "sg");
if (rc) if (rc)
return rc; return rc;
@ -2304,7 +2309,7 @@ static const struct file_operations adio_fops = {
}; };
static int sg_proc_single_open_dressz(struct inode *inode, struct file *file); static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
static ssize_t sg_proc_write_dressz(struct file *filp, static ssize_t sg_proc_write_dressz(struct file *filp,
const char __user *buffer, size_t count, loff_t *off); const char __user *buffer, size_t count, loff_t *off);
static const struct file_operations dressz_fops = { static const struct file_operations dressz_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
@ -2444,7 +2449,7 @@ static int sg_proc_single_open_adio(struct inode *inode, struct file *file)
return single_open(file, sg_proc_seq_show_int, &sg_allow_dio); return single_open(file, sg_proc_seq_show_int, &sg_allow_dio);
} }
static ssize_t static ssize_t
sg_proc_write_adio(struct file *filp, const char __user *buffer, sg_proc_write_adio(struct file *filp, const char __user *buffer,
size_t count, loff_t *off) size_t count, loff_t *off)
{ {
@ -2465,7 +2470,7 @@ static int sg_proc_single_open_dressz(struct inode *inode, struct file *file)
return single_open(file, sg_proc_seq_show_int, &sg_big_buff); return single_open(file, sg_proc_seq_show_int, &sg_big_buff);
} }
static ssize_t static ssize_t
sg_proc_write_dressz(struct file *filp, const char __user *buffer, sg_proc_write_dressz(struct file *filp, const char __user *buffer,
size_t count, loff_t *off) size_t count, loff_t *off)
{ {
@ -2640,6 +2645,9 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
seq_puts(s, srp->done ? seq_puts(s, srp->done ?
((1 == srp->done) ? "rcv:" : "fin:") ((1 == srp->done) ? "rcv:" : "fin:")
: "act:"); : "act:");
seq_printf(s, srp->done ?
((1 == srp->done) ? "rcv:" : "fin:")
: "act:");
seq_printf(s, " id=%d blen=%d", seq_printf(s, " id=%d blen=%d",
srp->header.pack_id, blen); srp->header.pack_id, blen);
if (srp->done) if (srp->done)