Skip to content

Commit 750b679

Browse files
Robb Glasserfranciscofranco
authored andcommitted
Prevent potential double frees in sg driver
sg_ioctl could be spammed by requests, leading to a double free in __free_pages. This protects the entry points of sg_ioctl where the memory could be corrupted by a double call to __free_pages if multiple requests are happening concurrently. Bug:35644812 Signed-off-by: Robb Glasser <[email protected]> Git-commit: 22d8e80738b5ce8784d59b48b0b051a520da4bec Git-repo: https://android.googlesource.com/kernel/msm [[email protected]: Resolved trivial conflicts] Signed-off-by: Srinivasa Rao Kuppala <[email protected]> Signed-off-by: Sayali Lokhande <[email protected]> Signed-off-by: Chennuru Rajeshwar Reddy <[email protected]> change-Id: Ie13f65beb6974430f90292e2742841b26aecb8b1 Signed-off-by: Francisco Franco <[email protected]>
1 parent a8f6a4d commit 750b679

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

drivers/scsi/sg.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
172172

173173
typedef struct sg_device { /* holds the state of each scsi generic device */
174174
struct scsi_device *device;
175+
struct mutex open_rel_lock;
175176
wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */
176177
struct mutex open_rel_lock; /* held when in open() or release() */
177178
int sg_tablesize; /* adapter's max scatter-gather table size */
@@ -407,7 +408,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
407408
retval = 0; /* following macro beats race condition */
408409
__wait_event_interruptible(sfp->read_wait,
409410
(sdp->detached ||
410-
(srp = sg_get_rq_mark(sfp, req_pack_id))),
411+
(srp = sg_get_rq_mark(sfp, req_pack_id))),
411412
retval);
412413
if (sdp->detached) {
413414
retval = -ENODEV;
@@ -467,7 +468,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
467468
old_hdr->result = EIO;
468469
break;
469470
case DID_ERROR:
470-
old_hdr->result = (srp->sense_b[0] == 0 &&
471+
old_hdr->result = (srp->sense_b[0] == 0 &&
471472
hp->masked_status == GOOD) ? 0 : EIO;
472473
break;
473474
default:
@@ -994,8 +995,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
994995
if (srp) {
995996
rinfo[val].req_state = srp->done + 1;
996997
rinfo[val].problem =
997-
srp->header.masked_status &
998-
srp->header.host_status &
998+
srp->header.masked_status &
999+
srp->header.host_status &
9991000
srp->header.driver_status;
10001001
if (srp->done)
10011002
rinfo[val].duration =
@@ -1016,7 +1017,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg)
10161017
}
10171018
}
10181019
read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
1019-
result = __copy_to_user(p, rinfo,
1020+
result = __copy_to_user(p, rinfo,
10201021
SZ_SG_REQ_INFO * SG_MAX_QUEUE);
10211022
result = result ? -EFAULT : 0;
10221023
kfree(rinfo);
@@ -1130,14 +1131,14 @@ static long sg_compat_ioctl(struct file *filp, unsigned int cmd_in, unsigned lon
11301131
return -ENXIO;
11311132

11321133
sdev = sdp->device;
1133-
if (sdev->host->hostt->compat_ioctl) {
1134+
if (sdev->host->hostt->compat_ioctl) {
11341135
int ret;
11351136

11361137
ret = sdev->host->hostt->compat_ioctl(sdev, cmd_in, (void __user *)arg);
11371138

11381139
return ret;
11391140
}
1140-
1141+
11411142
return -ENOIOCTLCMD;
11421143
}
11431144
#endif
@@ -1416,6 +1417,7 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
14161417
disk->first_minor = k;
14171418
sdp->disk = disk;
14181419
sdp->device = scsidp;
1420+
mutex_init(&sdp->open_rel_lock);
14191421
INIT_LIST_HEAD(&sdp->sfds);
14201422
init_waitqueue_head(&sdp->o_excl_wait);
14211423
sdp->sg_tablesize = queue_max_segments(q);
@@ -1603,7 +1605,7 @@ init_sg(void)
16031605
else
16041606
def_reserved_size = sg_big_buff;
16051607

1606-
rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
1608+
rc = register_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0),
16071609
SG_MAX_DEVS, "sg");
16081610
if (rc)
16091611
return rc;
@@ -2256,7 +2258,7 @@ static const struct file_operations adio_fops = {
22562258
};
22572259

22582260
static int sg_proc_single_open_dressz(struct inode *inode, struct file *file);
2259-
static ssize_t sg_proc_write_dressz(struct file *filp,
2261+
static ssize_t sg_proc_write_dressz(struct file *filp,
22602262
const char __user *buffer, size_t count, loff_t *off);
22612263
static const struct file_operations dressz_fops = {
22622264
.owner = THIS_MODULE,
@@ -2396,7 +2398,7 @@ static int sg_proc_single_open_adio(struct inode *inode, struct file *file)
23962398
return single_open(file, sg_proc_seq_show_int, &sg_allow_dio);
23972399
}
23982400

2399-
static ssize_t
2401+
static ssize_t
24002402
sg_proc_write_adio(struct file *filp, const char __user *buffer,
24012403
size_t count, loff_t *off)
24022404
{
@@ -2417,7 +2419,7 @@ static int sg_proc_single_open_dressz(struct inode *inode, struct file *file)
24172419
return single_open(file, sg_proc_seq_show_int, &sg_big_buff);
24182420
}
24192421

2420-
static ssize_t
2422+
static ssize_t
24212423
sg_proc_write_dressz(struct file *filp, const char __user *buffer,
24222424
size_t count, loff_t *off)
24232425
{
@@ -2574,7 +2576,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
25742576
hp = &srp->header;
25752577
new_interface = (hp->interface_id == '\0') ? 0 : 1;
25762578
if (srp->res_used) {
2577-
if (new_interface &&
2579+
if (new_interface &&
25782580
(SG_FLAG_MMAP_IO & hp->flags))
25792581
cp = " mmap>> ";
25802582
else
@@ -2588,7 +2590,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
25882590
seq_printf(s, cp);
25892591
blen = srp->data.bufflen;
25902592
usg = srp->data.k_use_sg;
2591-
seq_printf(s, srp->done ?
2593+
seq_printf(s, srp->done ?
25922594
((1 == srp->done) ? "rcv:" : "fin:")
25932595
: "act:");
25942596
seq_printf(s, " id=%d blen=%d",

0 commit comments

Comments
 (0)