Commit 250f7a5f authored by Dan Carpenter's avatar Dan Carpenter Committed by Mauro Carvalho Chehab

[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: default avatarDan Carpenter <error27@gmail.com>
Reviewed-by: default avatarJarod Wilson <jarod@redhat.com>
Acked-by: default avatarJarod Wilson <jarod@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 5c769a68
...@@ -647,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file, ...@@ -647,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
if (!buf) if (!buf)
return -ENOMEM; return -ENOMEM;
if (mutex_lock_interruptible(&ir->irctl_lock)) if (mutex_lock_interruptible(&ir->irctl_lock)) {
return -ERESTARTSYS; ret = -ERESTARTSYS;
goto out_unlocked;
}
if (!ir->attached) { if (!ir->attached) {
mutex_unlock(&ir->irctl_lock); ret = -ENODEV;
return -ENODEV; goto out_locked;
} }
if (length % ir->chunk_size) { if (length % ir->chunk_size) {
dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n", ret = -EINVAL;
ir->d.name, ir->d.minor); goto out_locked;
mutex_unlock(&ir->irctl_lock);
return -EINVAL;
} }
/* /*
...@@ -709,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file, ...@@ -709,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file,
lirc_buffer_read(ir->buf, buf); lirc_buffer_read(ir->buf, buf);
ret = copy_to_user((void *)buffer+written, buf, ret = copy_to_user((void *)buffer+written, buf,
ir->buf->chunk_size); ir->buf->chunk_size);
if (!ret)
written += ir->buf->chunk_size; written += ir->buf->chunk_size;
else
ret = -EFAULT;
} }
} }
remove_wait_queue(&ir->buf->wait_poll, &wait); remove_wait_queue(&ir->buf->wait_poll, &wait);
set_current_state(TASK_RUNNING); set_current_state(TASK_RUNNING);
out_locked:
mutex_unlock(&ir->irctl_lock); mutex_unlock(&ir->irctl_lock);
out_unlocked: out_unlocked:
kfree(buf); kfree(buf);
dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n", dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret); ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
return ret ? ret : written; return ret ? ret : written;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment