lkml.org 
[lkml]   [2013]   [Nov]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subject[PATCH] block: cmdline-parser: perfect cmdline format checking
Date
From: Cai Zhiyong <caizhiyong@huawei.com>
Date: Sat, 9 Nov 2013 19:27:38 +0800
Subject: [PATCH] block: cmdline-parser: perfect cmdline format checking

-Fix compile warning with value and function undeclared.
this reported by <fengguang.wu@intel.com> and
Randy Dunlap <rdunlap@infradead.org>

-perfect cmdline format checking, make the error information clear
for understand, make this lib fully equivalent to the old parser
in drivers/mtd/cmdlinepart.c

Signed-off-by: Cai Zhiyong <caizhiyong@huawei.com>
---
block/cmdline-parser.c | 86 +++++++++++++++++++++++++++++++-----------
include/linux/cmdline-parser.h | 1 +
2 files changed, 65 insertions(+), 22 deletions(-)

diff --git a/block/cmdline-parser.c b/block/cmdline-parser.c
index 9dbc67e..39b6cf4 100644
--- a/block/cmdline-parser.c
+++ b/block/cmdline-parser.c
@@ -6,10 +6,15 @@
*/
#include <linux/export.h>
#include <linux/cmdline-parser.h>
+#include <linux/slab.h>
+
+#define PARSER "cmdline-parser: "

static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
{
int ret = 0;
+ int lastpart = 0;
+ char *partorg = partdef;
struct cmdline_subpart *new_subpart;

*subpart = NULL;
@@ -21,10 +26,12 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
if (*partdef == '-') {
new_subpart->size = (sector_t)(~0ULL);
partdef++;
+ lastpart = 1;
} else {
new_subpart->size = (sector_t)memparse(partdef, &partdef);
if (new_subpart->size < (sector_t)PAGE_SIZE) {
- pr_warn("cmdline partition size is invalid.");
+ pr_warn(PARSER "partition '%s' size '0x%llx' too small.",
+ partorg, new_subpart->size);
ret = -EINVAL;
goto fail;
}
@@ -42,13 +49,19 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
char *next = strchr(++partdef, ')');

if (!next) {
- pr_warn("cmdline partition format is invalid.");
+ pr_warn(PARSER "partition '%s' has no closing ')' "
+ "found in partition name.", partorg);
ret = -EINVAL;
goto fail;
}

- length = min_t(int, next - partdef,
- sizeof(new_subpart->name) - 1);
+ length = (int)(next - partdef);
+ if (length > sizeof(new_subpart->name) - 1) {
+ pr_warn(PARSER "partition '%s' partition name too long,"
+ " truncating.", partorg);
+ length = sizeof(new_subpart->name) - 1;
+ }
+
strncpy(new_subpart->name, partdef, length);
new_subpart->name[length] = '\0';

@@ -68,8 +81,15 @@ static int parse_subpart(struct cmdline_subpart **subpart, char *partdef)
partdef += 2;
}

+ if (*partdef) {
+ pr_warn(PARSER "partition '%s' has bad character '%c' after"
+ " partition.", partorg, *partdef);
+ ret = -EINVAL;
+ goto fail;
+ }
+
*subpart = new_subpart;
- return 0;
+ return lastpart;
fail:
kfree(new_subpart);
return ret;
@@ -86,14 +106,13 @@ static void free_subpart(struct cmdline_parts *parts)
}
}

-static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
+static int parse_parts(struct cmdline_parts **parts, char *bdevdef)
{
int ret = -EINVAL;
char *next;
int length;
struct cmdline_subpart **next_subpart;
struct cmdline_parts *newparts;
- char buf[BDEVNAME_SIZE + 32 + 4];

*parts = NULL;

@@ -102,14 +121,21 @@ static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
return -ENOMEM;

next = strchr(bdevdef, ':');
- if (!next) {
- pr_warn("cmdline partition has no block device.");
+ if (!next || next == bdevdef) {
+ pr_warn(PARSER "partition '%s' has no block device.", bdevdef);
goto fail;
}

- length = min_t(int, next - bdevdef, sizeof(newparts->name) - 1);
+ length = (int)(next - bdevdef);
+ if (length > sizeof(newparts->name) - 1) {
+ pr_warn(PARSER "partition '%s' device name too long, "
+ "truncating.", bdevdef);
+ length = sizeof(newparts->name) - 1;
+ }
+
strncpy(newparts->name, bdevdef, length);
newparts->name[length] = '\0';
+
newparts->nr_subparts = 0;

next_subpart = &newparts->subpart;
@@ -117,23 +143,26 @@ static int parse_parts(struct cmdline_parts **parts, const char *bdevdef)
while (next && *(++next)) {
bdevdef = next;
next = strchr(bdevdef, ',');
+ if (next)
+ *next = '\0';

- length = (!next) ? (sizeof(buf) - 1) :
- min_t(int, next - bdevdef, sizeof(buf) - 1);
-
- strncpy(buf, bdevdef, length);
- buf[length] = '\0';
-
- ret = parse_subpart(next_subpart, buf);
- if (ret)
+ ret = parse_subpart(next_subpart, bdevdef);
+ if (ret < 0) {
goto fail;
+ } else if (ret > 0 && next) {
+ pr_warn(PARSER "no partitions allowed after a "
+ "fill-up partition.");
+ ret = -EINVAL;
+ goto fail;
+ }

newparts->nr_subparts++;
next_subpart = &(*next_subpart)->next_subpart;
}

if (!newparts->subpart) {
- pr_warn("cmdline partition has no valid partition.");
+ pr_warn(PARSER "block device '%s' has no valid"
+ " partition.", newparts->name);
ret = -EINVAL;
goto fail;
}
@@ -192,7 +221,7 @@ int cmdline_parts_parse(struct cmdline_parts **parts, const char *cmdline)
}

if (!*parts) {
- pr_warn("cmdline partition has no valid partition.");
+ pr_warn(PARSER "no found valid partition.");
ret = -EINVAL;
goto fail;
}
@@ -237,11 +266,24 @@ int cmdline_parts_set(struct cmdline_parts *parts, sector_t disk_size,
else
from = subpart->from;

- if (from >= disk_size)
+ if (subpart->name[0] == '\0')
+ snprintf(subpart->name, sizeof(subpart->name),
+ "partition%03d", slot);
+
+ if (from >= disk_size) {
+ pr_warn(PARSER "partition '%s' offset exceeds device"
+ " '%s' size '0x%llx', ignoring.",
+ subpart->name, parts->name, disk_size);
break;
+ }

- if (subpart->size > (disk_size - from))
+ if (subpart->size > (disk_size - from)) {
+ if (subpart->size != (sector_t)(~0ULL))
+ pr_warn(PARSER "partition '%s' size exceeds "
+ "device '%s' size '0x%llx', truncating.",
+ subpart->name, parts->name, disk_size);
subpart->size = disk_size - from;
+ }

from += subpart->size;

diff --git a/include/linux/cmdline-parser.h b/include/linux/cmdline-parser.h
index 43b65a9..c6491b2 100644
--- a/include/linux/cmdline-parser.h
+++ b/include/linux/cmdline-parser.h
@@ -8,6 +8,7 @@
#define CMDLINEPARSEH

#include <linux/blkdev.h>
+#include <linux/fs.h>

/* partition flags */
#define PF_RDONLY 0x01 /* Device is read only */
--
1.8.1.5


\
 
 \ /
  Last update: 2013-11-09 13:01    [W:0.039 / U:0.548 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site