mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-05 01:54:09 +08:00
Merge branch 'topic/uaccess-ppc' into next
Merge our uaccess-ppc topic branch. It is based on the uaccess topic branch that we're sharing with Viro. This includes the addition of user_[read|write]_access_begin(), as well as some powerpc specific changes to our uaccess routines that would conflict badly if merged separately.
This commit is contained in:
commit
217ba7dcce
@ -108,7 +108,7 @@ static __always_inline void allow_user_access(void __user *to, const void __user
|
||||
u32 addr, end;
|
||||
|
||||
BUILD_BUG_ON(!__builtin_constant_p(dir));
|
||||
BUILD_BUG_ON(dir == KUAP_CURRENT);
|
||||
BUILD_BUG_ON(dir & ~KUAP_READ_WRITE);
|
||||
|
||||
if (!(dir & KUAP_WRITE))
|
||||
return;
|
||||
@ -131,7 +131,7 @@ static __always_inline void prevent_user_access(void __user *to, const void __us
|
||||
|
||||
BUILD_BUG_ON(!__builtin_constant_p(dir));
|
||||
|
||||
if (dir == KUAP_CURRENT) {
|
||||
if (dir & KUAP_CURRENT_WRITE) {
|
||||
u32 kuap = current->thread.kuap;
|
||||
|
||||
if (unlikely(!kuap))
|
||||
|
@ -10,7 +10,9 @@
|
||||
* Use the current saved situation instead of the to/from/size params.
|
||||
* Used on book3s/32
|
||||
*/
|
||||
#define KUAP_CURRENT 4
|
||||
#define KUAP_CURRENT_READ 4
|
||||
#define KUAP_CURRENT_WRITE 8
|
||||
#define KUAP_CURRENT (KUAP_CURRENT_READ | KUAP_CURRENT_WRITE)
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <asm/book3s/64/kup-radix.h>
|
||||
@ -101,6 +103,16 @@ static inline void prevent_current_access_user(void)
|
||||
prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT);
|
||||
}
|
||||
|
||||
static inline void prevent_current_read_from_user(void)
|
||||
{
|
||||
prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT_READ);
|
||||
}
|
||||
|
||||
static inline void prevent_current_write_to_user(void)
|
||||
{
|
||||
prevent_user_access(NULL, NULL, ~0UL, KUAP_CURRENT_WRITE);
|
||||
}
|
||||
|
||||
#endif /* !__ASSEMBLY__ */
|
||||
|
||||
#endif /* _ASM_POWERPC_KUAP_H_ */
|
||||
|
@ -93,12 +93,12 @@ static inline int __access_ok(unsigned long addr, unsigned long size,
|
||||
#define __get_user(x, ptr) \
|
||||
__get_user_nocheck((x), (ptr), sizeof(*(ptr)), true)
|
||||
#define __put_user(x, ptr) \
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), true)
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
|
||||
#define __put_user_goto(x, ptr, label) \
|
||||
__put_user_nocheck_goto((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), label)
|
||||
|
||||
#define __get_user_allowed(x, ptr) \
|
||||
__get_user_nocheck((x), (ptr), sizeof(*(ptr)), false)
|
||||
#define __put_user_allowed(x, ptr) \
|
||||
__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)), false)
|
||||
|
||||
#define __get_user_inatomic(x, ptr) \
|
||||
__get_user_nosleep((x), (ptr), sizeof(*(ptr)))
|
||||
@ -207,17 +207,18 @@ do { \
|
||||
prevent_write_to_user(ptr, size); \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_nocheck(x, ptr, size, do_allow) \
|
||||
#define __put_user_nocheck(x, ptr, size) \
|
||||
({ \
|
||||
long __pu_err; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
if (!is_kernel_addr((unsigned long)__pu_addr)) \
|
||||
might_fault(); \
|
||||
__chk_user_ptr(ptr); \
|
||||
if (do_allow) \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
else \
|
||||
__put_user_size_allowed((x), __pu_addr, (size), __pu_err); \
|
||||
__chk_user_ptr(__pu_addr); \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
@ -225,9 +226,13 @@ do { \
|
||||
({ \
|
||||
long __pu_err = -EFAULT; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
might_fault(); \
|
||||
if (access_ok(__pu_addr, size)) \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
if (access_ok(__pu_addr, __pu_size)) \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
@ -235,12 +240,62 @@ do { \
|
||||
({ \
|
||||
long __pu_err; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_size((x), __pu_addr, (size), __pu_err); \
|
||||
__typeof__(*(ptr)) __pu_val = (x); \
|
||||
__typeof__(size) __pu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__pu_addr); \
|
||||
__put_user_size(__pu_val, __pu_addr, __pu_size, __pu_err); \
|
||||
\
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
|
||||
#define __put_user_asm_goto(x, addr, label, op) \
|
||||
asm volatile goto( \
|
||||
"1: " op "%U1%X1 %0,%1 # put_user\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
: \
|
||||
: "r" (x), "m" (*addr) \
|
||||
: \
|
||||
: label)
|
||||
|
||||
#ifdef __powerpc64__
|
||||
#define __put_user_asm2_goto(x, ptr, label) \
|
||||
__put_user_asm_goto(x, ptr, label, "std")
|
||||
#else /* __powerpc64__ */
|
||||
#define __put_user_asm2_goto(x, addr, label) \
|
||||
asm volatile goto( \
|
||||
"1: stw%X1 %0, %1\n" \
|
||||
"2: stw%X1 %L0, %L1\n" \
|
||||
EX_TABLE(1b, %l2) \
|
||||
EX_TABLE(2b, %l2) \
|
||||
: \
|
||||
: "r" (x), "m" (*addr) \
|
||||
: \
|
||||
: label)
|
||||
#endif /* __powerpc64__ */
|
||||
|
||||
#define __put_user_size_goto(x, ptr, size, label) \
|
||||
do { \
|
||||
switch (size) { \
|
||||
case 1: __put_user_asm_goto(x, ptr, label, "stb"); break; \
|
||||
case 2: __put_user_asm_goto(x, ptr, label, "sth"); break; \
|
||||
case 4: __put_user_asm_goto(x, ptr, label, "stw"); break; \
|
||||
case 8: __put_user_asm2_goto(x, ptr, label); break; \
|
||||
default: __put_user_bad(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define __put_user_nocheck_goto(x, ptr, size, label) \
|
||||
do { \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
if (!is_kernel_addr((unsigned long)__pu_addr)) \
|
||||
might_fault(); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_size_goto((x), __pu_addr, (size), label); \
|
||||
} while (0)
|
||||
|
||||
|
||||
extern long __get_user_bad(void);
|
||||
|
||||
/*
|
||||
@ -328,15 +383,18 @@ do { \
|
||||
long __gu_err; \
|
||||
__long_type(*(ptr)) __gu_val; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__gu_addr); \
|
||||
if (!is_kernel_addr((unsigned long)__gu_addr)) \
|
||||
might_fault(); \
|
||||
barrier_nospec(); \
|
||||
if (do_allow) \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
else \
|
||||
__get_user_size_allowed(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size_allowed(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
(x) = (__typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@ -345,12 +403,15 @@ do { \
|
||||
long __gu_err = -EFAULT; \
|
||||
__long_type(*(ptr)) __gu_val = 0; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
might_fault(); \
|
||||
if (access_ok(__gu_addr, (size))) { \
|
||||
if (access_ok(__gu_addr, __gu_size)) { \
|
||||
barrier_nospec(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
} \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@ -359,10 +420,13 @@ do { \
|
||||
long __gu_err; \
|
||||
__long_type(*(ptr)) __gu_val; \
|
||||
__typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__typeof__(size) __gu_size = (size); \
|
||||
\
|
||||
__chk_user_ptr(__gu_addr); \
|
||||
barrier_nospec(); \
|
||||
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
|
||||
__get_user_size(__gu_val, __gu_addr, __gu_size, __gu_err); \
|
||||
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
||||
\
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@ -513,10 +577,51 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
|
||||
#define user_access_save prevent_user_access_return
|
||||
#define user_access_restore restore_user_access
|
||||
|
||||
static __must_check inline bool
|
||||
user_read_access_begin(const void __user *ptr, size_t len)
|
||||
{
|
||||
if (unlikely(!access_ok(ptr, len)))
|
||||
return false;
|
||||
allow_read_from_user(ptr, len);
|
||||
return true;
|
||||
}
|
||||
#define user_read_access_begin user_read_access_begin
|
||||
#define user_read_access_end prevent_current_read_from_user
|
||||
|
||||
static __must_check inline bool
|
||||
user_write_access_begin(const void __user *ptr, size_t len)
|
||||
{
|
||||
if (unlikely(!access_ok(ptr, len)))
|
||||
return false;
|
||||
allow_write_to_user((void __user *)ptr, len);
|
||||
return true;
|
||||
}
|
||||
#define user_write_access_begin user_write_access_begin
|
||||
#define user_write_access_end prevent_current_write_to_user
|
||||
|
||||
#define unsafe_op_wrap(op, err) do { if (unlikely(op)) goto err; } while (0)
|
||||
#define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e)
|
||||
#define unsafe_put_user(x, p, e) unsafe_op_wrap(__put_user_allowed(x, p), e)
|
||||
#define unsafe_put_user(x, p, e) __put_user_goto(x, p, e)
|
||||
|
||||
#define unsafe_copy_to_user(d, s, l, e) \
|
||||
unsafe_op_wrap(raw_copy_to_user_allowed(d, s, l), e)
|
||||
do { \
|
||||
u8 __user *_dst = (u8 __user *)(d); \
|
||||
const u8 *_src = (const u8 *)(s); \
|
||||
size_t _len = (l); \
|
||||
int _i; \
|
||||
\
|
||||
for (_i = 0; _i < (_len & ~(sizeof(long) - 1)); _i += sizeof(long)) \
|
||||
__put_user_goto(*(long*)(_src + _i), (long __user *)(_dst + _i), e);\
|
||||
if (IS_ENABLED(CONFIG_PPC64) && (_len & 4)) { \
|
||||
__put_user_goto(*(u32*)(_src + _i), (u32 __user *)(_dst + _i), e); \
|
||||
_i += 4; \
|
||||
} \
|
||||
if (_len & 2) { \
|
||||
__put_user_goto(*(u16*)(_src + _i), (u16 __user *)(_dst + _i), e); \
|
||||
_i += 2; \
|
||||
} \
|
||||
if (_len & 1) \
|
||||
__put_user_goto(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e);\
|
||||
} while (0)
|
||||
|
||||
#endif /* _ARCH_POWERPC_UACCESS_H */
|
||||
|
@ -2794,7 +2794,8 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
|
||||
* And this range already got effectively checked earlier
|
||||
* when we did the "copy_from_user()" above.
|
||||
*/
|
||||
if (!user_access_begin(user_exec_list, count * sizeof(*user_exec_list)))
|
||||
if (!user_write_access_begin(user_exec_list,
|
||||
count * sizeof(*user_exec_list)))
|
||||
goto end;
|
||||
|
||||
for (i = 0; i < args->buffer_count; i++) {
|
||||
@ -2808,7 +2809,7 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
|
||||
end_user);
|
||||
}
|
||||
end_user:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
end:;
|
||||
}
|
||||
|
||||
|
12
fs/readdir.c
12
fs/readdir.c
@ -242,7 +242,7 @@ static int filldir(struct dir_context *ctx, const char *name, int namlen,
|
||||
return -EINTR;
|
||||
dirent = buf->current_dir;
|
||||
prev = (void __user *) dirent - prev_reclen;
|
||||
if (!user_access_begin(prev, reclen + prev_reclen))
|
||||
if (!user_write_access_begin(prev, reclen + prev_reclen))
|
||||
goto efault;
|
||||
|
||||
/* 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,
|
||||
unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
|
||||
unsafe_put_user(d_type, (char __user *) dirent + reclen - 1, efault_end);
|
||||
unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
|
||||
buf->current_dir = (void __user *)dirent + reclen;
|
||||
buf->prev_reclen = reclen;
|
||||
buf->count -= reclen;
|
||||
return 0;
|
||||
efault_end:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
efault:
|
||||
buf->error = -EFAULT;
|
||||
return -EFAULT;
|
||||
@ -327,7 +327,7 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
||||
return -EINTR;
|
||||
dirent = buf->current_dir;
|
||||
prev = (void __user *)dirent - prev_reclen;
|
||||
if (!user_access_begin(prev, reclen + prev_reclen))
|
||||
if (!user_write_access_begin(prev, reclen + prev_reclen))
|
||||
goto efault;
|
||||
|
||||
/* This might be 'dirent->d_off', but if so it will get overwritten */
|
||||
@ -336,7 +336,7 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
||||
unsafe_put_user(reclen, &dirent->d_reclen, efault_end);
|
||||
unsafe_put_user(d_type, &dirent->d_type, efault_end);
|
||||
unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
|
||||
buf->prev_reclen = reclen;
|
||||
buf->current_dir = (void __user *)dirent + reclen;
|
||||
@ -344,7 +344,7 @@ static int filldir64(struct dir_context *ctx, const char *name, int namlen,
|
||||
return 0;
|
||||
|
||||
efault_end:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
efault:
|
||||
buf->error = -EFAULT;
|
||||
return -EFAULT;
|
||||
|
@ -378,6 +378,14 @@ extern long strnlen_unsafe_user(const void __user *unsafe_addr, long count);
|
||||
static inline unsigned long user_access_save(void) { return 0UL; }
|
||||
static inline void user_access_restore(unsigned long flags) { }
|
||||
#endif
|
||||
#ifndef user_write_access_begin
|
||||
#define user_write_access_begin user_access_begin
|
||||
#define user_write_access_end user_access_end
|
||||
#endif
|
||||
#ifndef user_read_access_begin
|
||||
#define user_read_access_begin user_access_begin
|
||||
#define user_read_access_end user_access_end
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HARDENED_USERCOPY
|
||||
void usercopy_warn(const char *name, const char *detail, bool to_user,
|
||||
|
@ -199,7 +199,7 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
if (!user_access_begin(umask, bitmap_size / 8))
|
||||
if (!user_read_access_begin(umask, bitmap_size / 8))
|
||||
return -EFAULT;
|
||||
|
||||
while (nr_compat_longs > 1) {
|
||||
@ -211,11 +211,11 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
}
|
||||
if (nr_compat_longs)
|
||||
unsafe_get_user(*mask, umask++, Efault);
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return 0;
|
||||
|
||||
Efault:
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -228,7 +228,7 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
bitmap_size = ALIGN(bitmap_size, BITS_PER_COMPAT_LONG);
|
||||
nr_compat_longs = BITS_TO_COMPAT_LONGS(bitmap_size);
|
||||
|
||||
if (!user_access_begin(umask, bitmap_size / 8))
|
||||
if (!user_write_access_begin(umask, bitmap_size / 8))
|
||||
return -EFAULT;
|
||||
|
||||
while (nr_compat_longs > 1) {
|
||||
@ -239,10 +239,10 @@ long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
}
|
||||
if (nr_compat_longs)
|
||||
unsafe_put_user((compat_ulong_t)*mask, umask++, Efault);
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return 0;
|
||||
Efault:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -1557,7 +1557,7 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
|
||||
if (!infop)
|
||||
return err;
|
||||
|
||||
if (!user_access_begin(infop, sizeof(*infop)))
|
||||
if (!user_write_access_begin(infop, sizeof(*infop)))
|
||||
return -EFAULT;
|
||||
|
||||
unsafe_put_user(signo, &infop->si_signo, Efault);
|
||||
@ -1566,10 +1566,10 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
|
||||
unsafe_put_user(info.pid, &infop->si_pid, Efault);
|
||||
unsafe_put_user(info.uid, &infop->si_uid, Efault);
|
||||
unsafe_put_user(info.status, &infop->si_status, Efault);
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return err;
|
||||
Efault:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -1684,7 +1684,7 @@ COMPAT_SYSCALL_DEFINE5(waitid,
|
||||
if (!infop)
|
||||
return err;
|
||||
|
||||
if (!user_access_begin(infop, sizeof(*infop)))
|
||||
if (!user_write_access_begin(infop, sizeof(*infop)))
|
||||
return -EFAULT;
|
||||
|
||||
unsafe_put_user(signo, &infop->si_signo, Efault);
|
||||
@ -1693,10 +1693,10 @@ COMPAT_SYSCALL_DEFINE5(waitid,
|
||||
unsafe_put_user(info.pid, &infop->si_pid, Efault);
|
||||
unsafe_put_user(info.uid, &infop->si_uid, Efault);
|
||||
unsafe_put_user(info.status, &infop->si_status, Efault);
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return err;
|
||||
Efault:
|
||||
user_access_end();
|
||||
user_write_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
@ -116,9 +116,9 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
|
||||
kasan_check_write(dst, count);
|
||||
check_object_size(dst, count, false);
|
||||
if (user_access_begin(src, max)) {
|
||||
if (user_read_access_begin(src, max)) {
|
||||
retval = do_strncpy_from_user(dst, src, count, max);
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -109,9 +109,9 @@ long strnlen_user(const char __user *str, long count)
|
||||
if (max > count)
|
||||
max = count;
|
||||
|
||||
if (user_access_begin(str, max)) {
|
||||
if (user_read_access_begin(str, max)) {
|
||||
retval = do_strnlen_user(str, count, max);
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ int check_zeroed_user(const void __user *from, size_t size)
|
||||
from -= align;
|
||||
size += align;
|
||||
|
||||
if (!user_access_begin(from, size))
|
||||
if (!user_read_access_begin(from, size))
|
||||
return -EFAULT;
|
||||
|
||||
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)
|
||||
val &= aligned_byte_mask(size);
|
||||
|
||||
done:
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return (val == 0);
|
||||
err_fault:
|
||||
user_access_end();
|
||||
user_read_access_end();
|
||||
return -EFAULT;
|
||||
}
|
||||
EXPORT_SYMBOL(check_zeroed_user);
|
||||
|
Loading…
Reference in New Issue
Block a user