mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
powerpc: Add a framework for Kernel Userspace Access Protection
This patch implements a framework for Kernel Userspace Access Protection. Then subarches will have the possibility to provide their own implementation by providing setup_kuap() and allow/prevent_user_access(). Some platforms will need to know the area accessed and whether it is accessed from read, write or both. Therefore source, destination and size and handed over to the two functions. mpe: Rename to allow/prevent rather than unlock/lock, and add read/write wrappers. Drop the 32-bit code for now until we have an implementation for it. Add kuap to pt_regs for 64-bit as well as 32-bit. Don't split strings, use pr_crit_ratelimited(). Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Russell Currey <ruscur@russell.cc> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
0fb1c25ab5
commit
de78a9c42a
10 changed files with 121 additions and 15 deletions
|
@ -6,6 +6,7 @@
|
|||
#include <asm/processor.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/extable.h>
|
||||
#include <asm/kup.h>
|
||||
|
||||
/*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
|
@ -140,6 +141,7 @@ extern long __put_user_bad(void);
|
|||
#define __put_user_size(x, ptr, size, retval) \
|
||||
do { \
|
||||
retval = 0; \
|
||||
allow_write_to_user(ptr, size); \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm(x, ptr, retval, "stb"); break; \
|
||||
case 2: __put_user_asm(x, ptr, retval, "sth"); break; \
|
||||
|
@ -147,6 +149,7 @@ do { \
|
|||
case 8: __put_user_asm2(x, ptr, retval); break; \
|
||||
default: __put_user_bad(); \
|
||||
} \
|
||||
prevent_write_to_user(ptr, size); \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_nocheck(x, ptr, size) \
|
||||
|
@ -239,6 +242,7 @@ do { \
|
|||
__chk_user_ptr(ptr); \
|
||||
if (size > sizeof(x)) \
|
||||
(x) = __get_user_bad(); \
|
||||
allow_read_from_user(ptr, size); \
|
||||
switch (size) { \
|
||||
case 1: __get_user_asm(x, ptr, retval, "lbz"); break; \
|
||||
case 2: __get_user_asm(x, ptr, retval, "lhz"); break; \
|
||||
|
@ -246,6 +250,7 @@ do { \
|
|||
case 8: __get_user_asm2(x, ptr, retval); break; \
|
||||
default: (x) = __get_user_bad(); \
|
||||
} \
|
||||
prevent_read_from_user(ptr, size); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
|
@ -305,15 +310,21 @@ extern unsigned long __copy_tofrom_user(void __user *to,
|
|||
static inline unsigned long
|
||||
raw_copy_in_user(void __user *to, const void __user *from, unsigned long n)
|
||||
{
|
||||
return __copy_tofrom_user(to, from, n);
|
||||
unsigned long ret;
|
||||
|
||||
allow_user_access(to, from, n);
|
||||
ret = __copy_tofrom_user(to, from, n);
|
||||
prevent_user_access(to, from, n);
|
||||
return ret;
|
||||
}
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
static inline unsigned long raw_copy_from_user(void *to,
|
||||
const void __user *from, unsigned long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
if (__builtin_constant_p(n) && (n <= 8)) {
|
||||
unsigned long ret = 1;
|
||||
ret = 1;
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
|
@ -338,14 +349,18 @@ static inline unsigned long raw_copy_from_user(void *to,
|
|||
}
|
||||
|
||||
barrier_nospec();
|
||||
return __copy_tofrom_user((__force void __user *)to, from, n);
|
||||
allow_read_from_user(from, n);
|
||||
ret = __copy_tofrom_user((__force void __user *)to, from, n);
|
||||
prevent_read_from_user(from, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline unsigned long raw_copy_to_user(void __user *to,
|
||||
const void *from, unsigned long n)
|
||||
{
|
||||
unsigned long ret;
|
||||
if (__builtin_constant_p(n) && (n <= 8)) {
|
||||
unsigned long ret = 1;
|
||||
ret = 1;
|
||||
|
||||
switch (n) {
|
||||
case 1:
|
||||
|
@ -365,17 +380,24 @@ static inline unsigned long raw_copy_to_user(void __user *to,
|
|||
return 0;
|
||||
}
|
||||
|
||||
return __copy_tofrom_user(to, (__force const void __user *)from, n);
|
||||
allow_write_to_user(to, n);
|
||||
ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
|
||||
prevent_write_to_user(to, n);
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern unsigned long __clear_user(void __user *addr, unsigned long size);
|
||||
|
||||
static inline unsigned long clear_user(void __user *addr, unsigned long size)
|
||||
{
|
||||
unsigned long ret = size;
|
||||
might_fault();
|
||||
if (likely(access_ok(addr, size)))
|
||||
return __clear_user(addr, size);
|
||||
return size;
|
||||
if (likely(access_ok(addr, size))) {
|
||||
allow_write_to_user(addr, size);
|
||||
ret = __clear_user(addr, size);
|
||||
prevent_write_to_user(addr, size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern long strncpy_from_user(char *dst, const char __user *src, long count);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue