Skip to content

Commit ab10ae1

Browse files
chleroytorvalds
authored andcommitted
lib: Reduce user_access_begin() boundaries in strncpy_from_user() and strnlen_user()
The range passed to user_access_begin() by strncpy_from_user() and strnlen_user() starts at 'src' and goes up to the limit of userspace although reads will be limited by the 'count' param. On 32 bits powerpc (book3s/32) access has to be granted for each 256Mbytes segment and the cost increases with the number of segments to unlock. Limit the range with 'count' param. Fixes: 594cc25 ("make 'user_access_begin()' do 'access_ok()'") Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 838a860 commit ab10ae1

2 files changed

Lines changed: 14 additions & 14 deletions

File tree

lib/strncpy_from_user.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,6 @@ static inline long do_strncpy_from_user(char *dst, const char __user *src,
3030
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
3131
unsigned long res = 0;
3232

33-
/*
34-
* Truncate 'max' to the user-specified limit, so that
35-
* we only have one limit we need to check in the loop
36-
*/
37-
if (max > count)
38-
max = count;
39-
4033
if (IS_UNALIGNED(src, dst))
4134
goto byte_at_a_time;
4235

@@ -114,6 +107,13 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
114107
unsigned long max = max_addr - src_addr;
115108
long retval;
116109

110+
/*
111+
* Truncate 'max' to the user-specified limit, so that
112+
* we only have one limit we need to check in the loop
113+
*/
114+
if (max > count)
115+
max = count;
116+
117117
kasan_check_write(dst, count);
118118
check_object_size(dst, count, false);
119119
if (user_access_begin(src, max)) {

lib/strnlen_user.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count,
2626
unsigned long align, res = 0;
2727
unsigned long c;
2828

29-
/*
30-
* Truncate 'max' to the user-specified limit, so that
31-
* we only have one limit we need to check in the loop
32-
*/
33-
if (max > count)
34-
max = count;
35-
3629
/*
3730
* Do everything aligned. But that means that we
3831
* need to also expand the maximum..
@@ -109,6 +102,13 @@ long strnlen_user(const char __user *str, long count)
109102
unsigned long max = max_addr - src_addr;
110103
long retval;
111104

105+
/*
106+
* Truncate 'max' to the user-specified limit, so that
107+
* we only have one limit we need to check in the loop
108+
*/
109+
if (max > count)
110+
max = count;
111+
112112
if (user_access_begin(str, max)) {
113113
retval = do_strnlen_user(str, count, max);
114114
user_access_end();

0 commit comments

Comments
 (0)