Introduce 'memvalue()' which uses 'memparse()' to parse a string with optional memory suffix into a non-negative number. If parsing has succeeded, returns 0 and stores the result at the location specified by the second argument. Otherwise returns -EINVAL and leaves the location untouched.
Suggested-by: Christoph Hellwig <[email protected]> Suggested-by: Kees Cook <[email protected]> Signed-off-by: Dmitry Antipov <[email protected]> --- v3: adjust as suggested by Kees and bump version to match the series --- include/linux/string.h | 1 + lib/cmdline.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/include/linux/string.h b/include/linux/string.h index 1b564c36d721..470c7051c58b 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -319,6 +319,7 @@ DEFINE_FREE(argv_free, char **, if (!IS_ERR_OR_NULL(_T)) argv_free(_T)) extern int get_option(char **str, int *pint); extern char *get_options(const char *str, int nints, int *ints); extern unsigned long long memparse(const char *ptr, char **retptr); +extern int __must_check memvalue(const char *ptr, unsigned long long *valptr); extern bool parse_option_str(const char *str, const char *option); extern char *next_arg(char *args, char **param, char **val); diff --git a/lib/cmdline.c b/lib/cmdline.c index 90ed997d9570..cf81c6363f6c 100644 --- a/lib/cmdline.c +++ b/lib/cmdline.c @@ -190,6 +190,32 @@ unsigned long long memparse(const char *ptr, char **retptr) } EXPORT_SYMBOL(memparse); +/** + * memvalue - Wrap memparse() with simple error detection + * @ptr: Where parse begins + * @valptr: Where to store result + * + * Unconditionally returns -EINVAL for a presumably negative value. + * Otherwise uses memparse() to parse a string into a number stored + * at @valptr and returns 0 or -EINVAL if an unrecognized character + * was encountered. For a non-zero return value, memory at @valptr + * is left untouched. + */ +int __must_check memvalue(const char *ptr, unsigned long long *valptr) +{ + unsigned long long ret; + char *end; + + if (*ptr == '-') + return -EINVAL; + ret = memparse(ptr, &end); + if (*end) + return -EINVAL; + *valptr = ret; + return 0; +} +EXPORT_SYMBOL(memvalue); + /** * parse_option_str - Parse a string and check an option is set or not * @str: String to be parsed -- 2.52.0
