DFU: Check the number of arguments and argument string strictly

When parsing the dfu_alt_info, check the number of arguments
and argument string strictly. If there is any garbage data
(which is not able to be parsed correctly) in dfu_alt_info,
that means something wrong and user may make a typo or mis-
understanding about the syntax. Since the dfu_alt_info is
used for updating the firmware, this mistake may lead to
brick the hardware.
Thus it should be checked strictly for making sure there
is no mistake.

Signed-off-by: Masami Hiramatsu <masami.hiramatsu@linaro.org>
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index d747ede..a91da97 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -337,35 +337,34 @@
  *	4th (optional):
  *		mmcpart <num> (access to HW eMMC partitions)
  */
-int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
+int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char **argv, int argc)
 {
 	const char *entity_type;
 	ssize_t second_arg;
 	size_t third_arg;
-
 	struct mmc *mmc;
-
-	const char *argv[3];
-	const char **parg = argv;
+	char *s;
 
-	dfu->data.mmc.dev_num = dectoul(devstr, NULL);
-
-	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
-		*parg = strsep(&s, " \t");
-		if (*parg == NULL) {
-			pr_err("Invalid number of arguments.\n");
-			return -ENODEV;
-		}
-		s = skip_spaces(s);
+	if (argc < 3) {
+		pr_err("The number of parameters are not enough.\n");
+		return -EINVAL;
 	}
 
+	dfu->data.mmc.dev_num = dectoul(devstr, &s);
+	if (*s)
+		return -EINVAL;
+
 	entity_type = argv[0];
 	/*
 	 * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
 	 * with default 10.
 	 */
-	second_arg = simple_strtol(argv[1], NULL, 0);
-	third_arg = simple_strtoul(argv[2], NULL, 0);
+	second_arg = simple_strtol(argv[1], &s, 0);
+	if (*s)
+		return -EINVAL;
+	third_arg = simple_strtoul(argv[2], &s, 0);
+	if (*s)
+		return -EINVAL;
 
 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
 	if (mmc == NULL) {
@@ -390,12 +389,14 @@
 		 * Check for an extra entry at dfu_alt_info env variable
 		 * specifying the mmc HW defined partition number
 		 */
-		if (s)
-			if (!strcmp(strsep(&s, " \t"), "mmcpart")) {
-				s = skip_spaces(s);
-				dfu->data.mmc.hw_partition =
-					simple_strtoul(s, NULL, 0);
+		if (argc > 3) {
+			if (argc != 5 || strcmp(argv[3], "mmcpart")) {
+				pr_err("DFU mmc raw accept 'mmcpart <partnum>' option.\n");
+				return -EINVAL;
 			}
+			dfu->data.mmc.hw_partition =
+				simple_strtoul(argv[4], NULL, 0);
+		}
 
 	} else if (!strcmp(entity_type, "part")) {
 		struct disk_partition partinfo;
@@ -414,15 +415,18 @@
 		 * Check for an extra entry at dfu_alt_info env variable
 		 * specifying the mmc HW defined partition number
 		 */
-		if (s)
-			if (!strcmp(strsep(&s, " \t"), "offset")) {
-				s = skip_spaces(s);
-				offset = simple_strtoul(s, NULL, 0);
+		if (argc > 3) {
+			if (argc != 5 || strcmp(argv[3], "offset")) {
+				pr_err("DFU mmc raw accept 'mmcpart <partnum>' option.\n");
+				return -EINVAL;
 			}
+			dfu->data.mmc.hw_partition =
+				simple_strtoul(argv[4], NULL, 0);
+		}
 
 		dfu->layout			= DFU_RAW_ADDR;
 		dfu->data.mmc.lba_start		= partinfo.start + offset;
-		dfu->data.mmc.lba_size		= partinfo.size-offset;
+		dfu->data.mmc.lba_size		= partinfo.size - offset;
 		dfu->data.mmc.lba_blk_size	= partinfo.blksz;
 	} else if (!strcmp(entity_type, "fat")) {
 		dfu->layout = DFU_FS_FAT;