aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Young <sean@mess.org>2017-12-13 16:09:21 -0500
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2017-12-18 15:21:28 -0500
commita74b2bff59455d466a4422ee2f49151ffd65a2ab (patch)
tree7e440794300206a08e00bff023f6565f5ed2eb6b
parentb996157dd2b9de57a61a6abbe4ab2d63e1d10908 (diff)
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>
-rw-r--r--drivers/media/rc/lirc_dev.c35
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,
231{ 231{
232 struct lirc_fh *fh = file->private_data; 232 struct lirc_fh *fh = file->private_data;
233 struct rc_dev *dev = fh->rc; 233 struct rc_dev *dev = fh->rc;
234 unsigned int *txbuf = NULL; 234 unsigned int *txbuf;
235 struct ir_raw_event *raw = NULL; 235 struct ir_raw_event *raw = NULL;
236 ssize_t ret; 236 ssize_t ret;
237 size_t count; 237 size_t count;
@@ -246,14 +246,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
246 246
247 if (!dev->registered) { 247 if (!dev->registered) {
248 ret = -ENODEV; 248 ret = -ENODEV;
249 goto out; 249 goto out_unlock;
250 } 250 }
251 251
252 start = ktime_get(); 252 start = ktime_get();
253 253
254 if (!dev->tx_ir) { 254 if (!dev->tx_ir) {
255 ret = -EINVAL; 255 ret = -EINVAL;
256 goto out; 256 goto out_unlock;
257 } 257 }
258 258
259 if (fh->send_mode == LIRC_MODE_SCANCODE) { 259 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,
261 261
262 if (n != sizeof(scan)) { 262 if (n != sizeof(scan)) {
263 ret = -EINVAL; 263 ret = -EINVAL;
264 goto out; 264 goto out_unlock;
265 } 265 }
266 266
267 if (copy_from_user(&scan, buf, sizeof(scan))) { 267 if (copy_from_user(&scan, buf, sizeof(scan))) {
268 ret = -EFAULT; 268 ret = -EFAULT;
269 goto out; 269 goto out_unlock;
270 } 270 }
271 271
272 if (scan.flags || scan.keycode || scan.timestamp) { 272 if (scan.flags || scan.keycode || scan.timestamp) {
273 ret = -EINVAL; 273 ret = -EINVAL;
274 goto out; 274 goto out_unlock;
275 } 275 }
276 276
277 /* 277 /*
@@ -283,26 +283,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
283 if (scan.scancode > U32_MAX || 283 if (scan.scancode > U32_MAX ||
284 !rc_validate_scancode(scan.rc_proto, scan.scancode)) { 284 !rc_validate_scancode(scan.rc_proto, scan.scancode)) {
285 ret = -EINVAL; 285 ret = -EINVAL;
286 goto out; 286 goto out_unlock;
287 } 287 }
288 288
289 raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL); 289 raw = kmalloc_array(LIRCBUF_SIZE, sizeof(*raw), GFP_KERNEL);
290 if (!raw) { 290 if (!raw) {
291 ret = -ENOMEM; 291 ret = -ENOMEM;
292 goto out; 292 goto out_unlock;
293 } 293 }
294 294
295 ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode, 295 ret = ir_raw_encode_scancode(scan.rc_proto, scan.scancode,
296 raw, LIRCBUF_SIZE); 296 raw, LIRCBUF_SIZE);
297 if (ret < 0) 297 if (ret < 0)
298 goto out; 298 goto out_kfree;
299 299
300 count = ret; 300 count = ret;
301 301
302 txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL); 302 txbuf = kmalloc_array(count, sizeof(unsigned int), GFP_KERNEL);
303 if (!txbuf) { 303 if (!txbuf) {
304 ret = -ENOMEM; 304 ret = -ENOMEM;
305 goto out; 305 goto out_kfree;
306 } 306 }
307 307
308 for (i = 0; i < count; i++) 308 for (i = 0; i < count; i++)
@@ -318,26 +318,26 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
318 } else { 318 } else {
319 if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) { 319 if (n < sizeof(unsigned int) || n % sizeof(unsigned int)) {
320 ret = -EINVAL; 320 ret = -EINVAL;
321 goto out; 321 goto out_unlock;
322 } 322 }
323 323
324 count = n / sizeof(unsigned int); 324 count = n / sizeof(unsigned int);
325 if (count > LIRCBUF_SIZE || count % 2 == 0) { 325 if (count > LIRCBUF_SIZE || count % 2 == 0) {
326 ret = -EINVAL; 326 ret = -EINVAL;
327 goto out; 327 goto out_unlock;
328 } 328 }
329 329
330 txbuf = memdup_user(buf, n); 330 txbuf = memdup_user(buf, n);
331 if (IS_ERR(txbuf)) { 331 if (IS_ERR(txbuf)) {
332 ret = PTR_ERR(txbuf); 332 ret = PTR_ERR(txbuf);
333 goto out; 333 goto out_unlock;
334 } 334 }
335 } 335 }
336 336
337 for (i = 0; i < count; i++) { 337 for (i = 0; i < count; i++) {
338 if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) { 338 if (txbuf[i] > IR_MAX_DURATION / 1000 - duration || !txbuf[i]) {
339 ret = -EINVAL; 339 ret = -EINVAL;
340 goto out; 340 goto out_kfree;
341 } 341 }
342 342
343 duration += txbuf[i]; 343 duration += txbuf[i];
@@ -345,7 +345,7 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
345 345
346 ret = dev->tx_ir(dev, txbuf, count); 346 ret = dev->tx_ir(dev, txbuf, count);
347 if (ret < 0) 347 if (ret < 0)
348 goto out; 348 goto out_kfree;
349 349
350 if (fh->send_mode == LIRC_MODE_SCANCODE) { 350 if (fh->send_mode == LIRC_MODE_SCANCODE) {
351 ret = n; 351 ret = n;
@@ -368,10 +368,11 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
368 schedule_timeout(usecs_to_jiffies(towait)); 368 schedule_timeout(usecs_to_jiffies(towait));
369 } 369 }
370 370
371out: 371out_kfree:
372 mutex_unlock(&dev->lock);
373 kfree(txbuf); 372 kfree(txbuf);
374 kfree(raw); 373 kfree(raw);
374out_unlock:
375 mutex_unlock(&dev->lock);
375 return ret; 376 return ret;
376} 377}
377 378