1 From 982905e15342cbc5ede3350cd37224d23b6ebc47 Mon Sep 17 00:00:00 2001
2 From: Peter Zijlstra <peterz@infradead.org>
3 Date: Wed, 24 Apr 2019 09:19:25 +0200
4 Subject: mm/uaccess: Use 'unsigned long' to placate UBSAN warnings on older
7 [ Upstream commit 29da93fea3ea39ab9b12270cc6be1b70ef201c9e ]
9 Randy reported objtool triggered on his (GCC-7.4) build:
11 lib/strncpy_from_user.o: warning: objtool: strncpy_from_user()+0x315: call to __ubsan_handle_add_overflow() with UACCESS enabled
12 lib/strnlen_user.o: warning: objtool: strnlen_user()+0x337: call to __ubsan_handle_sub_overflow() with UACCESS enabled
14 This is due to UBSAN generating signed-overflow-UB warnings where it
15 should not. Prior to GCC-8 UBSAN ignored -fwrapv (which the kernel
16 uses through -fno-strict-overflow).
18 Make the functions use 'unsigned long' throughout.
20 Reported-by: Randy Dunlap <rdunlap@infradead.org>
21 Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
22 Acked-by: Randy Dunlap <rdunlap@infradead.org> # build-tested
23 Acked-by: Linus Torvalds <torvalds@linux-foundation.org>
24 Cc: Peter Zijlstra <peterz@infradead.org>
25 Cc: Thomas Gleixner <tglx@linutronix.de>
27 Link: http://lkml.kernel.org/r/20190424072208.754094071@infradead.org
28 Signed-off-by: Ingo Molnar <mingo@kernel.org>
29 Signed-off-by: Sasha Levin <sashal@kernel.org>
31 lib/strncpy_from_user.c | 5 +++--
32 lib/strnlen_user.c | 4 ++--
33 2 files changed, 5 insertions(+), 4 deletions(-)
35 diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c
36 index e0af6ff73d146..f8b1e3cb716b9 100644
37 --- a/lib/strncpy_from_user.c
38 +++ b/lib/strncpy_from_user.c
40 * hit it), 'max' is the address space maximum (and we return
41 * -EFAULT if we hit it).
43 -static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max)
44 +static inline long do_strncpy_from_user(char *dst, const char __user *src,
45 + unsigned long count, unsigned long max)
47 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
49 + unsigned long res = 0;
52 * Truncate 'max' to the user-specified limit, so that
53 diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c
54 index 3a5f2b366d84e..1c87bfa63db7f 100644
55 --- a/lib/strnlen_user.c
56 +++ b/lib/strnlen_user.c
58 static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max)
60 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
61 - long align, res = 0;
62 + unsigned long align, res = 0;
66 @@ -41,7 +41,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
67 * Do everything aligned. But that means that we
68 * need to also expand the maximum..
70 - align = (sizeof(long) - 1) & (unsigned long)src;
71 + align = (sizeof(unsigned long) - 1) & (unsigned long)src;