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:
Arnd Bergmann 2022-02-25 11:16:17 +01:00
commit dd865f090f
No known key found for this signature in database
GPG key ID: 9A6C79EFE60018D9
127 changed files with 403 additions and 1292 deletions

View file

@ -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

View file

@ -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

View file

@ -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 { }

View file

@ -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, \
}

View file

@ -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);

View file

@ -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

View file

@ -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 */

View file

@ -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)

View file

@ -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

View file

@ -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;

View file

@ -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); \

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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.

View file

@ -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(); \

View file

@ -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

View file

@ -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; \

View file

@ -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 */

View file

@ -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, \

View file

@ -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 */

View file

@ -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));

View file

@ -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)))

View file

@ -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));

View file

@ -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

View file

@ -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>

View file

@ -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 */

View file

@ -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 */

View file

@ -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>

View file

@ -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>

View file

@ -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",

View file

@ -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>

View file

@ -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

View file

@ -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, \
}

View file

@ -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.

View file

@ -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;

View file

@ -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

View file

@ -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) \

View file

@ -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, \
}

View file

@ -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

View file

@ -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:

View file

@ -453,6 +453,7 @@ config CPU_HAS_NO_UNALIGNED
config CPU_HAS_ADDRESS_SPACES
bool
select ALTERNATE_USER_ADDRESS_SPACE
config FPU
bool

View file

@ -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); \

View file

@ -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

View file

@ -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 */

View file

@ -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; \
})

View file

@ -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();

View file

@ -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)

View file

@ -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; \

View file

@ -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?
*/

View file

@ -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.

View file

@ -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))

View file

@ -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; \
})

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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 */

View file

@ -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 */

View file

@ -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 @@ asmlinkage int do_rt_sigreturn(struct switch_stack *sw)
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));

View file

@ -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

View file

@ -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, \
}

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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; \

View file

@ -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

View file

@ -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. */

View file

@ -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)

View file

@ -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

View file

@ -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; \

View file

@ -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)))

View file

@ -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

View file

@ -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) \

View file

@ -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

View file

@ -3,7 +3,6 @@
#define __ASM_SH_PROCESSOR_H
#include <asm/cpu-features.h>
#include <asm/segment.h>
#include <asm/cache.h>
#ifndef __ASSEMBLY__

View file

@ -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 */

View file

@ -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 */

View file

@ -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 ...

View file

@ -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;
}

View file

@ -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;

View file

@ -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 @@ asmlinkage void do_address_error(struct pt_regs *regs,
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 @@ asmlinkage void do_address_error(struct pt_regs *regs,
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);
}
}

View file

@ -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

View file

@ -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 \
}

View file

@ -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 {

View file

@ -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__( \

View file

@ -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 \
}

View file

@ -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

View file

@ -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;

View file

@ -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; \

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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) \

View file

@ -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");
}

View file

@ -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)); \

View file

@ -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)

View file

@ -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), \

View file

@ -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

View file

@ -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