2019-06-03 13:44:50 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2012-03-05 19:49:32 +08:00
|
|
|
/*
|
|
|
|
* Based on arch/arm/include/asm/uaccess.h
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 ARM Ltd.
|
|
|
|
*/
|
|
|
|
#ifndef __ASM_UACCESS_H
|
|
|
|
#define __ASM_UACCESS_H
|
|
|
|
|
2016-07-01 21:58:21 +08:00
|
|
|
#include <asm/alternative.h>
|
2016-07-01 23:53:00 +08:00
|
|
|
#include <asm/kernel-pgtable.h>
|
2016-07-01 21:58:21 +08:00
|
|
|
#include <asm/sysreg.h>
|
|
|
|
|
2012-03-05 19:49:32 +08:00
|
|
|
/*
|
|
|
|
* User space memory access functions
|
|
|
|
*/
|
2016-10-19 21:40:54 +08:00
|
|
|
#include <linux/bitops.h>
|
2016-06-09 05:40:56 +08:00
|
|
|
#include <linux/kasan-checks.h>
|
2012-03-05 19:49:32 +08:00
|
|
|
#include <linux/string.h>
|
|
|
|
|
2015-07-23 02:05:54 +08:00
|
|
|
#include <asm/cpufeature.h>
|
2012-03-05 19:49:32 +08:00
|
|
|
#include <asm/ptrace.h>
|
|
|
|
#include <asm/memory.h>
|
2016-12-26 03:00:03 +08:00
|
|
|
#include <asm/extable.h>
|
2012-03-05 19:49:32 +08:00
|
|
|
|
|
|
|
#define get_fs() (current_thread_info()->addr_limit)
|
|
|
|
|
|
|
|
static inline void set_fs(mm_segment_t fs)
|
|
|
|
{
|
|
|
|
current_thread_info()->addr_limit = fs;
|
2016-02-05 22:58:48 +08:00
|
|
|
|
2018-02-05 23:34:21 +08:00
|
|
|
/*
|
|
|
|
* Prevent a mispredicted conditional call to set_fs from forwarding
|
|
|
|
* the wrong address limit to access_ok under speculation.
|
|
|
|
*/
|
2018-06-14 18:21:34 +08:00
|
|
|
spec_bar();
|
2018-02-05 23:34:21 +08:00
|
|
|
|
2017-06-15 09:12:03 +08:00
|
|
|
/* On user-mode return, check fs is correct */
|
|
|
|
set_thread_flag(TIF_FSCHECK);
|
|
|
|
|
2016-02-05 22:58:48 +08:00
|
|
|
/*
|
|
|
|
* Enable/disable UAO so that copy_to_user() etc can access
|
|
|
|
* kernel memory with the unprivileged instructions.
|
|
|
|
*/
|
|
|
|
if (IS_ENABLED(CONFIG_ARM64_UAO) && fs == KERNEL_DS)
|
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_UAO(1), ARM64_HAS_UAO));
|
|
|
|
else
|
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_UAO(0), ARM64_HAS_UAO,
|
|
|
|
CONFIG_ARM64_UAO));
|
2012-03-05 19:49:32 +08:00
|
|
|
}
|
|
|
|
|
2015-01-06 21:11:13 +08:00
|
|
|
#define segment_eq(a, b) ((a) == (b))
|
2012-03-05 19:49:32 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Test whether a block of memory is a valid user space address.
|
|
|
|
* Returns 1 if the range is valid, 0 otherwise.
|
|
|
|
*
|
|
|
|
* This is equivalent to the following test:
|
2018-02-05 23:34:18 +08:00
|
|
|
* (u65)addr + (u65)size <= (u65)current->addr_limit + 1
|
2012-03-05 19:49:32 +08:00
|
|
|
*/
|
2018-02-19 21:38:00 +08:00
|
|
|
static inline unsigned long __range_ok(const void __user *addr, unsigned long size)
|
2018-02-05 23:34:18 +08:00
|
|
|
{
|
2018-02-19 21:38:00 +08:00
|
|
|
unsigned long ret, limit = current_thread_info()->addr_limit;
|
2018-02-05 23:34:18 +08:00
|
|
|
|
|
|
|
__chk_user_ptr(addr);
|
|
|
|
asm volatile(
|
|
|
|
// A + B <= C + 1 for all A,B,C, in four easy steps:
|
|
|
|
// 1: X = A + B; X' = X % 2^64
|
2018-02-19 21:38:00 +08:00
|
|
|
" adds %0, %3, %2\n"
|
2018-02-05 23:34:18 +08:00
|
|
|
// 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4
|
|
|
|
" csel %1, xzr, %1, hi\n"
|
|
|
|
// 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X'
|
|
|
|
// to compensate for the carry flag being set in step 4. For
|
|
|
|
// X > 2^64, X' merely has to remain nonzero, which it does.
|
|
|
|
" csinv %0, %0, xzr, cc\n"
|
|
|
|
// 4: For X < 2^64, this gives us X' - C - 1 <= 0, where the -1
|
|
|
|
// comes from the carry in being clear. Otherwise, we are
|
|
|
|
// testing X' - C == 0, subject to the previous adjustments.
|
|
|
|
" sbcs xzr, %0, %1\n"
|
|
|
|
" cset %0, ls\n"
|
2018-02-19 21:38:00 +08:00
|
|
|
: "=&r" (ret), "+r" (limit) : "Ir" (size), "0" (addr) : "cc");
|
2018-02-05 23:34:18 +08:00
|
|
|
|
2018-02-19 21:38:00 +08:00
|
|
|
return ret;
|
2018-02-05 23:34:18 +08:00
|
|
|
}
|
2012-03-05 19:49:32 +08:00
|
|
|
|
Remove 'type' argument from access_ok() function
Nobody has actually used the type (VERIFY_READ vs VERIFY_WRITE) argument
of the user address range verification function since we got rid of the
old racy i386-only code to walk page tables by hand.
It existed because the original 80386 would not honor the write protect
bit when in kernel mode, so you had to do COW by hand before doing any
user access. But we haven't supported that in a long time, and these
days the 'type' argument is a purely historical artifact.
A discussion about extending 'user_access_begin()' to do the range
checking resulted this patch, because there is no way we're going to
move the old VERIFY_xyz interface to that model. And it's best done at
the end of the merge window when I've done most of my merges, so let's
just get this done once and for all.
This patch was mostly done with a sed-script, with manual fix-ups for
the cases that weren't of the trivial 'access_ok(VERIFY_xyz' form.
There were a couple of notable cases:
- csky still had the old "verify_area()" name as an alias.
- the iter_iov code had magical hardcoded knowledge of the actual
values of VERIFY_{READ,WRITE} (not that they mattered, since nothing
really used it)
- microblaze used the type argument for a debug printout
but other than those oddities this should be a total no-op patch.
I tried to fix up all architectures, did fairly extensive grepping for
access_ok() uses, and the changes are trivial, but I may have missed
something. Any missed conversion should be trivially fixable, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-01-04 10:57:57 +08:00
|
|
|
#define access_ok(addr, size) __range_ok(addr, size)
|
2013-11-07 01:20:22 +08:00
|
|
|
#define user_addr_max get_fs
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2016-01-01 22:02:12 +08:00
|
|
|
#define _ASM_EXTABLE(from, to) \
|
|
|
|
" .pushsection __ex_table, \"a\"\n" \
|
|
|
|
" .align 3\n" \
|
|
|
|
" .long (" #from " - .), (" #to " - .)\n" \
|
|
|
|
" .popsection\n"
|
|
|
|
|
2016-07-01 21:58:21 +08:00
|
|
|
/*
|
|
|
|
* User access enabling/disabling.
|
|
|
|
*/
|
2016-07-01 23:53:00 +08:00
|
|
|
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
|
|
|
|
static inline void __uaccess_ttbr0_disable(void)
|
|
|
|
{
|
2018-01-10 21:18:30 +08:00
|
|
|
unsigned long flags, ttbr;
|
2016-07-01 23:53:00 +08:00
|
|
|
|
2018-01-10 21:18:30 +08:00
|
|
|
local_irq_save(flags);
|
2017-08-10 20:58:16 +08:00
|
|
|
ttbr = read_sysreg(ttbr1_el1);
|
2018-01-10 21:18:30 +08:00
|
|
|
ttbr &= ~TTBR_ASID_MASK;
|
2018-01-11 18:11:57 +08:00
|
|
|
/* reserved_ttbr0 placed before swapper_pg_dir */
|
|
|
|
write_sysreg(ttbr - RESERVED_TTBR0_SIZE, ttbr0_el1);
|
2017-08-10 20:58:16 +08:00
|
|
|
isb();
|
|
|
|
/* Set reserved ASID */
|
|
|
|
write_sysreg(ttbr, ttbr1_el1);
|
2016-07-01 23:53:00 +08:00
|
|
|
isb();
|
2018-01-10 21:18:30 +08:00
|
|
|
local_irq_restore(flags);
|
2016-07-01 23:53:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __uaccess_ttbr0_enable(void)
|
|
|
|
{
|
2017-08-10 20:58:16 +08:00
|
|
|
unsigned long flags, ttbr0, ttbr1;
|
2016-07-01 23:53:00 +08:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Disable interrupts to avoid preemption between reading the 'ttbr0'
|
|
|
|
* variable and the MSR. A context switch could trigger an ASID
|
|
|
|
* roll-over and an update of 'ttbr0'.
|
|
|
|
*/
|
|
|
|
local_irq_save(flags);
|
2018-01-10 21:18:30 +08:00
|
|
|
ttbr0 = READ_ONCE(current_thread_info()->ttbr0);
|
2017-08-10 20:58:16 +08:00
|
|
|
|
|
|
|
/* Restore active ASID */
|
|
|
|
ttbr1 = read_sysreg(ttbr1_el1);
|
2018-01-10 21:18:30 +08:00
|
|
|
ttbr1 &= ~TTBR_ASID_MASK; /* safety measure */
|
2017-12-02 01:33:48 +08:00
|
|
|
ttbr1 |= ttbr0 & TTBR_ASID_MASK;
|
2017-08-10 20:58:16 +08:00
|
|
|
write_sysreg(ttbr1, ttbr1_el1);
|
|
|
|
isb();
|
|
|
|
|
|
|
|
/* Restore user page table */
|
|
|
|
write_sysreg(ttbr0, ttbr0_el1);
|
2016-07-01 23:53:00 +08:00
|
|
|
isb();
|
|
|
|
local_irq_restore(flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool uaccess_ttbr0_disable(void)
|
|
|
|
{
|
|
|
|
if (!system_uses_ttbr0_pan())
|
|
|
|
return false;
|
|
|
|
__uaccess_ttbr0_disable();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool uaccess_ttbr0_enable(void)
|
|
|
|
{
|
|
|
|
if (!system_uses_ttbr0_pan())
|
|
|
|
return false;
|
|
|
|
__uaccess_ttbr0_enable();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static inline bool uaccess_ttbr0_disable(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline bool uaccess_ttbr0_enable(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-01-08 23:38:11 +08:00
|
|
|
static inline void __uaccess_disable_hw_pan(void)
|
|
|
|
{
|
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_HAS_PAN,
|
|
|
|
CONFIG_ARM64_PAN));
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void __uaccess_enable_hw_pan(void)
|
|
|
|
{
|
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
|
|
|
|
CONFIG_ARM64_PAN));
|
|
|
|
}
|
|
|
|
|
2016-07-01 21:58:21 +08:00
|
|
|
#define __uaccess_disable(alt) \
|
|
|
|
do { \
|
2016-07-01 23:53:00 +08:00
|
|
|
if (!uaccess_ttbr0_disable()) \
|
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), alt, \
|
|
|
|
CONFIG_ARM64_PAN)); \
|
2016-07-01 21:58:21 +08:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define __uaccess_enable(alt) \
|
|
|
|
do { \
|
2016-12-12 21:50:26 +08:00
|
|
|
if (!uaccess_ttbr0_enable()) \
|
2016-07-01 23:53:00 +08:00
|
|
|
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), alt, \
|
|
|
|
CONFIG_ARM64_PAN)); \
|
2016-07-01 21:58:21 +08:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
static inline void uaccess_disable(void)
|
|
|
|
{
|
|
|
|
__uaccess_disable(ARM64_HAS_PAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void uaccess_enable(void)
|
|
|
|
{
|
|
|
|
__uaccess_enable(ARM64_HAS_PAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* These functions are no-ops when UAO is present.
|
|
|
|
*/
|
|
|
|
static inline void uaccess_disable_not_uao(void)
|
|
|
|
{
|
|
|
|
__uaccess_disable(ARM64_ALT_PAN_NOT_UAO);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void uaccess_enable_not_uao(void)
|
|
|
|
{
|
|
|
|
__uaccess_enable(ARM64_ALT_PAN_NOT_UAO);
|
|
|
|
}
|
|
|
|
|
2018-02-05 23:34:19 +08:00
|
|
|
/*
|
|
|
|
* Sanitise a uaccess pointer such that it becomes NULL if above the
|
|
|
|
* current addr_limit.
|
|
|
|
*/
|
|
|
|
#define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr)
|
|
|
|
static inline void __user *__uaccess_mask_ptr(const void __user *ptr)
|
|
|
|
{
|
|
|
|
void __user *safe_ptr;
|
|
|
|
|
|
|
|
asm volatile(
|
|
|
|
" bics xzr, %1, %2\n"
|
|
|
|
" csel %0, %1, xzr, eq\n"
|
|
|
|
: "=&r" (safe_ptr)
|
|
|
|
: "r" (ptr), "r" (current_thread_info()->addr_limit)
|
|
|
|
: "cc");
|
|
|
|
|
|
|
|
csdb();
|
|
|
|
return safe_ptr;
|
|
|
|
}
|
|
|
|
|
2012-03-05 19:49:32 +08:00
|
|
|
/*
|
|
|
|
* The "__xxx" versions of the user access functions do not verify the address
|
|
|
|
* space - it must have been done previously with a separate "access_ok()"
|
|
|
|
* call.
|
|
|
|
*
|
|
|
|
* The "__xxx_error" versions set the third argument to -EFAULT if an error
|
|
|
|
* occurs, and leave it unchanged on success.
|
|
|
|
*/
|
2016-02-05 22:58:48 +08:00
|
|
|
#define __get_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
|
2012-03-05 19:49:32 +08:00
|
|
|
asm volatile( \
|
2016-02-05 22:58:48 +08:00
|
|
|
"1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
|
|
|
|
alt_instr " " reg "1, [%2]\n", feature) \
|
2012-03-05 19:49:32 +08:00
|
|
|
"2:\n" \
|
|
|
|
" .section .fixup, \"ax\"\n" \
|
|
|
|
" .align 2\n" \
|
|
|
|
"3: mov %w0, %3\n" \
|
|
|
|
" mov %1, #0\n" \
|
|
|
|
" b 2b\n" \
|
|
|
|
" .previous\n" \
|
2016-01-01 22:02:12 +08:00
|
|
|
_ASM_EXTABLE(1b, 3b) \
|
2012-03-05 19:49:32 +08:00
|
|
|
: "+r" (err), "=&r" (x) \
|
|
|
|
: "r" (addr), "i" (-EFAULT))
|
|
|
|
|
2019-01-15 21:58:26 +08:00
|
|
|
#define __raw_get_user(x, ptr, err) \
|
2012-03-05 19:49:32 +08:00
|
|
|
do { \
|
|
|
|
unsigned long __gu_val; \
|
2018-10-10 23:55:44 +08:00
|
|
|
__chk_user_ptr(ptr); \
|
|
|
|
uaccess_enable_not_uao(); \
|
2012-03-05 19:49:32 +08:00
|
|
|
switch (sizeof(*(ptr))) { \
|
|
|
|
case 1: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 2: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__get_user_asm("ldrh", "ldtrh", "%w", __gu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 4: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__get_user_asm("ldr", "ldtr", "%w", __gu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 8: \
|
arm64: uaccess: suppress spurious clang warning
Clang tries to warn when there's a mismatch between an operand's size,
and the size of the register it is held in, as this may indicate a bug.
Specifically, clang warns when the operand's type is less than 64 bits
wide, and the register is used unqualified (i.e. %N rather than %xN or
%wN).
Unfortunately clang can generate these warnings for unreachable code.
For example, for code like:
do { \
typeof(*(ptr)) __v = (v); \
switch(sizeof(*(ptr))) { \
case 1: \
// assume __v is 1 byte wide \
asm ("{op}b %w0" : : "r" (v)); \
break; \
case 8: \
// assume __v is 8 bytes wide \
asm ("{op} %0" : : "r" (v)); \
break; \
}
while (0)
... if op() were passed a char value and pointer to char, clang may
produce a warning for the unreachable case where sizeof(*(ptr)) is 8.
For the same reasons, clang produces warnings when __put_user_err() is
used for types that are less than 64 bits wide.
We could avoid this with a cast to a fixed-width type in each of the
cases. However, GCC will then warn that pointer types are being cast to
mismatched integer sizes (in unreachable paths).
Another option would be to use the same union trickery as we do for
__smp_store_release() and __smp_load_acquire(), but this is fairly
invasive.
Instead, this patch suppresses the clang warning by using an x modifier
in the assembly for the 8 byte case of __put_user_err(). No additional
work is necessary as the value has been cast to typeof(*(ptr)), so the
compiler will have performed any necessary extension for the reachable
case.
For consistency, __get_user_err() is also updated to use the x modifier
for its 8 byte case.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reported-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-05-03 23:09:38 +08:00
|
|
|
__get_user_asm("ldr", "ldtr", "%x", __gu_val, (ptr), \
|
2016-02-05 22:58:48 +08:00
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
default: \
|
|
|
|
BUILD_BUG(); \
|
|
|
|
} \
|
2018-09-06 19:09:56 +08:00
|
|
|
uaccess_disable_not_uao(); \
|
2018-10-10 23:55:44 +08:00
|
|
|
(x) = (__force __typeof__(*(ptr)))__gu_val; \
|
2018-09-06 19:09:56 +08:00
|
|
|
} while (0)
|
|
|
|
|
2019-01-15 21:58:26 +08:00
|
|
|
#define __get_user_error(x, ptr, err) \
|
|
|
|
do { \
|
2018-02-05 23:34:22 +08:00
|
|
|
__typeof__(*(ptr)) __user *__p = (ptr); \
|
|
|
|
might_fault(); \
|
Remove 'type' argument from access_ok() function
Nobody has actually used the type (VERIFY_READ vs VERIFY_WRITE) argument
of the user address range verification function since we got rid of the
old racy i386-only code to walk page tables by hand.
It existed because the original 80386 would not honor the write protect
bit when in kernel mode, so you had to do COW by hand before doing any
user access. But we haven't supported that in a long time, and these
days the 'type' argument is a purely historical artifact.
A discussion about extending 'user_access_begin()' to do the range
checking resulted this patch, because there is no way we're going to
move the old VERIFY_xyz interface to that model. And it's best done at
the end of the merge window when I've done most of my merges, so let's
just get this done once and for all.
This patch was mostly done with a sed-script, with manual fix-ups for
the cases that weren't of the trivial 'access_ok(VERIFY_xyz' form.
There were a couple of notable cases:
- csky still had the old "verify_area()" name as an alias.
- the iter_iov code had magical hardcoded knowledge of the actual
values of VERIFY_{READ,WRITE} (not that they mattered, since nothing
really used it)
- microblaze used the type argument for a debug printout
but other than those oddities this should be a total no-op patch.
I tried to fix up all architectures, did fairly extensive grepping for
access_ok() uses, and the changes are trivial, but I may have missed
something. Any missed conversion should be trivially fixable, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-01-04 10:57:57 +08:00
|
|
|
if (access_ok(__p, sizeof(*__p))) { \
|
2018-02-05 23:34:22 +08:00
|
|
|
__p = uaccess_mask_ptr(__p); \
|
2019-03-01 22:19:06 +08:00
|
|
|
__raw_get_user((x), __p, (err)); \
|
2018-02-05 23:34:22 +08:00
|
|
|
} else { \
|
|
|
|
(x) = 0; (err) = -EFAULT; \
|
|
|
|
} \
|
2019-01-15 21:58:26 +08:00
|
|
|
} while (0)
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2018-02-05 23:34:22 +08:00
|
|
|
#define __get_user(x, ptr) \
|
2012-03-05 19:49:32 +08:00
|
|
|
({ \
|
2018-02-05 23:34:22 +08:00
|
|
|
int __gu_err = 0; \
|
2019-01-15 21:58:26 +08:00
|
|
|
__get_user_error((x), (ptr), __gu_err); \
|
2018-02-05 23:34:22 +08:00
|
|
|
__gu_err; \
|
2012-03-05 19:49:32 +08:00
|
|
|
})
|
|
|
|
|
2018-02-05 23:34:22 +08:00
|
|
|
#define get_user __get_user
|
|
|
|
|
2016-02-05 22:58:48 +08:00
|
|
|
#define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
|
2012-03-05 19:49:32 +08:00
|
|
|
asm volatile( \
|
2016-02-05 22:58:48 +08:00
|
|
|
"1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
|
|
|
|
alt_instr " " reg "1, [%2]\n", feature) \
|
2012-03-05 19:49:32 +08:00
|
|
|
"2:\n" \
|
|
|
|
" .section .fixup,\"ax\"\n" \
|
|
|
|
" .align 2\n" \
|
|
|
|
"3: mov %w0, %3\n" \
|
|
|
|
" b 2b\n" \
|
|
|
|
" .previous\n" \
|
2016-01-01 22:02:12 +08:00
|
|
|
_ASM_EXTABLE(1b, 3b) \
|
2012-03-05 19:49:32 +08:00
|
|
|
: "+r" (err) \
|
|
|
|
: "r" (x), "r" (addr), "i" (-EFAULT))
|
|
|
|
|
2019-01-15 21:58:26 +08:00
|
|
|
#define __raw_put_user(x, ptr, err) \
|
2012-03-05 19:49:32 +08:00
|
|
|
do { \
|
|
|
|
__typeof__(*(ptr)) __pu_val = (x); \
|
2018-10-10 23:55:44 +08:00
|
|
|
__chk_user_ptr(ptr); \
|
|
|
|
uaccess_enable_not_uao(); \
|
2012-03-05 19:49:32 +08:00
|
|
|
switch (sizeof(*(ptr))) { \
|
|
|
|
case 1: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 2: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__put_user_asm("strh", "sttrh", "%w", __pu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 4: \
|
2016-02-05 22:58:48 +08:00
|
|
|
__put_user_asm("str", "sttr", "%w", __pu_val, (ptr), \
|
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
case 8: \
|
arm64: uaccess: suppress spurious clang warning
Clang tries to warn when there's a mismatch between an operand's size,
and the size of the register it is held in, as this may indicate a bug.
Specifically, clang warns when the operand's type is less than 64 bits
wide, and the register is used unqualified (i.e. %N rather than %xN or
%wN).
Unfortunately clang can generate these warnings for unreachable code.
For example, for code like:
do { \
typeof(*(ptr)) __v = (v); \
switch(sizeof(*(ptr))) { \
case 1: \
// assume __v is 1 byte wide \
asm ("{op}b %w0" : : "r" (v)); \
break; \
case 8: \
// assume __v is 8 bytes wide \
asm ("{op} %0" : : "r" (v)); \
break; \
}
while (0)
... if op() were passed a char value and pointer to char, clang may
produce a warning for the unreachable case where sizeof(*(ptr)) is 8.
For the same reasons, clang produces warnings when __put_user_err() is
used for types that are less than 64 bits wide.
We could avoid this with a cast to a fixed-width type in each of the
cases. However, GCC will then warn that pointer types are being cast to
mismatched integer sizes (in unreachable paths).
Another option would be to use the same union trickery as we do for
__smp_store_release() and __smp_load_acquire(), but this is fairly
invasive.
Instead, this patch suppresses the clang warning by using an x modifier
in the assembly for the 8 byte case of __put_user_err(). No additional
work is necessary as the value has been cast to typeof(*(ptr)), so the
compiler will have performed any necessary extension for the reachable
case.
For consistency, __get_user_err() is also updated to use the x modifier
for its 8 byte case.
Acked-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Reported-by: Matthias Kaehlcke <mka@chromium.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
2017-05-03 23:09:38 +08:00
|
|
|
__put_user_asm("str", "sttr", "%x", __pu_val, (ptr), \
|
2016-02-05 22:58:48 +08:00
|
|
|
(err), ARM64_HAS_UAO); \
|
2012-03-05 19:49:32 +08:00
|
|
|
break; \
|
|
|
|
default: \
|
|
|
|
BUILD_BUG(); \
|
|
|
|
} \
|
2016-07-01 21:58:21 +08:00
|
|
|
uaccess_disable_not_uao(); \
|
2012-03-05 19:49:32 +08:00
|
|
|
} while (0)
|
|
|
|
|
2019-01-15 21:58:26 +08:00
|
|
|
#define __put_user_error(x, ptr, err) \
|
|
|
|
do { \
|
2018-02-05 23:34:22 +08:00
|
|
|
__typeof__(*(ptr)) __user *__p = (ptr); \
|
|
|
|
might_fault(); \
|
Remove 'type' argument from access_ok() function
Nobody has actually used the type (VERIFY_READ vs VERIFY_WRITE) argument
of the user address range verification function since we got rid of the
old racy i386-only code to walk page tables by hand.
It existed because the original 80386 would not honor the write protect
bit when in kernel mode, so you had to do COW by hand before doing any
user access. But we haven't supported that in a long time, and these
days the 'type' argument is a purely historical artifact.
A discussion about extending 'user_access_begin()' to do the range
checking resulted this patch, because there is no way we're going to
move the old VERIFY_xyz interface to that model. And it's best done at
the end of the merge window when I've done most of my merges, so let's
just get this done once and for all.
This patch was mostly done with a sed-script, with manual fix-ups for
the cases that weren't of the trivial 'access_ok(VERIFY_xyz' form.
There were a couple of notable cases:
- csky still had the old "verify_area()" name as an alias.
- the iter_iov code had magical hardcoded knowledge of the actual
values of VERIFY_{READ,WRITE} (not that they mattered, since nothing
really used it)
- microblaze used the type argument for a debug printout
but other than those oddities this should be a total no-op patch.
I tried to fix up all architectures, did fairly extensive grepping for
access_ok() uses, and the changes are trivial, but I may have missed
something. Any missed conversion should be trivially fixable, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-01-04 10:57:57 +08:00
|
|
|
if (access_ok(__p, sizeof(*__p))) { \
|
2018-02-05 23:34:22 +08:00
|
|
|
__p = uaccess_mask_ptr(__p); \
|
2019-03-01 22:19:06 +08:00
|
|
|
__raw_put_user((x), __p, (err)); \
|
2018-02-05 23:34:22 +08:00
|
|
|
} else { \
|
|
|
|
(err) = -EFAULT; \
|
|
|
|
} \
|
2019-01-15 21:58:26 +08:00
|
|
|
} while (0)
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2018-02-05 23:34:22 +08:00
|
|
|
#define __put_user(x, ptr) \
|
2012-03-05 19:49:32 +08:00
|
|
|
({ \
|
2018-02-05 23:34:22 +08:00
|
|
|
int __pu_err = 0; \
|
2019-01-15 21:58:26 +08:00
|
|
|
__put_user_error((x), (ptr), __pu_err); \
|
2018-02-05 23:34:22 +08:00
|
|
|
__pu_err; \
|
2012-03-05 19:49:32 +08:00
|
|
|
})
|
|
|
|
|
2018-02-05 23:34:22 +08:00
|
|
|
#define put_user __put_user
|
|
|
|
|
2016-06-09 05:40:56 +08:00
|
|
|
extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
|
2018-02-05 23:34:23 +08:00
|
|
|
#define raw_copy_from_user(to, from, n) \
|
|
|
|
({ \
|
|
|
|
__arch_copy_from_user((to), __uaccess_mask_ptr(from), (n)); \
|
|
|
|
})
|
|
|
|
|
2016-06-09 05:40:56 +08:00
|
|
|
extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
|
2018-02-05 23:34:23 +08:00
|
|
|
#define raw_copy_to_user(to, from, n) \
|
|
|
|
({ \
|
|
|
|
__arch_copy_to_user(__uaccess_mask_ptr(to), (from), (n)); \
|
|
|
|
})
|
|
|
|
|
|
|
|
extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n);
|
|
|
|
#define raw_copy_in_user(to, from, n) \
|
|
|
|
({ \
|
|
|
|
__arch_copy_in_user(__uaccess_mask_ptr(to), \
|
|
|
|
__uaccess_mask_ptr(from), (n)); \
|
|
|
|
})
|
|
|
|
|
2017-03-21 20:40:57 +08:00
|
|
|
#define INLINE_COPY_TO_USER
|
|
|
|
#define INLINE_COPY_FROM_USER
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2018-02-05 23:34:23 +08:00
|
|
|
extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n);
|
|
|
|
static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n)
|
2012-03-05 19:49:32 +08:00
|
|
|
{
|
Remove 'type' argument from access_ok() function
Nobody has actually used the type (VERIFY_READ vs VERIFY_WRITE) argument
of the user address range verification function since we got rid of the
old racy i386-only code to walk page tables by hand.
It existed because the original 80386 would not honor the write protect
bit when in kernel mode, so you had to do COW by hand before doing any
user access. But we haven't supported that in a long time, and these
days the 'type' argument is a purely historical artifact.
A discussion about extending 'user_access_begin()' to do the range
checking resulted this patch, because there is no way we're going to
move the old VERIFY_xyz interface to that model. And it's best done at
the end of the merge window when I've done most of my merges, so let's
just get this done once and for all.
This patch was mostly done with a sed-script, with manual fix-ups for
the cases that weren't of the trivial 'access_ok(VERIFY_xyz' form.
There were a couple of notable cases:
- csky still had the old "verify_area()" name as an alias.
- the iter_iov code had magical hardcoded knowledge of the actual
values of VERIFY_{READ,WRITE} (not that they mattered, since nothing
really used it)
- microblaze used the type argument for a debug printout
but other than those oddities this should be a total no-op patch.
I tried to fix up all architectures, did fairly extensive grepping for
access_ok() uses, and the changes are trivial, but I may have missed
something. Any missed conversion should be trivially fixable, though.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2019-01-04 10:57:57 +08:00
|
|
|
if (access_ok(to, n))
|
2018-02-05 23:34:23 +08:00
|
|
|
n = __arch_clear_user(__uaccess_mask_ptr(to), n);
|
2012-03-05 19:49:32 +08:00
|
|
|
return n;
|
|
|
|
}
|
2018-02-05 23:34:23 +08:00
|
|
|
#define clear_user __clear_user
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2013-11-07 01:20:22 +08:00
|
|
|
extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2013-11-07 01:20:22 +08:00
|
|
|
extern __must_check long strnlen_user(const char __user *str, long n);
|
2012-03-05 19:49:32 +08:00
|
|
|
|
2017-07-25 18:55:43 +08:00
|
|
|
#ifdef CONFIG_ARCH_HAS_UACCESS_FLUSHCACHE
|
|
|
|
struct page;
|
|
|
|
void memcpy_page_flushcache(char *to, struct page *page, size_t offset, size_t len);
|
|
|
|
extern unsigned long __must_check __copy_user_flushcache(void *to, const void __user *from, unsigned long n);
|
|
|
|
|
|
|
|
static inline int __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size)
|
|
|
|
{
|
|
|
|
kasan_check_write(dst, size);
|
2018-02-05 23:34:23 +08:00
|
|
|
return __copy_user_flushcache(dst, __uaccess_mask_ptr(src), size);
|
2017-07-25 18:55:43 +08:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-03-05 19:49:32 +08:00
|
|
|
#endif /* __ASM_UACCESS_H */
|