pse: fix slab-out-of-bounds read of size 1
KASAN reported a slab-out-of-bound read of size 1 when userspace wrote
the port priority to /sys/class/pse/port_priority. This patch fixes the
out-of-bound read as well makes the interface a little more robust
against invalid input.
Change-Id: I17a35ba1abb4c1e5b8222e6502534554580c0e58
diff --git a/pse/pse-sysfs.c b/pse/pse-sysfs.c
index fc2b58a..08c140a 100644
--- a/pse/pse-sysfs.c
+++ b/pse/pse-sysfs.c
@@ -201,31 +201,34 @@
{
struct device *dev;
struct class_dev_iter iter;
- char *substr;
- char *lbuffs;
-
+ char *current_port_priority;
+ char *port_priorities;
+ char *local_buff;
int vi = 0;
size_t bget = 0;
uint8_t port_priority = 0;
struct pse_data *pse_data = get_pse_data(class);
struct pse_port_device *port;
- char *local_buff = kcalloc(count, sizeof(char), GFP_KERNEL);
- lbuffs = memcpy((char *) local_buff, (const char *) buff, count);
+ local_buff = kzalloc(sizeof(char) * (count + 1), GFP_KERNEL);
+ if (!local_buff)
+ return -ENOMEM;
+ memcpy(local_buff, buff, count);
+ port_priorities=local_buff;
+ pr_debug("buff=%s, count=%ld\n", port_priorities, count);
mutex_lock(&pse_data->pse_lock);
- while (bget < count && vi < PSE_MAX_PORTS) {
- substr = strsep(&lbuffs, " ");
- if (substr == NULL) {
+ while (bget <= count && vi < PSE_MAX_PORTS) {
+ current_port_priority = strsep(&port_priorities, " ");
+ if (current_port_priority == NULL) {
break;
}
- printk(KERN_INFO "Looking at substr = %s\n", substr);
- if (kstrtou8(substr, 0, &port_priority) == 0) {
- pse_data->port_priorities[vi++] = port_priority;
- bget += strlen(substr);
- } else {
- printk(KERN_WARNING "Unable to parse the number out of %s\n", substr);
+ pr_debug("input=%s port_priorities=%s Current_port_priority=%s bget=%lu\n", buff, port_priorities, current_port_priority, bget);
+ if (kstrtou8(current_port_priority, 0, &port_priority) < 0) {
+ break;
}
+ pse_data->port_priorities[vi++] = port_priority;
+ bget += strlen(current_port_priority) + 1;
}
class_dev_iter_init(&iter, class, NULL, NULL);
dev = class_dev_iter_next(&iter);
@@ -239,8 +242,8 @@
relink_priority_list(class); /* Rebuild the dubly linked list */
redistribute_power(class); /* Force every port off & on again, to get them to repower in correct, priority order */
mutex_unlock(&pse_data->pse_lock);
-
kfree(local_buff);
+
return count;
}
static struct class_attribute port_priority = __ATTR_RW(port_priority);