| From ef951599074ba4fad2d0efa0a977129b41e6d203 Mon Sep 17 00:00:00 2001 |
| From: Kees Cook <keescook@chromium.org> |
| Date: Thu, 17 Mar 2016 14:22:50 -0700 |
| Subject: lib: move strtobool() to kstrtobool() |
| |
| From: Kees Cook <keescook@chromium.org> |
| |
| commit ef951599074ba4fad2d0efa0a977129b41e6d203 upstream. |
| |
| Create the kstrtobool_from_user() helper and move strtobool() logic into |
| the new kstrtobool() (matching all the other kstrto* functions). |
| Provides an inline wrapper for existing strtobool() callers. |
| |
| Signed-off-by: Kees Cook <keescook@chromium.org> |
| Cc: Joe Perches <joe@perches.com> |
| Cc: Andy Shevchenko <andy.shevchenko@gmail.com> |
| Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk> |
| Cc: Daniel Borkmann <daniel@iogearbox.net> |
| Cc: Amitkumar Karwar <akarwar@marvell.com> |
| Cc: Nishant Sarmukadam <nishants@marvell.com> |
| Cc: Kalle Valo <kvalo@codeaurora.org> |
| Cc: Steve French <sfrench@samba.org> |
| Cc: Michael Ellerman <mpe@ellerman.id.au> |
| Cc: Heiko Carstens <heiko.carstens@de.ibm.com> |
| Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| include/linux/kernel.h | 2 + |
| include/linux/string.h | 6 ++++- |
| lib/kstrtox.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ |
| lib/string.c | 29 ---------------------------- |
| 4 files changed, 57 insertions(+), 30 deletions(-) |
| |
| --- a/include/linux/kernel.h |
| +++ b/include/linux/kernel.h |
| @@ -356,6 +356,7 @@ int __must_check kstrtou16(const char *s |
| int __must_check kstrtos16(const char *s, unsigned int base, s16 *res); |
| int __must_check kstrtou8(const char *s, unsigned int base, u8 *res); |
| int __must_check kstrtos8(const char *s, unsigned int base, s8 *res); |
| +int __must_check kstrtobool(const char *s, bool *res); |
| |
| int __must_check kstrtoull_from_user(const char __user *s, size_t count, unsigned int base, unsigned long long *res); |
| int __must_check kstrtoll_from_user(const char __user *s, size_t count, unsigned int base, long long *res); |
| @@ -367,6 +368,7 @@ int __must_check kstrtou16_from_user(con |
| int __must_check kstrtos16_from_user(const char __user *s, size_t count, unsigned int base, s16 *res); |
| int __must_check kstrtou8_from_user(const char __user *s, size_t count, unsigned int base, u8 *res); |
| int __must_check kstrtos8_from_user(const char __user *s, size_t count, unsigned int base, s8 *res); |
| +int __must_check kstrtobool_from_user(const char __user *s, size_t count, bool *res); |
| |
| static inline int __must_check kstrtou64_from_user(const char __user *s, size_t count, unsigned int base, u64 *res) |
| { |
| --- a/include/linux/string.h |
| +++ b/include/linux/string.h |
| @@ -127,7 +127,11 @@ extern char **argv_split(gfp_t gfp, cons |
| extern void argv_free(char **argv); |
| |
| extern bool sysfs_streq(const char *s1, const char *s2); |
| -extern int strtobool(const char *s, bool *res); |
| +extern int kstrtobool(const char *s, bool *res); |
| +static inline int strtobool(const char *s, bool *res) |
| +{ |
| + return kstrtobool(s, res); |
| +} |
| |
| #ifdef CONFIG_BINARY_PRINTF |
| int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args); |
| --- a/lib/kstrtox.c |
| +++ b/lib/kstrtox.c |
| @@ -321,6 +321,56 @@ int kstrtos8(const char *s, unsigned int |
| } |
| EXPORT_SYMBOL(kstrtos8); |
| |
| +/** |
| + * kstrtobool - convert common user inputs into boolean values |
| + * @s: input string |
| + * @res: result |
| + * |
| + * This routine returns 0 iff the first character is one of 'Yy1Nn0'. |
| + * Otherwise it will return -EINVAL. Value pointed to by res is |
| + * updated upon finding a match. |
| + */ |
| +int kstrtobool(const char *s, bool *res) |
| +{ |
| + if (!s) |
| + return -EINVAL; |
| + |
| + switch (s[0]) { |
| + case 'y': |
| + case 'Y': |
| + case '1': |
| + *res = true; |
| + return 0; |
| + case 'n': |
| + case 'N': |
| + case '0': |
| + *res = false; |
| + return 0; |
| + default: |
| + break; |
| + } |
| + |
| + return -EINVAL; |
| +} |
| +EXPORT_SYMBOL(kstrtobool); |
| + |
| +/* |
| + * Since "base" would be a nonsense argument, this open-codes the |
| + * _from_user helper instead of using the helper macro below. |
| + */ |
| +int kstrtobool_from_user(const char __user *s, size_t count, bool *res) |
| +{ |
| + /* Longest string needed to differentiate, newline, terminator */ |
| + char buf[4]; |
| + |
| + count = min(count, sizeof(buf) - 1); |
| + if (copy_from_user(buf, s, count)) |
| + return -EFAULT; |
| + buf[count] = '\0'; |
| + return kstrtobool(buf, res); |
| +} |
| +EXPORT_SYMBOL(kstrtobool_from_user); |
| + |
| #define kstrto_from_user(f, g, type) \ |
| int f(const char __user *s, size_t count, unsigned int base, type *res) \ |
| { \ |
| --- a/lib/string.c |
| +++ b/lib/string.c |
| @@ -630,35 +630,6 @@ bool sysfs_streq(const char *s1, const c |
| } |
| EXPORT_SYMBOL(sysfs_streq); |
| |
| -/** |
| - * strtobool - convert common user inputs into boolean values |
| - * @s: input string |
| - * @res: result |
| - * |
| - * This routine returns 0 iff the first character is one of 'Yy1Nn0'. |
| - * Otherwise it will return -EINVAL. Value pointed to by res is |
| - * updated upon finding a match. |
| - */ |
| -int strtobool(const char *s, bool *res) |
| -{ |
| - switch (s[0]) { |
| - case 'y': |
| - case 'Y': |
| - case '1': |
| - *res = true; |
| - break; |
| - case 'n': |
| - case 'N': |
| - case '0': |
| - *res = false; |
| - break; |
| - default: |
| - return -EINVAL; |
| - } |
| - return 0; |
| -} |
| -EXPORT_SYMBOL(strtobool); |
| - |
| #ifndef __HAVE_ARCH_MEMSET |
| /** |
| * memset - Fill a region of memory with the given value |