Skip to content

Commit 41cd780

Browse files
chleroympe
authored andcommitted
uaccess: Selectively open read or write user access
When opening user access to only perform reads, only open read access. When opening user access to only perform writes, only open write access. Signed-off-by: Christophe Leroy <[email protected]> Reviewed-by: Kees Cook <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/2e73bc57125c2c6ab12a587586a4eed3a47105fc.1585898438.git.christophe.leroy@c-s.fr
1 parent 999a228 commit 41cd780

File tree

6 files changed

+25
-25
lines changed

6 files changed

+25
-25
lines changed

fs/readdir.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
242242
return -EINTR;
243243
dirent = buf->current_dir;
244244
prev = (void __user *) dirent - prev_reclen;
245-
if (!user_access_begin(prev, reclen + prev_reclen))
245+
if (!user_write_access_begin(prev, reclen + prev_reclen))
246246
goto efault;
247247

248248
/* This might be 'dirent->d_off', but if so it will get overwritten */
@@ -251,14 +251,14 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
251251
unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
252252
unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
253253
unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
254-
user_access_end();
254+
user_write_access_end();
255255

256256
buf->current_dir = (void __user *)dirent + reclen;
257257
buf->prev_reclen = reclen;
258258
buf->count -= reclen;
259259
return 0;
260260
efault_end:
261-
user_access_end();
261+
user_write_access_end();
262262
efault:
263263
buf->error = -EFAULT;
264264
return -EFAULT;
@@ -327,7 +327,7 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
327327
return -EINTR;
328328
dirent = buf->current_dir;
329329
prev = (void __user *)dirent - prev_reclen;
330-
if (!user_access_begin(prev, reclen + prev_reclen))
330+
if (!user_write_access_begin(prev, reclen + prev_reclen))
331331
goto efault;
332332

333333
/* This might be 'dirent->d_off', but if so it will get overwritten */
@@ -336,15 +336,15 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
336336
unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
337337
unsafe_put_user(d_type, &dirent->d_type, efault_end);
338338
unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
339-
user_access_end();
339+
user_write_access_end();
340340

341341
buf->prev_reclen = reclen;
342342
buf->current_dir = (void __user *)dirent + reclen;
343343
buf->count -= reclen;
344344
return 0;
345345

346346
efault_end:
347-
user_access_end();
347+
user_write_access_end();
348348
efault:
349349
buf->error = -EFAULT;
350350
return -EFAULT;

kernel/compat.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
199199
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
200200
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
201201

202-
if (!user_access_begin(umask, bitmap_size / 8))
202+
if (!user_read_access_begin(umask, bitmap_size / 8))
203203
return -EFAULT;
204204

205205
while (nr_compat_longs > 1) {
@@ -211,11 +211,11 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
211211
}
212212
if (nr_compat_longs)
213213
unsafe_get_user(*mask, umask++, Efault);
214-
user_access_end();
214+
user_read_access_end();
215215
return 0;
216216

217217
Efault:
218-
user_access_end();
218+
user_read_access_end();
219219
return -EFAULT;
220220
}
221221

@@ -228,7 +228,7 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
228228
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
229229
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
230230

231-
if (!user_access_begin(umask, bitmap_size / 8))
231+
if (!user_write_access_begin(umask, bitmap_size / 8))
232232
return -EFAULT;
233233

234234
while (nr_compat_longs > 1) {
@@ -239,10 +239,10 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
239239
}
240240
if (nr_compat_longs)
241241
unsafe_put_user((compat_ulong_t)*mask, umask++, Efault);
242-
user_access_end();
242+
user_write_access_end();
243243
return 0;
244244
Efault:
245-
user_access_end();
245+
user_write_access_end();
246246
return -EFAULT;
247247
}
248248

kernel/exit.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,7 +1557,7 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
15571557
if (!infop)
15581558
return err;
15591559

1560-
if (!user_access_begin(infop, sizeof(*infop)))
1560+
if (!user_write_access_begin(infop, sizeof(*infop)))
15611561
return -EFAULT;
15621562

15631563
unsafe_put_user(signo, &infop->si_signo, Efault);
@@ -1566,10 +1566,10 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
15661566
unsafe_put_user(info.pid, &infop->si_pid, Efault);
15671567
unsafe_put_user(info.uid, &infop->si_uid, Efault);
15681568
unsafe_put_user(info.status, &infop->si_status, Efault);
1569-
user_access_end();
1569+
user_write_access_end();
15701570
return err;
15711571
Efault:
1572-
user_access_end();
1572+
user_write_access_end();
15731573
return -EFAULT;
15741574
}
15751575

@@ -1684,7 +1684,7 @@ COMPAT_SYSCALL_DEFINE5(waitid,
16841684
if (!infop)
16851685
return err;
16861686

1687-
if (!user_access_begin(infop, sizeof(*infop)))
1687+
if (!user_write_access_begin(infop, sizeof(*infop)))
16881688
return -EFAULT;
16891689

16901690
unsafe_put_user(signo, &infop->si_signo, Efault);
@@ -1693,10 +1693,10 @@ COMPAT_SYSCALL_DEFINE5(waitid,
16931693
unsafe_put_user(info.pid, &infop->si_pid, Efault);
16941694
unsafe_put_user(info.uid, &infop->si_uid, Efault);
16951695
unsafe_put_user(info.status, &infop->si_status, Efault);
1696-
user_access_end();
1696+
user_write_access_end();
16971697
return err;
16981698
Efault:
1699-
user_access_end();
1699+
user_write_access_end();
17001700
return -EFAULT;
17011701
}
17021702
#endif

lib/strncpy_from_user.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
116116

117117
kasan_check_write(dst, count);
118118
check_object_size(dst, count, false);
119-
if (user_access_begin(src, max)) {
119+
if (user_read_access_begin(src, max)) {
120120
retval = do_strncpy_from_user(dst, src, count, max);
121-
user_access_end();
121+
user_read_access_end();
122122
return retval;
123123
}
124124
}

lib/strnlen_user.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,9 @@ long strnlen_user(const char __user *str, long count)
109109
if (max > count)
110110
max = count;
111111

112-
if (user_access_begin(str, max)) {
112+
if (user_read_access_begin(str, max)) {
113113
retval = do_strnlen_user(str, count, max);
114-
user_access_end();
114+
user_read_access_end();
115115
return retval;
116116
}
117117
}

lib/usercopy.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ int check_zeroed_user(const void __user *from, size_t size)
5858
from -= align;
5959
size += align;
6060

61-
if (!user_access_begin(from, size))
61+
if (!user_read_access_begin(from, size))
6262
return -EFAULT;
6363

6464
unsafe_get_user(val, (unsigned long __user *) from, err_fault);
@@ -79,10 +79,10 @@ int check_zeroed_user(const void __user *from, size_t size)
7979
val &= aligned_byte_mask(size);
8080

8181
done:
82-
user_access_end();
82+
user_read_access_end();
8383
return (val == 0);
8484
err_fault:
85-
user_access_end();
85+
user_read_access_end();
8686
return -EFAULT;
8787
}
8888
EXPORT_SYMBOL(check_zeroed_user);

0 commit comments

Comments
 (0)