| From dfe79ab56380b3ad3df0724e7160d99c5a736ff7 Mon Sep 17 00:00:00 2001 |
| From: Peter Zijlstra <peterz@infradead.org> |
| Date: Wed, 24 Apr 2019 09:19:25 +0200 |
| Subject: mm/uaccess: Use 'unsigned long' to placate UBSAN warnings on older |
| GCC versions |
| |
| [ Upstream commit 29da93fea3ea39ab9b12270cc6be1b70ef201c9e ] |
| |
| Randy reported objtool triggered on his (GCC-7.4) build: |
| |
| lib/strncpy_from_user.o: warning: objtool: strncpy_from_user()+0x315: call to __ubsan_handle_add_overflow() with UACCESS enabled |
| lib/strnlen_user.o: warning: objtool: strnlen_user()+0x337: call to __ubsan_handle_sub_overflow() with UACCESS enabled |
| |
| This is due to UBSAN generating signed-overflow-UB warnings where it |
| should not. Prior to GCC-8 UBSAN ignored -fwrapv (which the kernel |
| uses through -fno-strict-overflow). |
| |
| Make the functions use 'unsigned long' throughout. |
| |
| Reported-by: Randy Dunlap <rdunlap@infradead.org> |
| Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> |
| Acked-by: Randy Dunlap <rdunlap@infradead.org> # build-tested |
| Acked-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Cc: luto@kernel.org |
| Link: http://lkml.kernel.org/r/20190424072208.754094071@infradead.org |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| lib/strncpy_from_user.c | 5 +++-- |
| lib/strnlen_user.c | 4 ++-- |
| 2 files changed, 5 insertions(+), 4 deletions(-) |
| |
| diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c |
| index 58eacd41526c5..023ba9f3b99f0 100644 |
| --- a/lib/strncpy_from_user.c |
| +++ b/lib/strncpy_from_user.c |
| @@ -23,10 +23,11 @@ |
| * hit it), 'max' is the address space maximum (and we return |
| * -EFAULT if we hit it). |
| */ |
| -static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max) |
| +static inline long do_strncpy_from_user(char *dst, const char __user *src, |
| + unsigned long count, unsigned long max) |
| { |
| const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; |
| - long res = 0; |
| + unsigned long res = 0; |
| |
| /* |
| * Truncate 'max' to the user-specified limit, so that |
| diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c |
| index 1c1a1b0e38a5f..7f2db3fe311fd 100644 |
| --- a/lib/strnlen_user.c |
| +++ b/lib/strnlen_user.c |
| @@ -28,7 +28,7 @@ |
| static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max) |
| { |
| const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; |
| - long align, res = 0; |
| + unsigned long align, res = 0; |
| unsigned long c; |
| |
| /* |
| @@ -42,7 +42,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count, |
| * Do everything aligned. But that means that we |
| * need to also expand the maximum.. |
| */ |
| - align = (sizeof(long) - 1) & (unsigned long)src; |
| + align = (sizeof(unsigned long) - 1) & (unsigned long)src; |
| src -= align; |
| max += align; |
| |
| -- |
| 2.20.1 |
| |