Skip to content

Commit

Permalink
ACPI / debugfs: Fix buffer overflows, double free
Browse files Browse the repository at this point in the history
File position is not controlled, it may lead to overwrites of arbitrary
kernel memory.  Also the code may kfree() the same pointer multiple
times.

One more flaw is still present: if multiple processes open the file then
all 3 static variables are shared, leading to various race conditions.
They should be moved to file->private_data.

Signed-off-by: Vasiliy Kulikov <segoon@openwall.com>
Reviewed-by: WANG Cong <xiyou.wangcong@gmail.com>
Reviewed-by: Eugene Teo <eugeneteo@kernel.org>
Cc: stable@kernel.org
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
  • Loading branch information
Vasiliy Kulikov authored and Rafael J. Wysocki committed Feb 24, 2011
1 parent 2aa1589 commit 2949ad5
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions drivers/acpi/debugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
size_t count, loff_t *ppos)
{
static char *buf;
static int uncopied_bytes;
static u32 max_size;
static u32 uncopied_bytes;

struct acpi_table_header table;
acpi_status status;

Expand All @@ -37,19 +39,24 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
if (copy_from_user(&table, user_buf,
sizeof(struct acpi_table_header)))
return -EFAULT;
uncopied_bytes = table.length;
buf = kzalloc(uncopied_bytes, GFP_KERNEL);
uncopied_bytes = max_size = table.length;
buf = kzalloc(max_size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
}

if (uncopied_bytes < count) {
kfree(buf);
if (buf == NULL)
return -EINVAL;

if ((*ppos > max_size) ||
(*ppos + count > max_size) ||
(*ppos + count < count) ||
(count > uncopied_bytes))
return -EINVAL;
}

if (copy_from_user(buf + (*ppos), user_buf, count)) {
kfree(buf);
buf = NULL;
return -EFAULT;
}

Expand All @@ -59,6 +66,7 @@ static ssize_t cm_write(struct file *file, const char __user * user_buf,
if (!uncopied_bytes) {
status = acpi_install_method(buf);
kfree(buf);
buf = NULL;
if (ACPI_FAILURE(status))
return -EINVAL;
add_taint(TAINT_OVERRIDDEN_ACPI_TABLE);
Expand Down

0 comments on commit 2949ad5

Please sign in to comment.