diff options
author | Sean Young <sean@mess.org> | 2017-12-13 16:09:21 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@s-opensource.com> | 2017-12-18 15:21:28 -0500 |
commit | a74b2bff59455d466a4422ee2f49151ffd65a2ab (patch) | |
tree | 7e440794300206a08e00bff023f6565f5ed2eb6b /drivers/media/rc | |
parent | b996157dd2b9de57a61a6abbe4ab2d63e1d10908 (diff) | |
download | linux-a74b2bff59455d466a4422ee2f49151ffd65a2ab.tar.bz2 |
media: lirc: do not pass ERR_PTR to kfree
If memdup_user() fails, txbuf will be an error pointer and passed
to kfree.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Sean Young <sean@mess.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/rc')
-rw-r--r-- | drivers/media/rc/lirc_dev.c | 35 |
1 files changed, 18 insertions, 17 deletions
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c index 6cedb546c3e0..8618aba152c6 100644 --- a/drivers/media/rc/lirc_dev.c +++ b/drivers/media/rc/lirc_dev.c @@ -231,7 +231,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, { struct lirc_fh *fh = file->private_data; struct rc_dev *dev = fh->rc; - unsigned int *txbuf = NULL; + unsigned int *txbuf; struct ir_raw_event *raw = NULL; ssize_t ret; size_t count; @@ -246,14 +246,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, if (!dev->registered) { ret = -ENODEV; - goto out; + goto out_unlock; } start = ktime_get(); if (!dev->tx_ir) { ret = -EINVAL; - goto out; + goto out_unlock; } if (fh->send_mode == LIRC_MODE_SCANCODE) { @@ -261,17 +261,17 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, if (n != sizeof(scan)) { ret = -EINVAL; - goto out; + goto out_unlock; } if (copy_from_user(&scan, buf, sizeof(scan))) { ret = -EFAULT; - goto out; + goto out_unlock; } if (scan.flags || scan.keycode || scan.timestamp) { ret = -EINVAL; - goto out; + goto out_unlock; } /* @@ -283,26 +283,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, if (scan.scancode > U32_MAX || !rc_validate_scancode(scan.rc_proto, scan.scancode)) { ret = -EINVAL; - goto out; + goto out_unlock; } raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL); if (!raw) { ret = -ENOMEM; - goto out; + goto out_unlock; } ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode, raw, LIRCBUF_SIZE); if (ret < 0) - goto out; + goto out_kfree; count = ret; txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL); if (!txbuf) { ret = -ENOMEM; - goto out; + goto out_kfree; } for (i = 0; i < count; i++) @@ -318,26 +318,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, } else { if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) { ret = -EINVAL; - goto out; + goto out_unlock; } count = n / sizeof(unsigned int); if (count > LIRCBUF_SIZE || count % 2 == 0) { ret = -EINVAL; - goto out; + goto out_unlock; } txbuf = memdup_user(buf, n); if (IS_ERR(txbuf)) { ret = PTR_ERR(txbuf); - goto out; + goto out_unlock; } } for (i = 0; i < count; i++) { if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { ret = -EINVAL; - goto out; + goto out_kfree; } duration += txbuf[i]; @@ -345,7 +345,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, ret = dev->tx_ir(dev, txbuf, count); if (ret < 0) - goto out; + goto out_kfree; if (fh->send_mode == LIRC_MODE_SCANCODE) { ret = n; @@ -368,10 +368,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf, schedule_timeout(usecs_to_jiffies(towait)); } -out: - mutex_unlock(&dev->lock); +out_kfree: kfree(txbuf); kfree(raw); +out_unlock: + mutex_unlock(&dev->lock); return ret; } |