aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Carpenter <error27@gmail.com>2010-11-17 00:20:15 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-20 11:11:15 -0500
commit250f7a5f62a08985af5cf7728ae7ba9edbfdc0a9 (patch)
tree0aa3cbc24524efbb1fc9f29608a44e20b68c1d06
parent5c769a68beaee924e1dc90bf06e1b087b1d46237 (diff)
[media] lirc_dev: fixes in lirc_dev_fop_read()
This makes several changes but they're in one function and sort of related: "buf" was leaked on error. The leak if we try to read an invalid length is the main concern because it could be triggered over and over. If the copy_to_user() failed, then the original code returned the number of bytes remaining. read() is supposed to be the opposite way, where we return the number of bytes copied. I changed it to just return -EFAULT on errors. Also I changed the debug output from "-EFAULT" to just "<fail>" because it isn't -EFAULT necessarily. And since we go though that path if the length is invalid now, there was another debug print that I removed. Signed-off-by: Dan Carpenter <error27@gmail.com> Reviewed-by: Jarod Wilson <jarod@redhat.com> Acked-by: Jarod Wilson <jarod@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/IR/lirc_dev.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/drivers/media/IR/lirc_dev.c b/drivers/media/IR/lirc_dev.c
index 8ab9d87f3a4..756656e17bd 100644
--- a/drivers/media/IR/lirc_dev.c
+++ b/drivers/media/IR/lirc_dev.c
@@ -647,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
647 if (!buf) 647 if (!buf)
648 return -ENOMEM; 648 return -ENOMEM;
649 649
650 if (mutex_lock_interruptible(&ir->irctl_lock)) 650 if (mutex_lock_interruptible(&ir->irctl_lock)) {
651 return -ERESTARTSYS; 651 ret = -ERESTARTSYS;
652 goto out_unlocked;
653 }
652 if (!ir->attached) { 654 if (!ir->attached) {
653 mutex_unlock(&ir->irctl_lock); 655 ret = -ENODEV;
654 return -ENODEV; 656 goto out_locked;
655 } 657 }
656 658
657 if (length % ir->chunk_size) { 659 if (length % ir->chunk_size) {
658 dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n", 660 ret = -EINVAL;
659 ir->d.name, ir->d.minor); 661 goto out_locked;
660 mutex_unlock(&ir->irctl_lock);
661 return -EINVAL;
662 } 662 }
663 663
664 /* 664 /*
@@ -709,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file,
709 lirc_buffer_read(ir->buf, buf); 709 lirc_buffer_read(ir->buf, buf);
710 ret = copy_to_user((void *)buffer+written, buf, 710 ret = copy_to_user((void *)buffer+written, buf,
711 ir->buf->chunk_size); 711 ir->buf->chunk_size);
712 written += ir->buf->chunk_size; 712 if (!ret)
713 written += ir->buf->chunk_size;
714 else
715 ret = -EFAULT;
713 } 716 }
714 } 717 }
715 718
716 remove_wait_queue(&ir->buf->wait_poll, &wait); 719 remove_wait_queue(&ir->buf->wait_poll, &wait);
717 set_current_state(TASK_RUNNING); 720 set_current_state(TASK_RUNNING);
721
722out_locked:
718 mutex_unlock(&ir->irctl_lock); 723 mutex_unlock(&ir->irctl_lock);
719 724
720out_unlocked: 725out_unlocked:
721 kfree(buf); 726 kfree(buf);
722 dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", 727 dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
723 ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); 728 ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
724 729
725 return ret ? ret : written; 730 return ret ? ret : written;
726} 731}