Skip to content

Commit 999a228

Browse files
chleroympe
authored andcommitted
uaccess: Add user_read_access_begin/end and user_write_access_begin/end
Some architectures like powerpc64 have the capability to separate read access and write access protection. For get_user() and copy_from_user(), powerpc64 only open read access. For put_user() and copy_to_user(), powerpc64 only open write access. But when using unsafe_get_user() or unsafe_put_user(), user_access_begin open both read and write. Other architectures like powerpc book3s 32 bits only allow write access protection. And on this architecture protection is an heavy operation as it requires locking/unlocking per segment of 256Mbytes. On those architecture it is therefore desirable to do the unlocking only for write access. (Note that book3s/32 ranges from very old powermac from the 90's with powerpc 601 processor, till modern ADSL boxes with PowerQuicc II processors for instance so it is still worth considering.) In order to avoid any risk based of hacking some variable parameters passed to user_access_begin/end that would allow hacking and leaving user access open or opening too much, it is preferable to use dedicated static functions that can't be overridden. Add a user_read_access_begin and user_read_access_end to only open read access. Add a user_write_access_begin and user_write_access_end to only open write access. By default, when undefined, those new access helpers default on the existing user_access_begin and user_access_end. 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/36e43241c7f043a24b5069e78c6a7edd11043be5.1585898438.git.christophe.leroy@c-s.fr
1 parent 8f3d9f3 commit 999a228

File tree

1 file changed

+8
-0
lines changed

1 file changed

+8
-0
lines changed

include/linux/uaccess.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,14 @@ extern long strnlen_unsafe_user(const void __user *unsafe_addr, long count);
378378
static inline unsigned long user_access_save(void) { return 0UL; }
379379
static inline void user_access_restore(unsigned long flags) { }
380380
#endif
381+
#ifndef user_write_access_begin
382+
#define user_write_access_begin user_access_begin
383+
#define user_write_access_end user_access_end
384+
#endif
385+
#ifndef user_read_access_begin
386+
#define user_read_access_begin user_access_begin
387+
#define user_read_access_end user_access_end
388+
#endif
381389

382390
#ifdef CONFIG_HARDENED_USERCOPY
383391
void usercopy_warn(const char *name, const char *detail, bool to_user,

0 commit comments

Comments
 (0)