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);