Commit 4a5391e7 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] sparse: asus_acpi dereference of userland pointers

Direct sscanf() on userland buffer in procfs ->write_proc().  Fixed.
parent dfc2505c
...@@ -40,6 +40,7 @@ ...@@ -40,6 +40,7 @@
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <acpi/acpi_drivers.h> #include <acpi/acpi_drivers.h>
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
#include <asm/uaccess.h>
#define ASUS_ACPI_VERSION "0.28" #define ASUS_ACPI_VERSION "0.28"
...@@ -480,16 +481,31 @@ read_led(struct asus_hotk *hotk, const char *ledname, int ledmask) ...@@ -480,16 +481,31 @@ read_led(struct asus_hotk *hotk, const char *ledname, int ledmask)
return (hotk->status & ledmask) ? 1 : 0; return (hotk->status & ledmask) ? 1 : 0;
} }
static int parse_arg(const char __user *buf, unsigned long count, int *val)
{
char s[32];
if (!count)
return 0;
if (count > 31)
return -EINVAL;
if (copy_from_user(s, buf, count))
return -EFAULT;
s[count] = 0;
if (sscanf(s, "%i", val) != 1)
return -EINVAL;
return count;
}
/* FIXME: kill extraneous args so it can be called independently */ /* FIXME: kill extraneous args so it can be called independently */
static int static int
write_led(const char *buffer, unsigned long count, struct asus_hotk *hotk, write_led(const char __user *buffer, unsigned long count, struct asus_hotk *hotk,
char *ledname, int ledmask, int invert) char *ledname, int ledmask, int invert)
{ {
int value; int value;
int led_out = 0; int led_out = 0;
if (sscanf(buffer, "%i", &value) == 1) count = parse_arg(buffer, count, &value);
if (count > 0)
led_out = value ? 1 : 0; led_out = value ? 1 : 0;
hotk->status = hotk->status =
...@@ -518,7 +534,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof, ...@@ -518,7 +534,7 @@ proc_read_mled(char *page, char **start, off_t off, int count, int *eof,
static int static int
proc_write_mled(struct file *file, const char *buffer, proc_write_mled(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
...@@ -537,7 +553,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof, ...@@ -537,7 +553,7 @@ proc_read_wled(char *page, char **start, off_t off, int count, int *eof,
} }
static int static int
proc_write_wled(struct file *file, const char *buffer, proc_write_wled(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
...@@ -556,7 +572,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof, ...@@ -556,7 +572,7 @@ proc_read_tled(char *page, char **start, off_t off, int count, int *eof,
} }
static int static int
proc_write_tled(struct file *file, const char *buffer, proc_write_tled(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
...@@ -640,13 +656,14 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, ...@@ -640,13 +656,14 @@ proc_read_lcd(char *page, char **start, off_t off, int count, int *eof,
static int static int
proc_write_lcd(struct file *file, const char *buffer, proc_write_lcd(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
int value; int value;
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
if (sscanf(buffer, "%i", &value) == 1) count = parse_arg(buffer, count, &value);
if (count > 0)
set_lcd_state(hotk, value); set_lcd_state(hotk, value);
return count; return count;
} }
...@@ -707,17 +724,18 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof, ...@@ -707,17 +724,18 @@ proc_read_brn(char *page, char **start, off_t off, int count, int *eof,
} }
static int static int
proc_write_brn(struct file *file, const char *buffer, proc_write_brn(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
int value; int value;
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
if (sscanf(buffer, "%d", &value) == 1) { count = parse_arg(buffer, count, &value);
if (count > 0) {
value = (0 < value) ? ((15 < value) ? 15 : value) : 0; value = (0 < value) ? ((15 < value) ? 15 : value) : 0;
/* 0 <= value <= 15 */ /* 0 <= value <= 15 */
set_brightness(value, hotk); set_brightness(value, hotk);
} else { } else if (count < 0) {
printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
} }
...@@ -756,17 +774,17 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, ...@@ -756,17 +774,17 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof,
* simultaneously, so be warned. See the acpi4asus README for more info. * simultaneously, so be warned. See the acpi4asus README for more info.
*/ */
static int static int
proc_write_disp(struct file *file, const char *buffer, proc_write_disp(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
int value; int value;
struct asus_hotk *hotk = (struct asus_hotk *) data; struct asus_hotk *hotk = (struct asus_hotk *) data;
if (sscanf(buffer, "%d", &value) == 1) count = parse_arg(buffer, count, &value);
if (count > 0)
set_display(value, hotk); set_display(value, hotk);
else { else if (count < 0)
printk(KERN_WARNING "Asus ACPI: Error reading user input\n"); printk(KERN_WARNING "Asus ACPI: Error reading user input\n");
}
return count; return count;
} }
...@@ -774,7 +792,7 @@ proc_write_disp(struct file *file, const char *buffer, ...@@ -774,7 +792,7 @@ proc_write_disp(struct file *file, const char *buffer,
typedef int (proc_readfunc)(char *page, char **start, off_t off, int count, typedef int (proc_readfunc)(char *page, char **start, off_t off, int count,
int *eof, void *data); int *eof, void *data);
typedef int (proc_writefunc)(struct file *file, const char *buffer, typedef int (proc_writefunc)(struct file *file, const char __user *buffer,
unsigned long count, void *data); unsigned long count, void *data);
static int static int
......
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