From ae3950d6238c828de10ed8c66e4b9dd9e27ecad0 Mon Sep 17 00:00:00 2001 From: Sanrio Alvares Date: Mon, 8 Feb 2016 18:42:08 -0800 Subject: [PATCH] lib: align source before using optimized implementation If the source is at the boundary of the VMA, loading one word at a time can cause an alignment fault when the adjacent VMA is IO mapped. Do byte-by-byte copy until source aligns to 8 bytes and then continue with optimized version. CRs-Fixed: 973724 Change-Id: I05e085597c58169fc6e275508a907029b9c7ec64 Signed-off-by: Sanrio Alvares --- lib/strncpy_from_user.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index e0af6ff73d14..9d2683b521ae 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c @@ -14,6 +14,8 @@ (((long) dst | (long) src) & (sizeof(long) - 1)) #endif +#define CHECK_ALIGN(v, a) ((((unsigned long)(v)) & ((a) - 1)) == 0) + /* * Do a strncpy, return length of string without final '\0'. * 'count' is the user-supplied count (return 'count' if we @@ -35,6 +37,21 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src, long if (IS_UNALIGNED(src, dst)) goto byte_at_a_time; + /* Copy a byte at a time until we align to 8 bytes */ + while (max && (!CHECK_ALIGN(src + res, 8))) { + char c; + int ret; + + ret = __get_user(c, src + res); + if (ret) + return -ret; + dst[res] = c; + if (!c) + return res; + res++; + max--; + } + while (max >= sizeof(unsigned long)) { unsigned long c, data;