path: root/lib
diff options
authorAlexey Dobriyan <adobriyan@gmail.com>2011-05-24 17:13:31 -0700
committersaid m bagheri <ebgheri@steludxu2848.(none)>2011-06-29 10:30:29 +0200
commit39066062cdf7065d32965d4184f06b8766d74453 (patch)
tree3b1cdf77aa611932eafe3a248e1c9f2666af9005 /lib
parent49a6cf160acc5a7be0c479c503a554a5c1035739 (diff)
lib: add kstrto*_from_user()
There is quite a lot of code which does copy_from_user() + strict_strto*() or simple_strto*() combo in slightly different ways. Before doing conversions all over tree, let's get final API correct. Enter kstrtoull_from_user() and friends. Typical code which uses them looks very simple: TYPE val; int rv; rv = kstrtoTYPE_from_user(buf, count, 0, &val); if (rv < 0) return rv; [use val] return count; There is a tiny semantic difference from the plain kstrto*() API -- the latter allows any amount of leading zeroes, while the former copies data into buffer on stack and thus allows leading zeroes as long as it fits into buffer. This shouldn't be a problem for typical usecase "echo 42 > /proc/x". The point is to make reading one integer from userspace _very_ simple and very bug free. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Change-Id: I2f9776b265fb4368abc955ed38ebe60958c01d12 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25238 Tested-by: Jonas ABERG <jonas.aberg@stericsson.com> Reviewed-by: QATEST Reviewed-by: Linus WALLEIJ <linus.walleij@stericsson.com>
Diffstat (limited to 'lib')
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/kstrtox.c b/lib/kstrtox.c
index a235f3cc471..2dbae88090a 100644
--- a/lib/kstrtox.c
+++ b/lib/kstrtox.c
@@ -17,6 +17,7 @@
#include <linux/math64.h>
#include <linux/module.h>
#include <linux/types.h>
+#include <asm/uaccess.h>
static inline char _tolower(const char c)
@@ -222,3 +223,28 @@ int kstrtos8(const char *s, unsigned int base, s8 *res)
return 0;
+#define kstrto_from_user(f, g, type) \
+int f(const char __user *s, size_t count, unsigned int base, type *res) \
+{ \
+ /* sign, base 2 representation, newline, terminator */ \
+ char buf[1 + sizeof(type) * 8 + 1 + 1]; \
+ \
+ count = min(count, sizeof(buf) - 1); \
+ if (copy_from_user(buf, s, count)) \
+ return -EFAULT; \
+ buf[count] = '\0'; \
+ return g(buf, base, res); \
+} \
+kstrto_from_user(kstrtoull_from_user, kstrtoull, unsigned long long);
+kstrto_from_user(kstrtoll_from_user, kstrtoll, long long);
+kstrto_from_user(kstrtoul_from_user, kstrtoul, unsigned long);
+kstrto_from_user(kstrtol_from_user, kstrtol, long);
+kstrto_from_user(kstrtouint_from_user, kstrtouint, unsigned int);
+kstrto_from_user(kstrtoint_from_user, kstrtoint, int);
+kstrto_from_user(kstrtou16_from_user, kstrtou16, u16);
+kstrto_from_user(kstrtos16_from_user, kstrtos16, s16);
+kstrto_from_user(kstrtou8_from_user, kstrtou8, u8);
+kstrto_from_user(kstrtos8_from_user, kstrtos8, s8);