forked from Minki/linux
Merge branch 'set_fs-4' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic into asm-generic
Christoph Hellwig and a few others spent a huge effort on removing set_fs() from most of the important architectures, but about half the other architectures were never completed even though most of them don't actually use set_fs() at all. I did a patch for microblaze at some point, which turned out to be fairly generic, and now ported it to most other architectures, using new generic implementations of access_ok() and __{get,put}_kernel_nocheck(). Three architectures (sparc64, ia64, and sh) needed some extra work, which I also completed. * 'set_fs-4' of git://git.kernel.org/pub/scm/linux/kernel/git/arnd/asm-generic: uaccess: remove CONFIG_SET_FS ia64: remove CONFIG_SET_FS support sh: remove CONFIG_SET_FS support sparc64: remove CONFIG_SET_FS support lib/test_lockup: fix kernel pointer check for separate address spaces uaccess: generalize access_ok() uaccess: fix type mismatch warnings from access_ok() arm64: simplify access_ok() m68k: fix access_ok for coldfire MIPS: use simpler access_ok() MIPS: Handle address errors for accesses above CPU max virtual user address uaccess: add generic __{get,put}_kernel_nofault nios2: drop access_ok() check from __put_user() x86: use more conventional access_ok() definition x86: remove __range_not_ok() sparc64: add __{get,put}_kernel_nofault() nds32: fix access_ok() checks in get/put_user uaccess: fix nios2 and microblaze get_user_8() uaccess: fix integer overflow on access_ok()
This commit is contained in:
commit
dd865f090f
10
arch/Kconfig
10
arch/Kconfig
@ -24,9 +24,6 @@ config KEXEC_ELF
|
||||
config HAVE_IMA_KEXEC
|
||||
bool
|
||||
|
||||
config SET_FS
|
||||
bool
|
||||
|
||||
config HOTPLUG_SMT
|
||||
bool
|
||||
|
||||
@ -898,6 +895,13 @@ config HAVE_SOFTIRQ_ON_OWN_STACK
|
||||
Architecture provides a function to run __do_softirq() on a
|
||||
separate stack.
|
||||
|
||||
config ALTERNATE_USER_ADDRESS_SPACE
|
||||
bool
|
||||
help
|
||||
Architectures set this when the CPU uses separate address
|
||||
spaces for kernel and user space pointers. In this case, the
|
||||
access_ok() check on a __user pointer is skipped.
|
||||
|
||||
config PGTABLE_LEVELS
|
||||
int
|
||||
default 2
|
||||
|
@ -35,7 +35,6 @@ config ALPHA
|
||||
select OLD_SIGSUSPEND
|
||||
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
|
||||
select MMU_GATHER_NO_RANGE
|
||||
select SET_FS
|
||||
select SPARSEMEM_EXTREME if SPARSEMEM
|
||||
select ZONE_DMA
|
||||
help
|
||||
|
@ -26,10 +26,6 @@
|
||||
#define TASK_UNMAPPED_BASE \
|
||||
((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2)
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/* This is dead. Everything has been moved to thread_info. */
|
||||
struct thread_struct { };
|
||||
#define INIT_THREAD { }
|
||||
|
@ -19,7 +19,6 @@ struct thread_info {
|
||||
unsigned int flags; /* low level flags */
|
||||
unsigned int ieee_state; /* see fpu.h */
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
unsigned cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
unsigned int status; /* thread-synchronous flags */
|
||||
@ -35,7 +34,6 @@ struct thread_info {
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
|
@ -2,47 +2,7 @@
|
||||
#ifndef __ALPHA_UACCESS_H
|
||||
#define __ALPHA_UACCESS_H
|
||||
|
||||
/*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
* performed or not. If get_fs() == USER_DS, checking is performed, with
|
||||
* get_fs() == KERNEL_DS, checking is bypassed.
|
||||
*
|
||||
* Or at least it did once upon a time. Nowadays it is a mask that
|
||||
* defines which bits of the address space are off limits. This is a
|
||||
* wee bit faster than the above.
|
||||
*
|
||||
* For historical reasons, these macros are grossly misnamed.
|
||||
*/
|
||||
|
||||
#define KERNEL_DS ((mm_segment_t) { 0UL })
|
||||
#define USER_DS ((mm_segment_t) { -0x40000000000UL })
|
||||
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define set_fs(x) (current_thread_info()->addr_limit = (x))
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
/*
|
||||
* Is a address valid? This does a straightforward calculation rather
|
||||
* than tests.
|
||||
*
|
||||
* Address valid if:
|
||||
* - "addr" doesn't have any high-bits set
|
||||
* - AND "size" doesn't have any high-bits set
|
||||
* - AND "addr+size-(size != 0)" doesn't have any high-bits set
|
||||
* - OR we are in kernel mode.
|
||||
*/
|
||||
#define __access_ok(addr, size) ({ \
|
||||
unsigned long __ao_a = (addr), __ao_b = (size); \
|
||||
unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b; \
|
||||
(get_fs().seg & (__ao_a | __ao_b | __ao_end)) == 0; })
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
({ \
|
||||
__chk_user_ptr(addr); \
|
||||
__access_ok(((unsigned long)(addr)), (size)); \
|
||||
})
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
/*
|
||||
* These are the main single-value transfer routines. They automatically
|
||||
* use the right size if we just have the right pointer type.
|
||||
@ -105,7 +65,7 @@ extern void __get_user_unknown(void);
|
||||
long __gu_err = -EFAULT; \
|
||||
unsigned long __gu_val = 0; \
|
||||
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
|
||||
if (__access_ok((unsigned long)__gu_addr, size)) { \
|
||||
if (__access_ok(__gu_addr, size)) { \
|
||||
__gu_err = 0; \
|
||||
switch (size) { \
|
||||
case 1: __get_user_8(__gu_addr); break; \
|
||||
@ -200,7 +160,7 @@ extern void __put_user_unknown(void);
|
||||
({ \
|
||||
long __pu_err = -EFAULT; \
|
||||
__typeof__(*(ptr)) __user *__pu_addr = (ptr); \
|
||||
if (__access_ok((unsigned long)__pu_addr, size)) { \
|
||||
if (__access_ok(__pu_addr, size)) { \
|
||||
__pu_err = 0; \
|
||||
switch (size) { \
|
||||
case 1: __put_user_8(x, __pu_addr); break; \
|
||||
@ -316,17 +276,14 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long len)
|
||||
|
||||
extern long __clear_user(void __user *to, long len);
|
||||
|
||||
extern inline long
|
||||
static inline long
|
||||
clear_user(void __user *to, long len)
|
||||
{
|
||||
if (__access_ok((unsigned long)to, len))
|
||||
if (__access_ok(to, len))
|
||||
len = __clear_user(to, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
#define user_addr_max() \
|
||||
(uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
|
||||
extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
|
||||
|
@ -45,7 +45,6 @@ config ARC
|
||||
select PCI_SYSCALL if PCI
|
||||
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
|
||||
select HAVE_ARCH_JUMP_LABEL if ISA_ARCV2 && !CPU_ENDIAN_BE32
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
|
@ -1,20 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*/
|
||||
|
||||
#ifndef __ASMARC_SEGMENT_H
|
||||
#define __ASMARC_SEGMENT_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
|
||||
#define KERNEL_DS MAKE_MM_SEG(0)
|
||||
#define USER_DS MAKE_MM_SEG(TASK_SIZE)
|
||||
#define uaccess_kernel() (get_fs() == KERNEL_DS)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASMARC_SEGMENT_H */
|
@ -27,7 +27,6 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to
|
||||
@ -40,7 +39,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
struct task_struct *task; /* main task structure */
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
__u32 cpu; /* current CPU */
|
||||
unsigned long thr_ptr; /* TLS ptr */
|
||||
};
|
||||
@ -56,7 +54,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
||||
|
@ -23,35 +23,6 @@
|
||||
|
||||
#include <linux/string.h> /* for generic string functions */
|
||||
|
||||
|
||||
#define __kernel_ok (uaccess_kernel())
|
||||
|
||||
/*
|
||||
* Algorithmically, for __user_ok() we want do:
|
||||
* (start < TASK_SIZE) && (start+len < TASK_SIZE)
|
||||
* where TASK_SIZE could either be retrieved from thread_info->addr_limit or
|
||||
* emitted directly in code.
|
||||
*
|
||||
* This can however be rewritten as follows:
|
||||
* (len <= TASK_SIZE) && (start+len < TASK_SIZE)
|
||||
*
|
||||
* Because it essentially checks if buffer end is within limit and @len is
|
||||
* non-ngeative, which implies that buffer start will be within limit too.
|
||||
*
|
||||
* The reason for rewriting being, for majority of cases, @len is generally
|
||||
* compile time constant, causing first sub-expression to be compile time
|
||||
* subsumed.
|
||||
*
|
||||
* The second part would generate weird large LIMMs e.g. (0x6000_0000 - 0x10),
|
||||
* so we check for TASK_SIZE using get_fs() since the addr_limit load from mem
|
||||
* would already have been done at this call site for __kernel_ok()
|
||||
*
|
||||
*/
|
||||
#define __user_ok(addr, sz) (((sz) <= TASK_SIZE) && \
|
||||
((addr) <= (get_fs() - (sz))))
|
||||
#define __access_ok(addr, sz) (unlikely(__kernel_ok) || \
|
||||
likely(__user_ok((addr), (sz))))
|
||||
|
||||
/*********** Single byte/hword/word copies ******************/
|
||||
|
||||
#define __get_user_fn(sz, u, k) \
|
||||
@ -667,7 +638,6 @@ extern unsigned long arc_clear_user_noinline(void __user *to,
|
||||
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ SYSCALL_DEFINE0(arc_gettls)
|
||||
return task_thread_info(current)->thr_ptr;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(arc_usr_cmpxchg, int *, uaddr, int, expected, int, new)
|
||||
SYSCALL_DEFINE3(arc_usr_cmpxchg, int __user *, uaddr, int, expected, int, new)
|
||||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
u32 uval;
|
||||
|
@ -55,21 +55,6 @@ extern int __put_user_bad(void);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
/*
|
||||
* We use 33-bit arithmetic here. Success returns zero, failure returns
|
||||
* addr_limit. We take advantage that addr_limit will be zero for KERNEL_DS,
|
||||
* so this will always return success in that case.
|
||||
*/
|
||||
#define __range_ok(addr, size) ({ \
|
||||
unsigned long flag, roksum; \
|
||||
__chk_user_ptr(addr); \
|
||||
__asm__(".syntax unified\n" \
|
||||
"adds %1, %2, %3; sbcscc %1, %1, %0; movcc %0, #0" \
|
||||
: "=&r" (flag), "=&r" (roksum) \
|
||||
: "r" (addr), "Ir" (size), "0" (TASK_SIZE) \
|
||||
: "cc"); \
|
||||
flag; })
|
||||
|
||||
/*
|
||||
* This is a type: either unsigned long, if the argument fits into
|
||||
* that type, or otherwise unsigned long long.
|
||||
@ -241,15 +226,12 @@ extern int __put_user_8(void *, unsigned long long);
|
||||
|
||||
#else /* CONFIG_MMU */
|
||||
|
||||
#define __addr_ok(addr) ((void)(addr), 1)
|
||||
#define __range_ok(addr, size) ((void)(addr), 0)
|
||||
|
||||
#define get_user(x, p) __get_user(x, p)
|
||||
#define __put_user_check __put_user_nocheck
|
||||
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
#define access_ok(addr, size) (__range_ok(addr, size) == 0)
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#ifdef CONFIG_CPU_SPECTRE
|
||||
/*
|
||||
@ -476,8 +458,6 @@ do { \
|
||||
: "r" (x), "i" (-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
do { \
|
||||
const type *__pk_ptr = (src); \
|
||||
|
@ -195,7 +195,7 @@ static int swp_handler(struct pt_regs *regs, unsigned int instr)
|
||||
destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
|
||||
|
||||
/* Check access in reasonable access range for both SWP and SWPB */
|
||||
if (!access_ok((address & ~3), 4)) {
|
||||
if (!access_ok((void __user *)(address & ~3), 4)) {
|
||||
pr_debug("SWP{B} emulation: access to %p not allowed!\n",
|
||||
(void *)address);
|
||||
res = -EFAULT;
|
||||
|
@ -576,7 +576,7 @@ do_cache_op(unsigned long start, unsigned long end, int flags)
|
||||
if (end < start || flags)
|
||||
return -EINVAL;
|
||||
|
||||
if (!access_ok(start, end - start))
|
||||
if (!access_ok((void __user *)start, end - start))
|
||||
return -EFAULT;
|
||||
|
||||
return __do_cache_op(start, end);
|
||||
|
@ -92,11 +92,6 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
|
||||
unsigned long ua_flags;
|
||||
int atomic;
|
||||
|
||||
if (uaccess_kernel()) {
|
||||
memcpy((void *)to, from, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the mmap semaphore is taken only if not in an atomic context */
|
||||
atomic = faulthandler_disabled();
|
||||
|
||||
@ -165,11 +160,6 @@ __clear_user_memset(void __user *addr, unsigned long n)
|
||||
{
|
||||
unsigned long ua_flags;
|
||||
|
||||
if (uaccess_kernel()) {
|
||||
memset((void *)addr, 0, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmap_read_lock(current->mm);
|
||||
while (n) {
|
||||
pte_t *pte;
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <asm/memory.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
static inline int __access_ok(const void __user *ptr, unsigned long size);
|
||||
|
||||
/*
|
||||
* Test whether a block of memory is a valid user space address.
|
||||
@ -35,10 +35,8 @@
|
||||
* This is equivalent to the following test:
|
||||
* (u65)addr + (u65)size <= (u65)TASK_SIZE_MAX
|
||||
*/
|
||||
static inline unsigned long __range_ok(const void __user *addr, unsigned long size)
|
||||
static inline int access_ok(const void __user *addr, unsigned long size)
|
||||
{
|
||||
unsigned long ret, limit = TASK_SIZE_MAX - 1;
|
||||
|
||||
/*
|
||||
* Asynchronous I/O running in a kernel thread does not have the
|
||||
* TIF_TAGGED_ADDR flag of the process owning the mm, so always untag
|
||||
@ -48,28 +46,11 @@ static inline unsigned long __range_ok(const void __user *addr, unsigned long si
|
||||
(current->flags & PF_KTHREAD || test_thread_flag(TIF_TAGGED_ADDR)))
|
||||
addr = untagged_addr(addr);
|
||||
|
||||
__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
|
||||
" adds %0, %3, %2\n"
|
||||
// 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"
|
||||
: "=&r" (ret), "+r" (limit) : "Ir" (size), "0" (addr) : "cc");
|
||||
|
||||
return ret;
|
||||
return likely(__access_ok(addr, size));
|
||||
}
|
||||
#define access_ok access_ok
|
||||
|
||||
#define access_ok(addr, size) __range_ok(addr, size)
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* User access enabling/disabling.
|
||||
|
@ -519,7 +519,7 @@ void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr)
|
||||
NOKPROBE_SYMBOL(do_ptrauth_fault);
|
||||
|
||||
#define __user_cache_maint(insn, address, res) \
|
||||
if (address >= user_addr_max()) { \
|
||||
if (address >= TASK_SIZE_MAX) { \
|
||||
res = -EFAULT; \
|
||||
} else { \
|
||||
uaccess_ttbr0_enable(); \
|
||||
|
@ -79,7 +79,6 @@ config CSKY
|
||||
select PCI_DOMAINS_GENERIC if PCI
|
||||
select PCI_SYSCALL if PCI
|
||||
select PCI_MSI if PCI
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
|
@ -4,7 +4,6 @@
|
||||
#define __ASM_CSKY_PROCESSOR_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/cache.h>
|
||||
@ -59,7 +58,6 @@ struct thread_struct {
|
||||
*/
|
||||
#define start_thread(_regs, _pc, _usp) \
|
||||
do { \
|
||||
set_fs(USER_DS); /* reads from user space */ \
|
||||
(_regs)->pc = (_pc); \
|
||||
(_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */ \
|
||||
(_regs)->regs[2] = 0; \
|
||||
|
@ -1,10 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __ASM_CSKY_SEGMENT_H
|
||||
#define __ASM_CSKY_SEGMENT_H
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#endif /* __ASM_CSKY_SEGMENT_H */
|
@ -16,7 +16,6 @@ struct thread_info {
|
||||
unsigned long flags;
|
||||
int preempt_count;
|
||||
unsigned long tp_value;
|
||||
mm_segment_t addr_limit;
|
||||
struct restart_block restart_block;
|
||||
struct pt_regs *regs;
|
||||
unsigned int cpu;
|
||||
@ -26,7 +25,6 @@ struct thread_info {
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.cpu = 0, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
|
@ -3,17 +3,6 @@
|
||||
#ifndef __ASM_CSKY_UACCESS_H
|
||||
#define __ASM_CSKY_UACCESS_H
|
||||
|
||||
#define user_addr_max() \
|
||||
(uaccess_kernel() ? KERNEL_DS.seg : get_fs().seg)
|
||||
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
unsigned long limit = current_thread_info()->addr_limit.seg;
|
||||
|
||||
return ((addr < limit) && ((addr + size) < limit));
|
||||
}
|
||||
#define __access_ok __access_ok
|
||||
|
||||
/*
|
||||
* __put_user_fn
|
||||
*/
|
||||
@ -209,7 +198,6 @@ unsigned long raw_copy_to_user(void *to, const void *from, unsigned long n);
|
||||
unsigned long __clear_user(void __user *to, unsigned long n);
|
||||
#define __clear_user __clear_user
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
#endif /* __ASM_CSKY_UACCESS_H */
|
||||
|
@ -25,7 +25,6 @@ int main(void)
|
||||
/* offsets into the thread_info struct */
|
||||
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TINFO_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TINFO_TP_VALUE, offsetof(struct thread_info, tp_value));
|
||||
DEFINE(TINFO_TASK, offsetof(struct thread_info, task));
|
||||
|
||||
|
@ -49,7 +49,7 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
|
||||
{
|
||||
struct stackframe buftail;
|
||||
unsigned long lr = 0;
|
||||
unsigned long *user_frame_tail = (unsigned long *)fp;
|
||||
unsigned long __user *user_frame_tail = (unsigned long __user *)fp;
|
||||
|
||||
/* Check accessibility of one struct frame_tail beyond */
|
||||
if (!access_ok(user_frame_tail, sizeof(buftail)))
|
||||
|
@ -136,7 +136,7 @@ static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
static int
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
@ -24,7 +24,6 @@ config H8300
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_HASH
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select SET_FS
|
||||
select UACCESS_MEMCPY
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
|
@ -13,7 +13,6 @@
|
||||
#define __ASM_H8300_PROCESSOR_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _H8300_SEGMENT_H
|
||||
#define _H8300_SEGMENT_H
|
||||
|
||||
/* define constants */
|
||||
#define USER_DATA (1)
|
||||
#ifndef __USER_DS
|
||||
#define __USER_DS (USER_DATA)
|
||||
#endif
|
||||
#define USER_PROGRAM (2)
|
||||
#define SUPER_DATA (3)
|
||||
#ifndef __KERNEL_DS
|
||||
#define __KERNEL_DS (SUPER_DATA)
|
||||
#endif
|
||||
#define SUPER_PROGRAM (4)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
#define USER_DS MAKE_MM_SEG(__USER_DS)
|
||||
#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
|
||||
|
||||
/*
|
||||
* Get/set the SFC/DFC registers for MOVES instructions
|
||||
*/
|
||||
|
||||
static inline mm_segment_t get_fs(void)
|
||||
{
|
||||
return USER_DS;
|
||||
}
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _H8300_SEGMENT_H */
|
@ -10,7 +10,6 @@
|
||||
#define _ASM_THREAD_INFO_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
@ -31,7 +30,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -43,7 +41,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/sys.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
@ -71,11 +70,6 @@ void __init paging_init(void)
|
||||
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||
__func__, PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Set up SFC/DFC registers (user data space).
|
||||
*/
|
||||
set_fs(USER_DS);
|
||||
|
||||
pr_debug("before free_area_init\n");
|
||||
|
||||
pr_debug("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -30,7 +30,6 @@ config HEXAGON
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_CPU_DEVICES
|
||||
select SET_FS
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
help
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/*
|
||||
* This is union'd with the "bottom" of the kernel stack.
|
||||
* It keeps track of thread info which is handy for routines
|
||||
@ -37,7 +33,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current cpu */
|
||||
int preempt_count; /* 0=>preemptible,<0=>BUG */
|
||||
mm_segment_t addr_limit; /* segmentation sux */
|
||||
/*
|
||||
* used for syscalls somehow;
|
||||
* seems to have a function pointer and four arguments
|
||||
@ -66,7 +61,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = 1, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.sp = 0, \
|
||||
.regs = NULL, \
|
||||
}
|
||||
|
@ -12,31 +12,6 @@
|
||||
*/
|
||||
#include <asm/sections.h>
|
||||
|
||||
/*
|
||||
* access_ok: - Checks if a user space pointer is valid
|
||||
* @addr: User space pointer to start of block to check
|
||||
* @size: Size of block to check
|
||||
*
|
||||
* Context: User context only. This function may sleep if pagefaults are
|
||||
* enabled.
|
||||
*
|
||||
* Checks if a pointer to a block of memory in user space is valid.
|
||||
*
|
||||
* Returns true (nonzero) if the memory block *may* be valid, false (zero)
|
||||
* if it is definitely invalid.
|
||||
*
|
||||
* User address space in Hexagon, like x86, goes to 0xbfffffff, so the
|
||||
* simple MSB-based tests used by MIPS won't work. Some further
|
||||
* optimization is probably possible here, but for now, keep it
|
||||
* reasonably simple and not *too* slow. After all, we've got the
|
||||
* MMU for backup.
|
||||
*/
|
||||
|
||||
#define __access_ok(addr, size) \
|
||||
((get_fs().seg == KERNEL_DS.seg) || \
|
||||
(((unsigned long)addr < get_fs().seg) && \
|
||||
(unsigned long)size < (get_fs().seg - (unsigned long)addr)))
|
||||
|
||||
/*
|
||||
* When a kernel-mode page fault is taken, the faulting instruction
|
||||
* address is checked against a table of exception_table_entries.
|
||||
|
@ -105,7 +105,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
|
||||
/*
|
||||
* Parent sees new pid -- not necessary, not even possible at
|
||||
* this point in the fork process
|
||||
* Might also want to set things like ti->addr_limit
|
||||
*/
|
||||
|
||||
return 0;
|
||||
|
@ -61,7 +61,6 @@ config IA64
|
||||
select NEED_SG_DMA_LENGTH
|
||||
select NUMA if !FLATMEM
|
||||
select PCI_MSI_ARCH_FALLBACKS if PCI_MSI
|
||||
select SET_FS
|
||||
select ZONE_DMA32
|
||||
default y
|
||||
help
|
||||
|
@ -243,10 +243,6 @@ DECLARE_PER_CPU(struct cpuinfo_ia64, ia64_cpu_info);
|
||||
|
||||
extern void print_cpu_info (struct cpuinfo_ia64 *);
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#define SET_UNALIGN_CTL(task,value) \
|
||||
({ \
|
||||
(task)->thread.flags = (((task)->thread.flags & ~IA64_THREAD_UAC_MASK) \
|
||||
|
@ -27,7 +27,6 @@ struct thread_info {
|
||||
__u32 cpu; /* current CPU */
|
||||
__u32 last_cpu; /* Last CPU thread ran on */
|
||||
__u32 status; /* Thread synchronous flags */
|
||||
mm_segment_t addr_limit; /* user-level address space limit */
|
||||
int preempt_count; /* 0=premptable, <0=BUG; will also serve as bh-counter */
|
||||
#ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE
|
||||
__u64 utime;
|
||||
@ -48,7 +47,6 @@ struct thread_info {
|
||||
.task = &tsk, \
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
|
@ -42,30 +42,20 @@
|
||||
#include <asm/extable.h>
|
||||
|
||||
/*
|
||||
* For historical reasons, the following macros are grossly misnamed:
|
||||
*/
|
||||
#define KERNEL_DS ((mm_segment_t) { ~0UL }) /* cf. access_ok() */
|
||||
#define USER_DS ((mm_segment_t) { TASK_SIZE-1 }) /* cf. access_ok() */
|
||||
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define set_fs(x) (current_thread_info()->addr_limit = (x))
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
/*
|
||||
* When accessing user memory, we need to make sure the entire area really is in
|
||||
* user-level space. In order to do this efficiently, we make sure that the page at
|
||||
* address TASK_SIZE is never valid. We also need to make sure that the address doesn't
|
||||
* When accessing user memory, we need to make sure the entire area really is
|
||||
* in user-level space. We also need to make sure that the address doesn't
|
||||
* point inside the virtually mapped linear page table.
|
||||
*/
|
||||
static inline int __access_ok(const void __user *p, unsigned long size)
|
||||
{
|
||||
unsigned long limit = TASK_SIZE;
|
||||
unsigned long addr = (unsigned long)p;
|
||||
unsigned long seg = get_fs().seg;
|
||||
return likely(addr <= seg) &&
|
||||
(seg == KERNEL_DS.seg || likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT));
|
||||
|
||||
return likely((size <= limit) && (addr <= (limit - size)) &&
|
||||
likely(REGION_OFFSET(addr) < RGN_MAP_LIMIT));
|
||||
}
|
||||
#define access_ok(addr, size) __access_ok((addr), (size))
|
||||
#define __access_ok __access_ok
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* These are the main single-value transfer routines. They automatically
|
||||
|
@ -749,9 +749,25 @@ emulate_load_updates (update_t type, load_store_t ld, struct pt_regs *regs, unsi
|
||||
}
|
||||
}
|
||||
|
||||
static int emulate_store(unsigned long ifa, void *val, int len, bool kernel_mode)
|
||||
{
|
||||
if (kernel_mode)
|
||||
return copy_to_kernel_nofault((void *)ifa, val, len);
|
||||
|
||||
return copy_to_user((void __user *)ifa, val, len);
|
||||
}
|
||||
|
||||
static int emulate_load(void *val, unsigned long ifa, int len, bool kernel_mode)
|
||||
{
|
||||
if (kernel_mode)
|
||||
return copy_from_kernel_nofault(val, (void *)ifa, len);
|
||||
|
||||
return copy_from_user(val, (void __user *)ifa, len);
|
||||
}
|
||||
|
||||
static int
|
||||
emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
|
||||
bool kernel_mode)
|
||||
{
|
||||
unsigned int len = 1 << ld.x6_sz;
|
||||
unsigned long val = 0;
|
||||
@ -774,7 +790,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
return -1;
|
||||
}
|
||||
/* this assumes little-endian byte-order: */
|
||||
if (copy_from_user(&val, (void __user *) ifa, len))
|
||||
if (emulate_load(&val, ifa, len, kernel_mode))
|
||||
return -1;
|
||||
setreg(ld.r1, val, 0, regs);
|
||||
|
||||
@ -872,7 +888,8 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
static int
|
||||
emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
|
||||
bool kernel_mode)
|
||||
{
|
||||
unsigned long r2;
|
||||
unsigned int len = 1 << ld.x6_sz;
|
||||
@ -901,7 +918,7 @@ emulate_store_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/* this assumes little-endian byte-order: */
|
||||
if (copy_to_user((void __user *) ifa, &r2, len))
|
||||
if (emulate_store(ifa, &r2, len, kernel_mode))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@ -1021,7 +1038,7 @@ float2mem_double (struct ia64_fpreg *init, struct ia64_fpreg *final)
|
||||
}
|
||||
|
||||
static int
|
||||
emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs, bool kernel_mode)
|
||||
{
|
||||
struct ia64_fpreg fpr_init[2];
|
||||
struct ia64_fpreg fpr_final[2];
|
||||
@ -1050,8 +1067,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs
|
||||
* This assumes little-endian byte-order. Note that there is no "ldfpe"
|
||||
* instruction:
|
||||
*/
|
||||
if (copy_from_user(&fpr_init[0], (void __user *) ifa, len)
|
||||
|| copy_from_user(&fpr_init[1], (void __user *) (ifa + len), len))
|
||||
if (emulate_load(&fpr_init[0], ifa, len, kernel_mode)
|
||||
|| emulate_load(&fpr_init[1], (ifa + len), len, kernel_mode))
|
||||
return -1;
|
||||
|
||||
DPRINT("ld.r1=%d ld.imm=%d x6_sz=%d\n", ld.r1, ld.imm, ld.x6_sz);
|
||||
@ -1126,7 +1143,8 @@ emulate_load_floatpair (unsigned long ifa, load_store_t ld, struct pt_regs *regs
|
||||
|
||||
|
||||
static int
|
||||
emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
|
||||
bool kernel_mode)
|
||||
{
|
||||
struct ia64_fpreg fpr_init;
|
||||
struct ia64_fpreg fpr_final;
|
||||
@ -1152,7 +1170,7 @@ emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
* See comments in ldX for descriptions on how the various loads are handled.
|
||||
*/
|
||||
if (ld.x6_op != 0x2) {
|
||||
if (copy_from_user(&fpr_init, (void __user *) ifa, len))
|
||||
if (emulate_load(&fpr_init, ifa, len, kernel_mode))
|
||||
return -1;
|
||||
|
||||
DPRINT("ld.r1=%d x6_sz=%d\n", ld.r1, ld.x6_sz);
|
||||
@ -1202,7 +1220,8 @@ emulate_load_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
|
||||
|
||||
static int
|
||||
emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs,
|
||||
bool kernel_mode)
|
||||
{
|
||||
struct ia64_fpreg fpr_init;
|
||||
struct ia64_fpreg fpr_final;
|
||||
@ -1244,7 +1263,7 @@ emulate_store_float (unsigned long ifa, load_store_t ld, struct pt_regs *regs)
|
||||
DDUMP("fpr_init =", &fpr_init, len);
|
||||
DDUMP("fpr_final =", &fpr_final, len);
|
||||
|
||||
if (copy_to_user((void __user *) ifa, &fpr_final, len))
|
||||
if (emulate_store(ifa, &fpr_final, len, kernel_mode))
|
||||
return -1;
|
||||
|
||||
/*
|
||||
@ -1295,7 +1314,6 @@ void
|
||||
ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
{
|
||||
struct ia64_psr *ipsr = ia64_psr(regs);
|
||||
mm_segment_t old_fs = get_fs();
|
||||
unsigned long bundle[2];
|
||||
unsigned long opcode;
|
||||
const struct exception_table_entry *eh = NULL;
|
||||
@ -1304,6 +1322,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
load_store_t insn;
|
||||
} u;
|
||||
int ret = -1;
|
||||
bool kernel_mode = false;
|
||||
|
||||
if (ia64_psr(regs)->be) {
|
||||
/* we don't support big-endian accesses */
|
||||
@ -1367,13 +1386,13 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
if (unaligned_dump_stack)
|
||||
dump_stack();
|
||||
}
|
||||
set_fs(KERNEL_DS);
|
||||
kernel_mode = true;
|
||||
}
|
||||
|
||||
DPRINT("iip=%lx ifa=%lx isr=%lx (ei=%d, sp=%d)\n",
|
||||
regs->cr_iip, ifa, regs->cr_ipsr, ipsr->ri, ipsr->it);
|
||||
|
||||
if (__copy_from_user(bundle, (void __user *) regs->cr_iip, 16))
|
||||
if (emulate_load(bundle, regs->cr_iip, 16, kernel_mode))
|
||||
goto failure;
|
||||
|
||||
/*
|
||||
@ -1467,7 +1486,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
case LDCCLR_IMM_OP:
|
||||
case LDCNC_IMM_OP:
|
||||
case LDCCLRACQ_IMM_OP:
|
||||
ret = emulate_load_int(ifa, u.insn, regs);
|
||||
ret = emulate_load_int(ifa, u.insn, regs, kernel_mode);
|
||||
break;
|
||||
|
||||
case ST_OP:
|
||||
@ -1478,7 +1497,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
fallthrough;
|
||||
case ST_IMM_OP:
|
||||
case STREL_IMM_OP:
|
||||
ret = emulate_store_int(ifa, u.insn, regs);
|
||||
ret = emulate_store_int(ifa, u.insn, regs, kernel_mode);
|
||||
break;
|
||||
|
||||
case LDF_OP:
|
||||
@ -1486,21 +1505,21 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
case LDFCCLR_OP:
|
||||
case LDFCNC_OP:
|
||||
if (u.insn.x)
|
||||
ret = emulate_load_floatpair(ifa, u.insn, regs);
|
||||
ret = emulate_load_floatpair(ifa, u.insn, regs, kernel_mode);
|
||||
else
|
||||
ret = emulate_load_float(ifa, u.insn, regs);
|
||||
ret = emulate_load_float(ifa, u.insn, regs, kernel_mode);
|
||||
break;
|
||||
|
||||
case LDF_IMM_OP:
|
||||
case LDFA_IMM_OP:
|
||||
case LDFCCLR_IMM_OP:
|
||||
case LDFCNC_IMM_OP:
|
||||
ret = emulate_load_float(ifa, u.insn, regs);
|
||||
ret = emulate_load_float(ifa, u.insn, regs, kernel_mode);
|
||||
break;
|
||||
|
||||
case STF_OP:
|
||||
case STF_IMM_OP:
|
||||
ret = emulate_store_float(ifa, u.insn, regs);
|
||||
ret = emulate_store_float(ifa, u.insn, regs, kernel_mode);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1521,7 +1540,6 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
||||
|
||||
DPRINT("ipsr->ri=%d iip=%lx\n", ipsr->ri, regs->cr_iip);
|
||||
done:
|
||||
set_fs(old_fs); /* restore original address limit */
|
||||
return;
|
||||
|
||||
failure:
|
||||
|
@ -453,6 +453,7 @@ config CPU_HAS_NO_UNALIGNED
|
||||
|
||||
config CPU_HAS_ADDRESS_SPACES
|
||||
bool
|
||||
select ALTERNATE_USER_ADDRESS_SPACE
|
||||
|
||||
config FPU
|
||||
bool
|
||||
|
@ -10,17 +10,7 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
/* We let the MMU do all checking */
|
||||
static inline int access_ok(const void __user *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
/*
|
||||
* XXX: for !CONFIG_CPU_HAS_ADDRESS_SPACES this really needs to check
|
||||
* for TASK_SIZE!
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* Not all varients of the 68k family support the notion of address spaces.
|
||||
@ -390,8 +380,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
|
||||
#define INLINE_COPY_FROM_USER
|
||||
#define INLINE_COPY_TO_USER
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
do { \
|
||||
type *__gk_dst = (type *)(dst); \
|
||||
|
@ -42,7 +42,6 @@ config MICROBLAZE
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select MMU_GATHER_NO_RANGE
|
||||
select SPARSE_IRQ
|
||||
select SET_FS
|
||||
select ZONE_DMA
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
|
@ -56,17 +56,12 @@ struct cpu_context {
|
||||
__u32 fsr;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
unsigned long status; /* thread-synchronous flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
|
||||
struct cpu_context cpu_context;
|
||||
};
|
||||
@ -80,7 +75,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -15,48 +15,7 @@
|
||||
#include <linux/pgtable.h>
|
||||
#include <asm/extable.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/*
|
||||
* On Microblaze the fs value is actually the top of the corresponding
|
||||
* address space.
|
||||
*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
* performed or not. If get_fs() == USER_DS, checking is performed, with
|
||||
* get_fs() == KERNEL_DS, checking is bypassed.
|
||||
*
|
||||
* For historical reasons, these macros are grossly misnamed.
|
||||
*
|
||||
* For non-MMU arch like Microblaze, KERNEL_DS and USER_DS is equal.
|
||||
*/
|
||||
# define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
|
||||
# define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF)
|
||||
# define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
|
||||
|
||||
# define get_fs() (current_thread_info()->addr_limit)
|
||||
# define set_fs(val) (current_thread_info()->addr_limit = (val))
|
||||
# define user_addr_max() get_fs().seg
|
||||
|
||||
# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
static inline int access_ok(const void __user *addr, unsigned long size)
|
||||
{
|
||||
if (!size)
|
||||
goto ok;
|
||||
|
||||
if ((get_fs().seg < ((unsigned long)addr)) ||
|
||||
(get_fs().seg < ((unsigned long)addr + size - 1))) {
|
||||
pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 0;
|
||||
}
|
||||
ok:
|
||||
pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n",
|
||||
(__force u32)addr, (u32)size,
|
||||
(u32)get_fs().seg);
|
||||
return 1;
|
||||
}
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||
@ -141,27 +100,27 @@ extern long __user_bad(void);
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
({ \
|
||||
unsigned long __gu_val = 0; \
|
||||
long __gu_err; \
|
||||
switch (sizeof(*(ptr))) { \
|
||||
case 1: \
|
||||
__get_user_asm("lbu", (ptr), __gu_val, __gu_err); \
|
||||
__get_user_asm("lbu", (ptr), x, __gu_err); \
|
||||
break; \
|
||||
case 2: \
|
||||
__get_user_asm("lhu", (ptr), __gu_val, __gu_err); \
|
||||
__get_user_asm("lhu", (ptr), x, __gu_err); \
|
||||
break; \
|
||||
case 4: \
|
||||
__get_user_asm("lw", (ptr), __gu_val, __gu_err); \
|
||||
__get_user_asm("lw", (ptr), x, __gu_err); \
|
||||
break; \
|
||||
case 8: \
|
||||
__gu_err = __copy_from_user(&__gu_val, ptr, 8); \
|
||||
if (__gu_err) \
|
||||
__gu_err = -EFAULT; \
|
||||
case 8: { \
|
||||
__u64 __x = 0; \
|
||||
__gu_err = raw_copy_from_user(&__x, ptr, 8) ? \
|
||||
-EFAULT : 0; \
|
||||
(x) = (typeof(x))(typeof((x) - (x)))__x; \
|
||||
break; \
|
||||
} \
|
||||
default: \
|
||||
/* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\
|
||||
} \
|
||||
x = (__force __typeof__(*(ptr))) __gu_val; \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
|
@ -86,7 +86,6 @@ int main(int argc, char *argv[])
|
||||
/* struct thread_info */
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context));
|
||||
DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count));
|
||||
BLANK();
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/tick.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/uaccess.h> /* for USER_DS macros */
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
void show_regs(struct pt_regs *regs)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifdef CONFIG_32BIT
|
||||
|
||||
#define __UA_LIMIT 0x80000000UL
|
||||
#define TASK_SIZE_MAX KSEG0
|
||||
|
||||
#define __UA_ADDR ".word"
|
||||
#define __UA_LA "la"
|
||||
@ -33,6 +34,7 @@
|
||||
extern u64 __ua_limit;
|
||||
|
||||
#define __UA_LIMIT __ua_limit
|
||||
#define TASK_SIZE_MAX XKSSEG
|
||||
|
||||
#define __UA_ADDR ".dword"
|
||||
#define __UA_LA "dla"
|
||||
@ -42,50 +44,7 @@ extern u64 __ua_limit;
|
||||
|
||||
#endif /* CONFIG_64BIT */
|
||||
|
||||
/*
|
||||
* Is a address valid? This does a straightforward calculation rather
|
||||
* than tests.
|
||||
*
|
||||
* Address valid if:
|
||||
* - "addr" doesn't have any high-bits set
|
||||
* - AND "size" doesn't have any high-bits set
|
||||
* - AND "addr+size" doesn't have any high-bits set
|
||||
* - OR we are in kernel mode.
|
||||
*
|
||||
* __ua_size() is a trick to avoid runtime checking of positive constant
|
||||
* sizes; for those we already know at compile time that the size is ok.
|
||||
*/
|
||||
#define __ua_size(size) \
|
||||
((__builtin_constant_p(size) && (signed long) (size) > 0) ? 0 : (size))
|
||||
|
||||
/*
|
||||
* access_ok: - Checks if a user space pointer is valid
|
||||
* @addr: User space pointer to start of block to check
|
||||
* @size: Size of block to check
|
||||
*
|
||||
* Context: User context only. This function may sleep if pagefaults are
|
||||
* enabled.
|
||||
*
|
||||
* Checks if a pointer to a block of memory in user space is valid.
|
||||
*
|
||||
* Returns true (nonzero) if the memory block may be valid, false (zero)
|
||||
* if it is definitely invalid.
|
||||
*
|
||||
* Note that, depending on architecture, this function probably just
|
||||
* checks that the pointer is in the user space range - after calling
|
||||
* this function, memory access functions may still return -EFAULT.
|
||||
*/
|
||||
|
||||
static inline int __access_ok(const void __user *p, unsigned long size)
|
||||
{
|
||||
unsigned long addr = (unsigned long)p;
|
||||
unsigned long end = addr + size - !!size;
|
||||
|
||||
return (__UA_LIMIT & (addr | end | __ua_size(size))) == 0;
|
||||
}
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
likely(__access_ok((addr), (size)))
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* put_user: - Write a simple value into user space.
|
||||
@ -296,8 +255,6 @@ struct __large_struct { unsigned long buf[100]; };
|
||||
(val) = __gu_tmp.t; \
|
||||
}
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
do { \
|
||||
int __gu_err; \
|
||||
|
@ -1480,6 +1480,23 @@ asmlinkage void do_ade(struct pt_regs *regs)
|
||||
prev_state = exception_enter();
|
||||
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS,
|
||||
1, regs, regs->cp0_badvaddr);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
/*
|
||||
* check, if we are hitting space between CPU implemented maximum
|
||||
* virtual user address and 64bit maximum virtual user address
|
||||
* and do exception handling to get EFAULTs for get_user/put_user
|
||||
*/
|
||||
if ((regs->cp0_badvaddr >= (1UL << cpu_vmbits)) &&
|
||||
(regs->cp0_badvaddr < XKSSEG)) {
|
||||
if (fixup_exception(regs)) {
|
||||
current->thread.cp0_baduaddr = regs->cp0_badvaddr;
|
||||
return;
|
||||
}
|
||||
goto sigbus;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Did we catch a fault trying to load an instruction?
|
||||
*/
|
||||
|
@ -44,7 +44,6 @@ config NDS32
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
help
|
||||
Andes(nds32) Linux support.
|
||||
|
@ -16,8 +16,6 @@ struct task_struct;
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to.
|
||||
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
|
||||
@ -25,12 +23,10 @@ typedef unsigned long mm_segment_t;
|
||||
struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__s32 preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
};
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
#define thread_saved_pc(tsk) ((unsigned long)(tsk->thread.cpu_context.pc))
|
||||
#define thread_saved_fp(tsk) ((unsigned long)(tsk->thread.cpu_context.fp))
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <asm/errno.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
|
||||
|
||||
@ -33,23 +34,6 @@ struct exception_table_entry {
|
||||
|
||||
extern int fixup_exception(struct pt_regs *regs);
|
||||
|
||||
#define KERNEL_DS ((mm_segment_t) { ~0UL })
|
||||
#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
|
||||
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define user_addr_max get_fs
|
||||
|
||||
static inline void set_fs(mm_segment_t fs)
|
||||
{
|
||||
current_thread_info()->addr_limit = fs;
|
||||
}
|
||||
|
||||
#define uaccess_kernel() (get_fs() == KERNEL_DS)
|
||||
|
||||
#define __range_ok(addr, size) (size <= get_fs() && addr <= (get_fs() -size))
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
__range_ok((unsigned long)addr, (unsigned long)size)
|
||||
/*
|
||||
* Single-value transfer routines. They automatically use the right
|
||||
* size if we just have the right pointer type. Note that the functions
|
||||
@ -70,9 +54,7 @@ static inline void set_fs(mm_segment_t fs)
|
||||
* versions are void (ie, don't return a value as such).
|
||||
*/
|
||||
|
||||
#define get_user __get_user \
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
#define get_user(x, ptr) \
|
||||
({ \
|
||||
long __gu_err = 0; \
|
||||
__get_user_check((x), (ptr), __gu_err); \
|
||||
@ -85,6 +67,14 @@ static inline void set_fs(mm_segment_t fs)
|
||||
(void)0; \
|
||||
})
|
||||
|
||||
#define __get_user(x, ptr) \
|
||||
({ \
|
||||
long __gu_err = 0; \
|
||||
const __typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
__get_user_err((x), __p, (__gu_err)); \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
#define __get_user_check(x, ptr, err) \
|
||||
({ \
|
||||
const __typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
@ -165,12 +155,18 @@ do { \
|
||||
: "r"(addr), "i"(-EFAULT) \
|
||||
: "cc")
|
||||
|
||||
#define put_user __put_user \
|
||||
#define put_user(x, ptr) \
|
||||
({ \
|
||||
long __pu_err = 0; \
|
||||
__put_user_check((x), (ptr), __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
long __pu_err = 0; \
|
||||
__put_user_err((x), (ptr), __pu_err); \
|
||||
__typeof__(*(ptr)) __user *__p = (ptr); \
|
||||
__put_user_err((x), __p, __pu_err); \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
|
@ -119,9 +119,8 @@ void show_regs(struct pt_regs *regs)
|
||||
regs->uregs[7], regs->uregs[6], regs->uregs[5], regs->uregs[4]);
|
||||
pr_info("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
|
||||
regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
|
||||
pr_info(" IRQs o%s Segment %s\n",
|
||||
interrupts_enabled(regs) ? "n" : "ff",
|
||||
uaccess_kernel() ? "kernel" : "user");
|
||||
pr_info(" IRQs o%s Segment user\n",
|
||||
interrupts_enabled(regs) ? "n" : "ff");
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(show_regs);
|
||||
|
@ -512,7 +512,6 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long inst;
|
||||
int ret = -EFAULT;
|
||||
mm_segment_t seg;
|
||||
|
||||
inst = get_inst(regs->ipc);
|
||||
|
||||
@ -520,12 +519,10 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
|
||||
"Faulting addr: 0x%08lx, pc: 0x%08lx [inst: 0x%08lx ]\n", addr,
|
||||
regs->ipc, inst);
|
||||
|
||||
seg = force_uaccess_begin();
|
||||
if (inst & NDS32_16BIT_INSTRUCTION)
|
||||
ret = do_16((inst >> 16) & 0xffff, regs);
|
||||
else
|
||||
ret = do_32(inst, regs);
|
||||
force_uaccess_end(seg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ config NIOS2
|
||||
select USB_ARCH_HAS_HCD if USB_SUPPORT
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select MMU_GATHER_NO_RANGE if MMU
|
||||
select SET_FS
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
@ -26,10 +26,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to
|
||||
* - this struct should fit entirely inside of one cache line
|
||||
@ -42,10 +38,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable,<0 => BUG */
|
||||
mm_segment_t addr_limit; /* thread address space:
|
||||
0-0x7FFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct pt_regs *regs;
|
||||
};
|
||||
|
||||
@ -60,7 +52,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -18,31 +18,10 @@
|
||||
#include <asm/page.h>
|
||||
|
||||
#include <asm/extable.h>
|
||||
|
||||
/*
|
||||
* Segment stuff
|
||||
*/
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
#define USER_DS MAKE_MM_SEG(0x80000000UL)
|
||||
#define KERNEL_DS MAKE_MM_SEG(0)
|
||||
|
||||
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define set_fs(seg) (current_thread_info()->addr_limit = (seg))
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
#define __access_ok(addr, len) \
|
||||
(((signed long)(((long)get_fs().seg) & \
|
||||
((long)(addr) | (((long)(addr)) + (len)) | (len)))) == 0)
|
||||
|
||||
#define access_ok(addr, len) \
|
||||
likely(__access_ok((unsigned long)(addr), (unsigned long)(len)))
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||
|
||||
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
|
||||
/*
|
||||
* Zero Userspace
|
||||
*/
|
||||
@ -88,6 +67,7 @@ extern __must_check long strnlen_user(const char __user *s, long n);
|
||||
/* Optimized macros */
|
||||
#define __get_user_asm(val, insn, addr, err) \
|
||||
{ \
|
||||
unsigned long __gu_val; \
|
||||
__asm__ __volatile__( \
|
||||
" movi %0, %3\n" \
|
||||
"1: " insn " %1, 0(%2)\n" \
|
||||
@ -96,14 +76,20 @@ extern __must_check long strnlen_user(const char __user *s, long n);
|
||||
" .section __ex_table,\"a\"\n" \
|
||||
" .word 1b, 2b\n" \
|
||||
" .previous" \
|
||||
: "=&r" (err), "=r" (val) \
|
||||
: "=&r" (err), "=r" (__gu_val) \
|
||||
: "r" (addr), "i" (-EFAULT)); \
|
||||
val = (__force __typeof__(*(addr)))__gu_val; \
|
||||
}
|
||||
|
||||
#define __get_user_unknown(val, size, ptr, err) do { \
|
||||
extern void __get_user_unknown(void);
|
||||
|
||||
#define __get_user_8(val, ptr, err) do { \
|
||||
u64 __val = 0; \
|
||||
err = 0; \
|
||||
if (__copy_from_user(&(val), ptr, size)) { \
|
||||
if (raw_copy_from_user(&(__val), ptr, sizeof(val))) { \
|
||||
err = -EFAULT; \
|
||||
} else { \
|
||||
val = (typeof(val))(typeof((val) - (val)))__val; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -119,8 +105,11 @@ do { \
|
||||
case 4: \
|
||||
__get_user_asm(val, "ldw", ptr, err); \
|
||||
break; \
|
||||
case 8: \
|
||||
__get_user_8(val, ptr, err); \
|
||||
break; \
|
||||
default: \
|
||||
__get_user_unknown(val, size, ptr, err); \
|
||||
__get_user_unknown(); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
@ -129,9 +118,7 @@ do { \
|
||||
({ \
|
||||
long __gu_err = -EFAULT; \
|
||||
const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
|
||||
unsigned long __gu_val = 0; \
|
||||
__get_user_common(__gu_val, sizeof(*(ptr)), __gu_ptr, __gu_err);\
|
||||
(x) = (__force __typeof__(x))__gu_val; \
|
||||
__get_user_common(x, sizeof(*(ptr)), __gu_ptr, __gu_err); \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@ -139,11 +126,9 @@ do { \
|
||||
({ \
|
||||
long __gu_err = -EFAULT; \
|
||||
const __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \
|
||||
unsigned long __gu_val = 0; \
|
||||
if (access_ok( __gu_ptr, sizeof(*__gu_ptr))) \
|
||||
__get_user_common(__gu_val, sizeof(*__gu_ptr), \
|
||||
__get_user_common(x, sizeof(*__gu_ptr), \
|
||||
__gu_ptr, __gu_err); \
|
||||
(x) = (__force __typeof__(x))__gu_val; \
|
||||
__gu_err; \
|
||||
})
|
||||
|
||||
@ -161,34 +146,44 @@ do { \
|
||||
: "r" (val), "r" (ptr), "i" (-EFAULT)); \
|
||||
}
|
||||
|
||||
#define put_user(x, ptr) \
|
||||
#define __put_user_common(__pu_val, __pu_ptr) \
|
||||
({ \
|
||||
long __pu_err = -EFAULT; \
|
||||
__typeof__(*(ptr)) __user *__pu_ptr = (ptr); \
|
||||
__typeof__(*(ptr)) __pu_val = (__typeof(*ptr))(x); \
|
||||
if (access_ok(__pu_ptr, sizeof(*__pu_ptr))) { \
|
||||
switch (sizeof(*__pu_ptr)) { \
|
||||
case 1: \
|
||||
__put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
case 2: \
|
||||
__put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
case 4: \
|
||||
__put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
default: \
|
||||
/* XXX: This looks wrong... */ \
|
||||
__pu_err = 0; \
|
||||
if (copy_to_user(__pu_ptr, &(__pu_val), \
|
||||
sizeof(*__pu_ptr))) \
|
||||
__pu_err = -EFAULT; \
|
||||
break; \
|
||||
} \
|
||||
switch (sizeof(*__pu_ptr)) { \
|
||||
case 1: \
|
||||
__put_user_asm(__pu_val, "stb", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
case 2: \
|
||||
__put_user_asm(__pu_val, "sth", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
case 4: \
|
||||
__put_user_asm(__pu_val, "stw", __pu_ptr, __pu_err); \
|
||||
break; \
|
||||
default: \
|
||||
/* XXX: This looks wrong... */ \
|
||||
__pu_err = 0; \
|
||||
if (__copy_to_user(__pu_ptr, &(__pu_val), \
|
||||
sizeof(*__pu_ptr))) \
|
||||
__pu_err = -EFAULT; \
|
||||
break; \
|
||||
} \
|
||||
__pu_err; \
|
||||
})
|
||||
|
||||
#define __put_user(x, ptr) put_user(x, ptr)
|
||||
#define __put_user(x, ptr) \
|
||||
({ \
|
||||
__auto_type __pu_ptr = (ptr); \
|
||||
typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
|
||||
__put_user_common(__pu_val, __pu_ptr); \
|
||||
})
|
||||
|
||||
#define put_user(x, ptr) \
|
||||
({ \
|
||||
__auto_type __pu_ptr = (ptr); \
|
||||
typeof(*__pu_ptr) __pu_val = (typeof(*__pu_ptr))(x); \
|
||||
access_ok(__pu_ptr, sizeof(*__pu_ptr)) ? \
|
||||
__put_user_common(__pu_val, __pu_ptr) : \
|
||||
-EFAULT; \
|
||||
})
|
||||
|
||||
#endif /* _ASM_NIOS2_UACCESS_H */
|
||||
|
@ -36,10 +36,10 @@ struct rt_sigframe {
|
||||
|
||||
static inline int rt_restore_ucontext(struct pt_regs *regs,
|
||||
struct switch_stack *sw,
|
||||
struct ucontext *uc, int *pr2)
|
||||
struct ucontext __user *uc, int *pr2)
|
||||
{
|
||||
int temp;
|
||||
unsigned long *gregs = uc->uc_mcontext.gregs;
|
||||
unsigned long __user *gregs = uc->uc_mcontext.gregs;
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
@ -102,10 +102,11 @@ asmlinkage int do_rt_sigreturn(struct switch_stack *sw)
|
||||
{
|
||||
struct pt_regs *regs = (struct pt_regs *)(sw + 1);
|
||||
/* Verify, can we follow the stack back */
|
||||
struct rt_sigframe *frame = (struct rt_sigframe *) regs->sp;
|
||||
struct rt_sigframe __user *frame;
|
||||
sigset_t set;
|
||||
int rval;
|
||||
|
||||
frame = (struct rt_sigframe __user *) regs->sp;
|
||||
if (!access_ok(frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
||||
@ -124,10 +125,10 @@ badframe:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
|
||||
static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
|
||||
{
|
||||
struct switch_stack *sw = (struct switch_stack *)regs - 1;
|
||||
unsigned long *gregs = uc->uc_mcontext.gregs;
|
||||
unsigned long __user *gregs = uc->uc_mcontext.gregs;
|
||||
int err = 0;
|
||||
|
||||
err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
|
||||
@ -162,8 +163,9 @@ static inline int rt_setup_ucontext(struct ucontext *uc, struct pt_regs *regs)
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long usp;
|
||||
|
||||
@ -174,13 +176,13 @@ static inline void *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
|
||||
usp = sigsp(usp, ksig);
|
||||
|
||||
/* Verify, is it 32 or 64 bit aligned */
|
||||
return (void *)((usp - frame_size) & -8UL);
|
||||
return (void __user *)((usp - frame_size) & -8UL);
|
||||
}
|
||||
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
@ -36,7 +36,6 @@ config OPENRISC
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select GENERIC_IRQ_MULTI_HANDLER
|
||||
select MMU_GATHER_NO_RANGE if MMU
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
|
@ -40,18 +40,12 @@
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space:
|
||||
0-0x7FFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
__u8 supervisor_stack[0];
|
||||
|
||||
/* saved context data */
|
||||
@ -71,7 +65,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.ksp = 0, \
|
||||
}
|
||||
|
||||
|
@ -22,44 +22,7 @@
|
||||
#include <linux/string.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
/*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
* performed or not. If get_fs() == USER_DS, checking is performed, with
|
||||
* get_fs() == KERNEL_DS, checking is bypassed.
|
||||
*
|
||||
* For historical reasons, these macros are grossly misnamed.
|
||||
*/
|
||||
|
||||
/* addr_limit is the maximum accessible address for the task. we misuse
|
||||
* the KERNEL_DS and USER_DS values to both assign and compare the
|
||||
* addr_limit values through the equally misnamed get/set_fs macros.
|
||||
* (see above)
|
||||
*/
|
||||
|
||||
#define KERNEL_DS (~0UL)
|
||||
|
||||
#define USER_DS (TASK_SIZE)
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define set_fs(x) (current_thread_info()->addr_limit = (x))
|
||||
|
||||
#define uaccess_kernel() (get_fs() == KERNEL_DS)
|
||||
|
||||
/* Ensure that the range from addr to addr+size is all within the process'
|
||||
* address space
|
||||
*/
|
||||
static inline int __range_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
const mm_segment_t fs = get_fs();
|
||||
|
||||
return size <= fs && addr <= (fs - size);
|
||||
}
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
({ \
|
||||
__chk_user_ptr(addr); \
|
||||
__range_ok((unsigned long)(addr), (size)); \
|
||||
})
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* These are the main single-value transfer routines. They automatically
|
||||
@ -268,9 +231,6 @@ clear_user(void __user *addr, unsigned long size)
|
||||
return size;
|
||||
}
|
||||
|
||||
#define user_addr_max() \
|
||||
(uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
|
||||
extern long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
|
||||
extern __must_check long strnlen_user(const char __user *str, long n);
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config PARISC
|
||||
def_bool y
|
||||
select ALTERNATE_USER_ADDRESS_SPACE
|
||||
select ARCH_32BIT_OFF_T if !64BIT
|
||||
select ARCH_MIGHT_HAVE_PC_PARPORT
|
||||
select HAVE_FUNCTION_TRACER
|
||||
|
@ -96,12 +96,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
||||
u32 val;
|
||||
unsigned long flags;
|
||||
|
||||
/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
|
||||
* our gateway page, and causes no end of trouble...
|
||||
*/
|
||||
if (uaccess_kernel() && !uaddr)
|
||||
return -EFAULT;
|
||||
|
||||
if (!access_ok(uaddr, sizeof(u32)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -11,15 +11,9 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
/*
|
||||
* Note that since kernel addresses are in a separate address space on
|
||||
* parisc, we don't need to do anything for access_ok().
|
||||
* We just let the page fault handler do the right thing. This also means
|
||||
* that put_user is the same as __put_user, etc.
|
||||
*/
|
||||
|
||||
#define access_ok(uaddr, size) \
|
||||
( (uaddr) == (uaddr) )
|
||||
#define TASK_SIZE_MAX DEFAULT_TASK_SIZE
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#define put_user __put_user
|
||||
#define get_user __get_user
|
||||
@ -95,7 +89,6 @@ struct exception_table_entry {
|
||||
(val) = (__force __typeof__(*(ptr))) __gu_val; \
|
||||
}
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
{ \
|
||||
type __z; \
|
||||
|
@ -251,7 +251,7 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
|
||||
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
|
||||
|
||||
start = (unsigned long) frame;
|
||||
if (start >= user_addr_max() - sigframe_size)
|
||||
if (start >= TASK_SIZE_MAX - sigframe_size)
|
||||
return -EFAULT;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
@ -518,7 +518,7 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
long err = 0;
|
||||
|
||||
/* check that we don't exceed the stack */
|
||||
if (A(&usp[0]) >= user_addr_max() - 5 * sizeof(int))
|
||||
if (A(&usp[0]) >= TASK_SIZE_MAX - 5 * sizeof(int))
|
||||
return;
|
||||
|
||||
/* Setup a trampoline to restart the syscall
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define get_user_space() (uaccess_kernel() ? 0 : mfsp(3))
|
||||
#define get_user_space() (mfsp(3))
|
||||
#define get_kernel_space() (0)
|
||||
|
||||
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
|
||||
|
@ -11,18 +11,9 @@
|
||||
#ifdef __powerpc64__
|
||||
/* We use TASK_SIZE_USER64 as TASK_SIZE is not constant */
|
||||
#define TASK_SIZE_MAX TASK_SIZE_USER64
|
||||
#else
|
||||
#define TASK_SIZE_MAX TASK_SIZE
|
||||
#endif
|
||||
|
||||
static inline bool __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
return addr < TASK_SIZE_MAX && size <= TASK_SIZE_MAX - addr;
|
||||
}
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
(__chk_user_ptr(addr), \
|
||||
__access_ok((unsigned long)(addr), (size)))
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* These are the main single-value transfer routines. They automatically
|
||||
@ -467,8 +458,6 @@ do { \
|
||||
unsafe_put_user(*(u8*)(_src + _i), (u8 __user *)(_dst + _i), e); \
|
||||
} while (0)
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
__get_user_size_goto(*((type *)(dst)), \
|
||||
(__force type __user *)(src), sizeof(type), err_label)
|
||||
|
@ -112,9 +112,9 @@ static nokprobe_inline long address_ok(struct pt_regs *regs,
|
||||
{
|
||||
if (!user_mode(regs))
|
||||
return 1;
|
||||
if (__access_ok(ea, nb))
|
||||
if (access_ok((void __user *)ea, nb))
|
||||
return 1;
|
||||
if (__access_ok(ea, 1))
|
||||
if (access_ok((void __user *)ea, 1))
|
||||
/* Access overlaps the end of the user region */
|
||||
regs->dar = TASK_SIZE_MAX - 1;
|
||||
else
|
||||
|
@ -21,42 +21,13 @@
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/extable.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#define __enable_user_access() \
|
||||
__asm__ __volatile__ ("csrs sstatus, %0" : : "r" (SR_SUM) : "memory")
|
||||
#define __disable_user_access() \
|
||||
__asm__ __volatile__ ("csrc sstatus, %0" : : "r" (SR_SUM) : "memory")
|
||||
|
||||
/**
|
||||
* access_ok: - Checks if a user space pointer is valid
|
||||
* @addr: User space pointer to start of block to check
|
||||
* @size: Size of block to check
|
||||
*
|
||||
* Context: User context only. This function may sleep.
|
||||
*
|
||||
* Checks if a pointer to a block of memory in user space is valid.
|
||||
*
|
||||
* Returns true (nonzero) if the memory block may be valid, false (zero)
|
||||
* if it is definitely invalid.
|
||||
*
|
||||
* Note that, depending on architecture, this function probably just
|
||||
* checks that the pointer is in the user space range - after calling
|
||||
* this function, memory access functions may still return -EFAULT.
|
||||
*/
|
||||
#define access_ok(addr, size) ({ \
|
||||
__chk_user_ptr(addr); \
|
||||
likely(__access_ok((unsigned long __force)(addr), (size))); \
|
||||
})
|
||||
|
||||
/*
|
||||
* Ensure that the range [addr, addr+size) is within the process's
|
||||
* address space
|
||||
*/
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
return size <= TASK_SIZE && addr <= TASK_SIZE - size;
|
||||
}
|
||||
|
||||
/*
|
||||
* The exception table consists of pairs of addresses: the first is the
|
||||
* address of an instruction that is allowed to fault, and the second is
|
||||
@ -346,8 +317,6 @@ unsigned long __must_check clear_user(void __user *to, unsigned long n)
|
||||
__clear_user(to, n) : n;
|
||||
}
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
do { \
|
||||
long __kr_err; \
|
||||
|
@ -15,8 +15,8 @@ static unsigned long user_backtrace(struct perf_callchain_entry_ctx *entry,
|
||||
{
|
||||
struct stackframe buftail;
|
||||
unsigned long ra = 0;
|
||||
unsigned long *user_frame_tail =
|
||||
(unsigned long *)(fp - sizeof(struct stackframe));
|
||||
unsigned long __user *user_frame_tail =
|
||||
(unsigned long __user *)(fp - sizeof(struct stackframe));
|
||||
|
||||
/* Check accessibility of one struct frame_tail beyond */
|
||||
if (!access_ok(user_frame_tail, sizeof(buftail)))
|
||||
|
@ -55,6 +55,7 @@ config S390
|
||||
# Note: keep this list sorted alphabetically
|
||||
#
|
||||
imply IMA_SECURE_AND_OR_TRUSTED_BOOT
|
||||
select ALTERNATE_USER_ADDRESS_SPACE
|
||||
select ARCH_32BIT_USTAT_F_TINODE
|
||||
select ARCH_BINFMT_ELF_STATE
|
||||
select ARCH_ENABLE_MEMORY_HOTPLUG if SPARSEMEM
|
||||
|
@ -17,22 +17,10 @@
|
||||
#include <asm/ctl_reg.h>
|
||||
#include <asm/extable.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
void debug_user_asce(int exit);
|
||||
|
||||
static inline int __range_ok(unsigned long addr, unsigned long size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define __access_ok(addr, size) \
|
||||
({ \
|
||||
__chk_user_ptr(addr); \
|
||||
__range_ok((unsigned long)(addr), (size)); \
|
||||
})
|
||||
|
||||
#define access_ok(addr, size) __access_ok(addr, size)
|
||||
|
||||
unsigned long __must_check
|
||||
raw_copy_from_user(void *to, const void __user *from, unsigned long n);
|
||||
|
||||
@ -282,8 +270,6 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
|
||||
int copy_to_user_real(void __user *dest, void *src, unsigned long count);
|
||||
void *s390_kernel_write(void *dst, const void *src, size_t size);
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
int __noreturn __put_kernel_bad(void);
|
||||
|
||||
#define __put_kernel_asm(val, to, insn) \
|
||||
|
@ -65,7 +65,6 @@ config SUPERH
|
||||
select PERF_EVENTS
|
||||
select PERF_USE_VMALLOC
|
||||
select RTC_LIB
|
||||
select SET_FS
|
||||
select SPARSE_IRQ
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
help
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define __ASM_SH_PROCESSOR_H
|
||||
|
||||
#include <asm/cpu-features.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/cache.h>
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
@ -1,33 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef __ASM_SH_SEGMENT_H
|
||||
#define __ASM_SH_SEGMENT_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
|
||||
/*
|
||||
* The fs value determines whether argument validity checking should be
|
||||
* performed or not. If get_fs() == USER_DS, checking is performed, with
|
||||
* get_fs() == KERNEL_DS, checking is bypassed.
|
||||
*
|
||||
* For historical reasons, these macros are grossly misnamed.
|
||||
*/
|
||||
#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL)
|
||||
#ifdef CONFIG_MMU
|
||||
#define USER_DS MAKE_MM_SEG(PAGE_OFFSET)
|
||||
#else
|
||||
#define USER_DS KERNEL_DS
|
||||
#endif
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
#define get_fs() (current_thread_info()->addr_limit)
|
||||
#define set_fs(x) (current_thread_info()->addr_limit = (x))
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_SH_SEGMENT_H */
|
@ -30,7 +30,6 @@ struct thread_info {
|
||||
__u32 status; /* thread synchronous flags */
|
||||
__u32 cpu;
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
unsigned long previous_sp; /* sp of previous stack in case
|
||||
of nested IRQ stacks */
|
||||
__u8 supervisor_stack[0];
|
||||
@ -58,7 +57,6 @@ struct thread_info {
|
||||
.status = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the current stack pointer from C */
|
||||
|
@ -2,30 +2,8 @@
|
||||
#ifndef __ASM_SH_UACCESS_H
|
||||
#define __ASM_SH_UACCESS_H
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
#define __addr_ok(addr) \
|
||||
((unsigned long __force)(addr) < current_thread_info()->addr_limit.seg)
|
||||
|
||||
/*
|
||||
* __access_ok: Check if address with size is OK or not.
|
||||
*
|
||||
* Uhhuh, this needs 33-bit arithmetic. We have a carry..
|
||||
*
|
||||
* sum := addr + size; carry? --> flag = true;
|
||||
* if (sum >= addr_limit) flag = true;
|
||||
*/
|
||||
#define __access_ok(addr, size) ({ \
|
||||
unsigned long __ao_a = (addr), __ao_b = (size); \
|
||||
unsigned long __ao_end = __ao_a + __ao_b - !!__ao_b; \
|
||||
__ao_end >= __ao_a && __addr_ok(__ao_end); })
|
||||
|
||||
#define access_ok(addr, size) \
|
||||
(__chk_user_ptr(addr), \
|
||||
__access_ok((unsigned long __force)(addr), (size)))
|
||||
|
||||
#define user_addr_max() (current_thread_info()->addr_limit.seg)
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* Uh, these should become the main single-value transfer routines ...
|
||||
|
@ -270,7 +270,6 @@ static struct mem_access trapped_io_access = {
|
||||
|
||||
int handle_trapped_io(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
mm_segment_t oldfs;
|
||||
insn_size_t instruction;
|
||||
int tmp;
|
||||
|
||||
@ -281,16 +280,12 @@ int handle_trapped_io(struct pt_regs *regs, unsigned long address)
|
||||
|
||||
WARN_ON(user_mode(regs));
|
||||
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
if (copy_from_user(&instruction, (void *)(regs->pc),
|
||||
sizeof(instruction))) {
|
||||
set_fs(oldfs);
|
||||
if (copy_from_kernel_nofault(&instruction, (void *)(regs->pc),
|
||||
sizeof(instruction))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
tmp = handle_unaligned_access(instruction, regs,
|
||||
&trapped_io_access, 1, address);
|
||||
set_fs(oldfs);
|
||||
return tmp == 0;
|
||||
}
|
||||
|
@ -123,7 +123,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
|
||||
#if defined(CONFIG_SH_FPU)
|
||||
childregs->sr |= SR_FD;
|
||||
#endif
|
||||
ti->addr_limit = KERNEL_DS;
|
||||
ti->status &= ~TS_USEDFPU;
|
||||
p->thread.fpu_counter = 0;
|
||||
return 0;
|
||||
@ -132,7 +131,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
|
||||
|
||||
if (usp)
|
||||
childregs->regs[15] = usp;
|
||||
ti->addr_limit = USER_DS;
|
||||
|
||||
if (clone_flags & CLONE_SETTLS)
|
||||
childregs->gbr = tls;
|
||||
|
@ -75,6 +75,23 @@ static struct mem_access user_mem_access = {
|
||||
copy_to_user,
|
||||
};
|
||||
|
||||
static unsigned long copy_from_kernel_wrapper(void *dst, const void __user *src,
|
||||
unsigned long cnt)
|
||||
{
|
||||
return copy_from_kernel_nofault(dst, (const void __force *)src, cnt);
|
||||
}
|
||||
|
||||
static unsigned long copy_to_kernel_wrapper(void __user *dst, const void *src,
|
||||
unsigned long cnt)
|
||||
{
|
||||
return copy_to_kernel_nofault((void __force *)dst, src, cnt);
|
||||
}
|
||||
|
||||
static struct mem_access kernel_mem_access = {
|
||||
copy_from_kernel_wrapper,
|
||||
copy_to_kernel_wrapper,
|
||||
};
|
||||
|
||||
/*
|
||||
* handle an instruction that does an unaligned memory access by emulating the
|
||||
* desired behaviour
|
||||
@ -473,7 +490,6 @@ asmlinkage void do_address_error(struct pt_regs *regs,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long error_code = 0;
|
||||
mm_segment_t oldfs;
|
||||
insn_size_t instruction;
|
||||
int tmp;
|
||||
|
||||
@ -489,13 +505,10 @@ asmlinkage void do_address_error(struct pt_regs *regs,
|
||||
local_irq_enable();
|
||||
inc_unaligned_user_access();
|
||||
|
||||
oldfs = force_uaccess_begin();
|
||||
if (copy_from_user(&instruction, (insn_size_t __user *)(regs->pc & ~1),
|
||||
sizeof(instruction))) {
|
||||
force_uaccess_end(oldfs);
|
||||
goto uspace_segv;
|
||||
}
|
||||
force_uaccess_end(oldfs);
|
||||
|
||||
/* shout about userspace fixups */
|
||||
unaligned_fixups_notify(current, instruction, regs);
|
||||
@ -518,11 +531,9 @@ fixup:
|
||||
goto uspace_segv;
|
||||
}
|
||||
|
||||
oldfs = force_uaccess_begin();
|
||||
tmp = handle_unaligned_access(instruction, regs,
|
||||
&user_mem_access, 0,
|
||||
address);
|
||||
force_uaccess_end(oldfs);
|
||||
|
||||
if (tmp == 0)
|
||||
return; /* sorted */
|
||||
@ -538,21 +549,18 @@ uspace_segv:
|
||||
if (regs->pc & 1)
|
||||
die("unaligned program counter", regs, error_code);
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
if (copy_from_user(&instruction, (void __user *)(regs->pc),
|
||||
if (copy_from_kernel_nofault(&instruction, (void *)(regs->pc),
|
||||
sizeof(instruction))) {
|
||||
/* Argh. Fault on the instruction itself.
|
||||
This should never happen non-SMP
|
||||
*/
|
||||
set_fs(oldfs);
|
||||
die("insn faulting in do_address_error", regs, 0);
|
||||
}
|
||||
|
||||
unaligned_fixups_notify(current, instruction, regs);
|
||||
|
||||
handle_unaligned_access(instruction, regs, &user_mem_access,
|
||||
handle_unaligned_access(instruction, regs, &kernel_mem_access,
|
||||
0, address);
|
||||
set_fs(oldfs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,6 @@ config SPARC
|
||||
select LOCKDEP_SMALL if LOCKDEP
|
||||
select NEED_DMA_MAP_STATE
|
||||
select NEED_SG_DMA_LENGTH
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config SPARC32
|
||||
@ -62,6 +61,7 @@ config SPARC32
|
||||
|
||||
config SPARC64
|
||||
def_bool 64BIT
|
||||
select ALTERNATE_USER_ADDRESS_SPACE
|
||||
select HAVE_FUNCTION_TRACER
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_KRETPROBES
|
||||
|
@ -32,10 +32,6 @@ struct fpq {
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/* The Sparc processor specific thread struct. */
|
||||
struct thread_struct {
|
||||
struct pt_regs *kregs;
|
||||
@ -50,11 +46,9 @@ struct thread_struct {
|
||||
unsigned long fsr;
|
||||
unsigned long fpqdepth;
|
||||
struct fpq fpqueue[16];
|
||||
mm_segment_t current_ds;
|
||||
};
|
||||
|
||||
#define INIT_THREAD { \
|
||||
.current_ds = KERNEL_DS, \
|
||||
.kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
|
||||
}
|
||||
|
||||
|
@ -47,10 +47,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned char seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/* The Sparc processor specific thread struct. */
|
||||
/* XXX This should die, everything can go into thread_info now. */
|
||||
struct thread_struct {
|
||||
|
@ -20,10 +20,8 @@ do { \
|
||||
*/
|
||||
#define switch_to(prev, next, last) \
|
||||
do { save_and_clear_fpu(); \
|
||||
/* If you are tempted to conditionalize the following */ \
|
||||
/* so that ASI is only written if it changes, think again. */ \
|
||||
__asm__ __volatile__("wr %%g0, %0, %%asi" \
|
||||
: : "r" (task_thread_info(next)->current_ds));\
|
||||
: : "r" (ASI_AIUS)); \
|
||||
trap_block[current_thread_info()->cpu].thread = \
|
||||
task_thread_info(next); \
|
||||
__asm__ __volatile__( \
|
||||
|
@ -46,7 +46,7 @@ struct thread_info {
|
||||
struct pt_regs *kregs;
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
__u8 new_child;
|
||||
__u8 current_ds;
|
||||
__u8 __pad;
|
||||
__u16 cpu;
|
||||
|
||||
unsigned long *utraps;
|
||||
@ -81,7 +81,6 @@ struct thread_info {
|
||||
#define TI_KREGS 0x00000028
|
||||
#define TI_PRE_COUNT 0x00000030
|
||||
#define TI_NEW_CHILD 0x00000034
|
||||
#define TI_CURRENT_DS 0x00000035
|
||||
#define TI_CPU 0x00000036
|
||||
#define TI_UTRAPS 0x00000038
|
||||
#define TI_REG_WINDOW 0x00000040
|
||||
@ -116,7 +115,6 @@ struct thread_info {
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.current_ds = ASI_P, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
|
||||
}
|
||||
|
@ -10,9 +10,6 @@
|
||||
#include <asm/uaccess_32.h>
|
||||
#endif
|
||||
|
||||
#define user_addr_max() \
|
||||
(uaccess_kernel() ? ~0UL : TASK_SIZE)
|
||||
|
||||
long strncpy_from_user(char *dest, const char __user *src, long count);
|
||||
|
||||
#endif
|
||||
|
@ -12,30 +12,7 @@
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
|
||||
/* Sparc is not segmented, however we need to be able to fool access_ok()
|
||||
* when doing system calls from kernel mode legitimately.
|
||||
*
|
||||
* "For historical reasons, these macros are grossly misnamed." -Linus
|
||||
*/
|
||||
|
||||
#define KERNEL_DS ((mm_segment_t) { 0 })
|
||||
#define USER_DS ((mm_segment_t) { -1 })
|
||||
|
||||
#define get_fs() (current->thread.current_ds)
|
||||
#define set_fs(val) ((current->thread.current_ds) = (val))
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
/* We have there a nice not-mapped page at PAGE_OFFSET - PAGE_SIZE, so that this test
|
||||
* can be fairly lightweight.
|
||||
* No one can read/write anything from userland in the kernel space by setting
|
||||
* large size and address near to PAGE_OFFSET - a fault will break his intentions.
|
||||
*/
|
||||
#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
|
||||
#define __kernel_ok (uaccess_kernel())
|
||||
#define __access_ok(addr, size) (__user_ok((addr) & get_fs().seg, (size)))
|
||||
#define access_ok(addr, size) __access_ok((unsigned long)(addr), size)
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/* Uh, these should become the main single-value transfer routines..
|
||||
* They automatically use the right size if we just have the right
|
||||
@ -47,13 +24,13 @@
|
||||
* and hide all the ugliness from the user.
|
||||
*/
|
||||
#define put_user(x, ptr) ({ \
|
||||
unsigned long __pu_addr = (unsigned long)(ptr); \
|
||||
void __user *__pu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__put_user_check((__typeof__(*(ptr)))(x), __pu_addr, sizeof(*(ptr))); \
|
||||
})
|
||||
|
||||
#define get_user(x, ptr) ({ \
|
||||
unsigned long __gu_addr = (unsigned long)(ptr); \
|
||||
const void __user *__gu_addr = (ptr); \
|
||||
__chk_user_ptr(ptr); \
|
||||
__get_user_check((x), __gu_addr, sizeof(*(ptr)), __typeof__(*(ptr))); \
|
||||
})
|
||||
@ -232,7 +209,7 @@ static inline unsigned long __clear_user(void __user *addr, unsigned long size)
|
||||
|
||||
static inline unsigned long clear_user(void __user *addr, unsigned long n)
|
||||
{
|
||||
if (n && __access_ok((unsigned long) addr, n))
|
||||
if (n && __access_ok(addr, n))
|
||||
return __clear_user(addr, n);
|
||||
else
|
||||
return n;
|
||||
|
@ -12,33 +12,15 @@
|
||||
#include <asm/spitfire.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
* Sparc64 is segmented, though more like the M68K than the I386.
|
||||
* We use the secondary ASI to address user memory, which references a
|
||||
* completely different VM map, thus there is zero chance of the user
|
||||
* doing something queer and tricking us into poking kernel memory.
|
||||
*
|
||||
* What is left here is basically what is needed for the other parts of
|
||||
* the kernel that expect to be able to manipulate, erum, "segments".
|
||||
* Or perhaps more properly, permissions.
|
||||
*
|
||||
* "For historical reasons, these macros are grossly misnamed." -Linus
|
||||
*/
|
||||
|
||||
#define KERNEL_DS ((mm_segment_t) { ASI_P })
|
||||
#define USER_DS ((mm_segment_t) { ASI_AIUS }) /* har har har */
|
||||
|
||||
#define get_fs() ((mm_segment_t){(current_thread_info()->current_ds)})
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
#define set_fs(val) \
|
||||
do { \
|
||||
current_thread_info()->current_ds = (val).seg; \
|
||||
__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg)); \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Test whether a block of memory is a valid user space address.
|
||||
* Returns 0 if the range is valid, nonzero otherwise.
|
||||
@ -61,16 +43,6 @@ static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, un
|
||||
__chk_range_not_ok((unsigned long __force)(addr), size, limit); \
|
||||
})
|
||||
|
||||
static inline int __access_ok(const void __user * addr, unsigned long size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int access_ok(const void __user * addr, unsigned long size)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void __retl_efault(void);
|
||||
|
||||
/* Uh, these should become the main single-value transfer routines..
|
||||
@ -100,6 +72,42 @@ void __retl_efault(void);
|
||||
struct __large_struct { unsigned long buf[100]; };
|
||||
#define __m(x) ((struct __large_struct *)(x))
|
||||
|
||||
#define __put_kernel_nofault(dst, src, type, label) \
|
||||
do { \
|
||||
type *addr = (type __force *)(dst); \
|
||||
type data = *(type *)src; \
|
||||
register int __pu_ret; \
|
||||
switch (sizeof(type)) { \
|
||||
case 1: __put_kernel_asm(data, b, addr, __pu_ret); break; \
|
||||
case 2: __put_kernel_asm(data, h, addr, __pu_ret); break; \
|
||||
case 4: __put_kernel_asm(data, w, addr, __pu_ret); break; \
|
||||
case 8: __put_kernel_asm(data, x, addr, __pu_ret); break; \
|
||||
default: __pu_ret = __put_user_bad(); break; \
|
||||
} \
|
||||
if (__pu_ret) \
|
||||
goto label; \
|
||||
} while (0)
|
||||
|
||||
#define __put_kernel_asm(x, size, addr, ret) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Put kernel asm, inline. */\n" \
|
||||
"1:\t" "st"#size " %1, [%2]\n\t" \
|
||||
"clr %0\n" \
|
||||
"2:\n\n\t" \
|
||||
".section .fixup,#alloc,#execinstr\n\t" \
|
||||
".align 4\n" \
|
||||
"3:\n\t" \
|
||||
"sethi %%hi(2b), %0\n\t" \
|
||||
"jmpl %0 + %%lo(2b), %%g0\n\t" \
|
||||
" mov %3, %0\n\n\t" \
|
||||
".previous\n\t" \
|
||||
".section __ex_table,\"a\"\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, 3b\n\t" \
|
||||
".previous\n\n\t" \
|
||||
: "=r" (ret) : "r" (x), "r" (__m(addr)), \
|
||||
"i" (-EFAULT))
|
||||
|
||||
#define __put_user_nocheck(data, addr, size) ({ \
|
||||
register int __pu_ret; \
|
||||
switch (size) { \
|
||||
@ -134,6 +142,46 @@ __asm__ __volatile__( \
|
||||
|
||||
int __put_user_bad(void);
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, label) \
|
||||
do { \
|
||||
type *addr = (type __force *)(src); \
|
||||
register int __gu_ret; \
|
||||
register unsigned long __gu_val; \
|
||||
switch (sizeof(type)) { \
|
||||
case 1: __get_kernel_asm(__gu_val, ub, addr, __gu_ret); break; \
|
||||
case 2: __get_kernel_asm(__gu_val, uh, addr, __gu_ret); break; \
|
||||
case 4: __get_kernel_asm(__gu_val, uw, addr, __gu_ret); break; \
|
||||
case 8: __get_kernel_asm(__gu_val, x, addr, __gu_ret); break; \
|
||||
default: \
|
||||
__gu_val = 0; \
|
||||
__gu_ret = __get_user_bad(); \
|
||||
break; \
|
||||
} \
|
||||
if (__gu_ret) \
|
||||
goto label; \
|
||||
*(type *)dst = (__force type) __gu_val; \
|
||||
} while (0)
|
||||
#define __get_kernel_asm(x, size, addr, ret) \
|
||||
__asm__ __volatile__( \
|
||||
"/* Get kernel asm, inline. */\n" \
|
||||
"1:\t" "ld"#size " [%2], %1\n\t" \
|
||||
"clr %0\n" \
|
||||
"2:\n\n\t" \
|
||||
".section .fixup,#alloc,#execinstr\n\t" \
|
||||
".align 4\n" \
|
||||
"3:\n\t" \
|
||||
"sethi %%hi(2b), %0\n\t" \
|
||||
"clr %1\n\t" \
|
||||
"jmpl %0 + %%lo(2b), %%g0\n\t" \
|
||||
" mov %3, %0\n\n\t" \
|
||||
".previous\n\t" \
|
||||
".section __ex_table,\"a\"\n\t" \
|
||||
".align 4\n\t" \
|
||||
".word 1b, 3b\n\n\t" \
|
||||
".previous\n\t" \
|
||||
: "=r" (ret), "=r" (x) : "r" (__m(addr)), \
|
||||
"i" (-EFAULT))
|
||||
|
||||
#define __get_user_nocheck(data, addr, size, type) ({ \
|
||||
register int __gu_ret; \
|
||||
register unsigned long __gu_val; \
|
||||
|
@ -300,7 +300,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
|
||||
extern int nwindows;
|
||||
unsigned long psr;
|
||||
memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
|
||||
p->thread.current_ds = KERNEL_DS;
|
||||
ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
|
||||
childregs->u_regs[UREG_G1] = sp; /* function */
|
||||
childregs->u_regs[UREG_G2] = arg;
|
||||
@ -311,7 +310,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
|
||||
}
|
||||
memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
|
||||
childregs->u_regs[UREG_FP] = sp;
|
||||
p->thread.current_ds = USER_DS;
|
||||
ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
|
||||
ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
|
||||
ti->kwim = current->thread.fork_kwim;
|
||||
|
@ -106,18 +106,13 @@ static void show_regwindow32(struct pt_regs *regs)
|
||||
{
|
||||
struct reg_window32 __user *rw;
|
||||
struct reg_window32 r_w;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
__asm__ __volatile__ ("flushw");
|
||||
rw = compat_ptr((unsigned int)regs->u_regs[14]);
|
||||
old_fs = get_fs();
|
||||
set_fs (USER_DS);
|
||||
if (copy_from_user (&r_w, rw, sizeof(r_w))) {
|
||||
set_fs (old_fs);
|
||||
return;
|
||||
}
|
||||
|
||||
set_fs (old_fs);
|
||||
printk("l0: %08x l1: %08x l2: %08x l3: %08x "
|
||||
"l4: %08x l5: %08x l6: %08x l7: %08x\n",
|
||||
r_w.locals[0], r_w.locals[1], r_w.locals[2], r_w.locals[3],
|
||||
@ -136,7 +131,6 @@ static void show_regwindow(struct pt_regs *regs)
|
||||
struct reg_window __user *rw;
|
||||
struct reg_window *rwk;
|
||||
struct reg_window r_w;
|
||||
mm_segment_t old_fs;
|
||||
|
||||
if ((regs->tstate & TSTATE_PRIV) || !(test_thread_flag(TIF_32BIT))) {
|
||||
__asm__ __volatile__ ("flushw");
|
||||
@ -145,14 +139,10 @@ static void show_regwindow(struct pt_regs *regs)
|
||||
rwk = (struct reg_window *)
|
||||
(regs->u_regs[14] + STACK_BIAS);
|
||||
if (!(regs->tstate & TSTATE_PRIV)) {
|
||||
old_fs = get_fs();
|
||||
set_fs (USER_DS);
|
||||
if (copy_from_user (&r_w, rw, sizeof(r_w))) {
|
||||
set_fs (old_fs);
|
||||
return;
|
||||
}
|
||||
rwk = &r_w;
|
||||
set_fs (old_fs);
|
||||
}
|
||||
} else {
|
||||
show_regwindow32(regs);
|
||||
@ -598,7 +588,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
|
||||
memset(child_trap_frame, 0, child_stack_sz);
|
||||
__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
|
||||
(current_pt_regs()->tstate + 1) & TSTATE_CWP;
|
||||
t->current_ds = ASI_P;
|
||||
t->kregs->u_regs[UREG_G1] = sp; /* function */
|
||||
t->kregs->u_regs[UREG_G2] = arg;
|
||||
return 0;
|
||||
@ -613,7 +602,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
|
||||
t->kregs->u_regs[UREG_FP] = sp;
|
||||
__thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] =
|
||||
(regs->tstate + 1) & TSTATE_CWP;
|
||||
t->current_ds = ASI_AIUS;
|
||||
if (sp != regs->u_regs[UREG_FP]) {
|
||||
unsigned long csp;
|
||||
|
||||
|
@ -65,7 +65,7 @@ struct rt_signal_frame {
|
||||
*/
|
||||
static inline bool invalid_frame_pointer(void __user *fp, int fplen)
|
||||
{
|
||||
if ((((unsigned long) fp) & 15) || !__access_ok((unsigned long)fp, fplen))
|
||||
if ((((unsigned long) fp) & 15) || !access_ok(fp, fplen))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -2857,8 +2857,6 @@ void __init trap_init(void)
|
||||
TI_PRE_COUNT != offsetof(struct thread_info,
|
||||
preempt_count) ||
|
||||
TI_NEW_CHILD != offsetof(struct thread_info, new_child) ||
|
||||
TI_CURRENT_DS != offsetof(struct thread_info,
|
||||
current_ds) ||
|
||||
TI_KUNA_REGS != offsetof(struct thread_info,
|
||||
kern_una_regs) ||
|
||||
TI_KUNA_INSN != offsetof(struct thread_info,
|
||||
|
@ -10,8 +10,7 @@
|
||||
#include <asm/thread_info.h>
|
||||
#define GLOBAL_SPARE %g7
|
||||
#define RESTORE_ASI(TMP) \
|
||||
ldub [%g6 + TI_CURRENT_DS], TMP; \
|
||||
wr TMP, 0x0, %asi;
|
||||
wr %g0, ASI_AIUS, %asi
|
||||
#else
|
||||
#define GLOBAL_SPARE %g5
|
||||
#define RESTORE_ASI(TMP) \
|
||||
|
@ -709,9 +709,10 @@ static void __init inherit_prom_mappings(void)
|
||||
|
||||
void prom_world(int enter)
|
||||
{
|
||||
if (!enter)
|
||||
set_fs(get_fs());
|
||||
|
||||
/*
|
||||
* No need to change the address space any more, just flush
|
||||
* the register windows
|
||||
*/
|
||||
__asm__ __volatile__("flushw");
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
extern unsigned long raw_copy_from_user(void *to, const void __user *from, unsigned long n);
|
||||
extern unsigned long raw_copy_to_user(void __user *to, const void *from, unsigned long n);
|
||||
extern unsigned long __clear_user(void __user *mem, unsigned long len);
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size);
|
||||
static inline int __access_ok(const void __user *ptr, unsigned long size);
|
||||
|
||||
/* Teach asm-generic/uaccess.h that we have C functions for these. */
|
||||
#define __access_ok __access_ok
|
||||
@ -36,16 +36,15 @@ static inline int __access_ok(unsigned long addr, unsigned long size);
|
||||
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
static inline int __access_ok(unsigned long addr, unsigned long size)
|
||||
static inline int __access_ok(const void __user *ptr, unsigned long size)
|
||||
{
|
||||
unsigned long addr = (unsigned long)ptr;
|
||||
return __addr_range_nowrap(addr, size) &&
|
||||
(__under_task_size(addr, size) ||
|
||||
__access_ok_vsyscall(addr, size));
|
||||
}
|
||||
|
||||
/* no pagefaults for kernel addresses in um */
|
||||
#define HAVE_GET_KERNEL_NOFAULT 1
|
||||
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
do { \
|
||||
*((type *)dst) = get_unaligned((type *)(src)); \
|
||||
|
@ -2794,7 +2794,7 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
|
||||
static inline int
|
||||
valid_user_frame(const void __user *fp, unsigned long size)
|
||||
{
|
||||
return (__range_not_ok(fp, size, TASK_SIZE) == 0);
|
||||
return __access_ok(fp, size);
|
||||
}
|
||||
|
||||
static unsigned long get_segment_base(unsigned int segment)
|
||||
|
@ -12,35 +12,6 @@
|
||||
#include <asm/smap.h>
|
||||
#include <asm/extable.h>
|
||||
|
||||
/*
|
||||
* Test whether a block of memory is a valid user space address.
|
||||
* Returns 0 if the range is valid, nonzero otherwise.
|
||||
*/
|
||||
static inline bool __chk_range_not_ok(unsigned long addr, unsigned long size, unsigned long limit)
|
||||
{
|
||||
/*
|
||||
* If we have used "sizeof()" for the size,
|
||||
* we know it won't overflow the limit (but
|
||||
* it might overflow the 'addr', so it's
|
||||
* important to subtract the size from the
|
||||
* limit, not add it to the address).
|
||||
*/
|
||||
if (__builtin_constant_p(size))
|
||||
return unlikely(addr > limit - size);
|
||||
|
||||
/* Arbitrary sizes? Be careful about overflow */
|
||||
addr += size;
|
||||
if (unlikely(addr < size))
|
||||
return true;
|
||||
return unlikely(addr > limit);
|
||||
}
|
||||
|
||||
#define __range_not_ok(addr, size, limit) \
|
||||
({ \
|
||||
__chk_user_ptr(addr); \
|
||||
__chk_range_not_ok((unsigned long __force)(addr), size, limit); \
|
||||
})
|
||||
|
||||
#ifdef CONFIG_DEBUG_ATOMIC_SLEEP
|
||||
static inline bool pagefault_disabled(void);
|
||||
# define WARN_ON_IN_IRQ() \
|
||||
@ -69,9 +40,11 @@ static inline bool pagefault_disabled(void);
|
||||
#define access_ok(addr, size) \
|
||||
({ \
|
||||
WARN_ON_IN_IRQ(); \
|
||||
likely(!__range_not_ok(addr, size, TASK_SIZE_MAX)); \
|
||||
likely(__access_ok(addr, size)); \
|
||||
})
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
extern int __get_user_1(void);
|
||||
extern int __get_user_2(void);
|
||||
extern int __get_user_4(void);
|
||||
@ -524,8 +497,6 @@ do { \
|
||||
unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \
|
||||
} while (0)
|
||||
|
||||
#define HAVE_GET_KERNEL_NOFAULT
|
||||
|
||||
#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
|
||||
#define __get_kernel_nofault(dst, src, type, err_label) \
|
||||
__get_user_size(*((type *)(dst)), (__force type __user *)(src), \
|
||||
|
@ -81,12 +81,6 @@ static int copy_code(struct pt_regs *regs, u8 *buf, unsigned long src,
|
||||
/* The user space code from other tasks cannot be accessed. */
|
||||
if (regs != task_pt_regs(current))
|
||||
return -EPERM;
|
||||
/*
|
||||
* Make sure userspace isn't trying to trick us into dumping kernel
|
||||
* memory by pointing the userspace instruction pointer at it.
|
||||
*/
|
||||
if (__chk_range_not_ok(src, nbytes, TASK_SIZE_MAX))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Even if named copy_from_user_nmi() this can be invoked from
|
||||
|
@ -90,7 +90,7 @@ copy_stack_frame(const struct stack_frame_user __user *fp,
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (__range_not_ok(fp, sizeof(*frame), TASK_SIZE))
|
||||
if (!__access_ok(fp, sizeof(*frame)))
|
||||
return 0;
|
||||
|
||||
ret = 1;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user