Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ACPI / EC: access user space with get_user()/put_user()

User space pointer may not be dereferenced. Use get_user()/put_user()
instead and check their return codes.

Signed-off-by: Vasiliy Kulikov <segooon@gmail.com>
Signed-off-by: Thomas Renninger <trenn@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Vasiliy Kulikov and committed by
Rafael J. Wysocki
ecde3003 7d132055

+14 -4
+14 -4
drivers/acpi/ec_sys.c
··· 12 12 #include <linux/acpi.h> 13 13 #include <linux/debugfs.h> 14 14 #include <linux/module.h> 15 + #include <linux/uaccess.h> 15 16 #include "internal.h" 16 17 17 18 MODULE_AUTHOR("Thomas Renninger <trenn@suse.de>"); ··· 35 34 * struct acpi_ec *ec = ((struct seq_file *)f->private_data)->private; 36 35 */ 37 36 unsigned int size = EC_SPACE_SIZE; 38 - u8 *data = (u8 *) buf; 39 37 loff_t init_off = *off; 40 38 int err = 0; 41 39 ··· 47 47 size = count; 48 48 49 49 while (size) { 50 - err = ec_read(*off, &data[*off - init_off]); 50 + u8 byte_read; 51 + err = ec_read(*off, &byte_read); 51 52 if (err) 52 53 return err; 54 + if (put_user(byte_read, buf + *off - init_off)) { 55 + if (*off - init_off) 56 + return *off - init_off; /* partial read */ 57 + return -EFAULT; 58 + } 53 59 *off += 1; 54 60 size--; 55 61 } ··· 71 65 72 66 unsigned int size = count; 73 67 loff_t init_off = *off; 74 - u8 *data = (u8 *) buf; 75 68 int err = 0; 76 69 77 70 if (*off >= EC_SPACE_SIZE) ··· 81 76 } 82 77 83 78 while (size) { 84 - u8 byte_write = data[*off - init_off]; 79 + u8 byte_write; 80 + if (get_user(byte_write, buf + *off - init_off)) { 81 + if (*off - init_off) 82 + return *off - init_off; /* partial write */ 83 + return -EFAULT; 84 + } 85 85 err = ec_write(*off, byte_write); 86 86 if (err) 87 87 return err;