mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:41:42 +00:00
uaccess: remove CONFIG_SET_FS
There are no remaining callers of set_fs(), so CONFIG_SET_FS can be removed globally, along with the thread_info field and any references to it. This turns access_ok() into a cheaper check against TASK_SIZE_MAX. As CONFIG_SET_FS is now gone, drop all remaining references to set_fs()/get_fs(), mm_segment_t, user_addr_max() and uaccess_kernel(). Acked-by: Sam Ravnborg <sam@ravnborg.org> # for sparc32 changes Acked-by: "Eric W. Biederman" <ebiederm@xmission.com> Tested-by: Sergey Matyukevich <sergey.matyukevich@synopsys.com> # for arc changes Acked-by: Stafford Horne <shorne@gmail.com> # [openrisc, asm-generic] Acked-by: Dinh Nguyen <dinguyen@kernel.org> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
parent
e5ef21d139
commit
967747bbc0
@ -24,9 +24,6 @@ config KEXEC_ELF
|
|||||||
config HAVE_IMA_KEXEC
|
config HAVE_IMA_KEXEC
|
||||||
bool
|
bool
|
||||||
|
|
||||||
config SET_FS
|
|
||||||
bool
|
|
||||||
|
|
||||||
config HOTPLUG_SMT
|
config HOTPLUG_SMT
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ config ALPHA
|
|||||||
select OLD_SIGSUSPEND
|
select OLD_SIGSUSPEND
|
||||||
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
|
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
|
||||||
select MMU_GATHER_NO_RANGE
|
select MMU_GATHER_NO_RANGE
|
||||||
select SET_FS
|
|
||||||
select SPARSEMEM_EXTREME if SPARSEMEM
|
select SPARSEMEM_EXTREME if SPARSEMEM
|
||||||
select ZONE_DMA
|
select ZONE_DMA
|
||||||
help
|
help
|
||||||
|
@ -26,10 +26,6 @@
|
|||||||
#define TASK_UNMAPPED_BASE \
|
#define TASK_UNMAPPED_BASE \
|
||||||
((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2)
|
((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. */
|
/* This is dead. Everything has been moved to thread_info. */
|
||||||
struct thread_struct { };
|
struct thread_struct { };
|
||||||
#define INIT_THREAD { }
|
#define INIT_THREAD { }
|
||||||
|
@ -19,7 +19,6 @@ struct thread_info {
|
|||||||
unsigned int flags; /* low level flags */
|
unsigned int flags; /* low level flags */
|
||||||
unsigned int ieee_state; /* see fpu.h */
|
unsigned int ieee_state; /* see fpu.h */
|
||||||
|
|
||||||
mm_segment_t addr_limit; /* thread address space */
|
|
||||||
unsigned cpu; /* current CPU */
|
unsigned cpu; /* current CPU */
|
||||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||||
unsigned int status; /* thread-synchronous flags */
|
unsigned int status; /* thread-synchronous flags */
|
||||||
@ -35,7 +34,6 @@ struct thread_info {
|
|||||||
#define INIT_THREAD_INFO(tsk) \
|
#define INIT_THREAD_INFO(tsk) \
|
||||||
{ \
|
{ \
|
||||||
.task = &tsk, \
|
.task = &tsk, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,26 +2,7 @@
|
|||||||
#ifndef __ALPHA_UACCESS_H
|
#ifndef __ALPHA_UACCESS_H
|
||||||
#define __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))
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the main single-value transfer routines. They automatically
|
* These are the main single-value transfer routines. They automatically
|
||||||
* use the right size if we just have the right pointer type.
|
* use the right size if we just have the right pointer type.
|
||||||
|
@ -45,7 +45,6 @@ config ARC
|
|||||||
select PCI_SYSCALL if PCI
|
select PCI_SYSCALL if PCI
|
||||||
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
|
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
|
||||||
select HAVE_ARCH_JUMP_LABEL if ISA_ARCV2 && !CPU_ENDIAN_BE32
|
select HAVE_ARCH_JUMP_LABEL if ISA_ARCV2 && !CPU_ENDIAN_BE32
|
||||||
select SET_FS
|
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
|
|
||||||
config LOCKDEP_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__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
#include <linux/thread_info.h>
|
#include <linux/thread_info.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* low level task data that entry.S needs immediate access to
|
* low level task data that entry.S needs immediate access to
|
||||||
@ -40,7 +39,6 @@ struct thread_info {
|
|||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||||
struct task_struct *task; /* main task structure */
|
struct task_struct *task; /* main task structure */
|
||||||
mm_segment_t addr_limit; /* thread address space */
|
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
unsigned long thr_ptr; /* TLS ptr */
|
unsigned long thr_ptr; /* TLS ptr */
|
||||||
};
|
};
|
||||||
@ -56,7 +54,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
||||||
|
@ -638,7 +638,6 @@ extern unsigned long arc_clear_user_noinline(void __user *to,
|
|||||||
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
|
#define __clear_user(d, n) arc_clear_user_noinline(d, n)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm-generic/uaccess.h>
|
#include <asm-generic/uaccess.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -92,11 +92,6 @@ __copy_to_user_memcpy(void __user *to, const void *from, unsigned long n)
|
|||||||
unsigned long ua_flags;
|
unsigned long ua_flags;
|
||||||
int atomic;
|
int atomic;
|
||||||
|
|
||||||
if (uaccess_kernel()) {
|
|
||||||
memcpy((void *)to, from, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* the mmap semaphore is taken only if not in an atomic context */
|
/* the mmap semaphore is taken only if not in an atomic context */
|
||||||
atomic = faulthandler_disabled();
|
atomic = faulthandler_disabled();
|
||||||
|
|
||||||
@ -165,11 +160,6 @@ __clear_user_memset(void __user *addr, unsigned long n)
|
|||||||
{
|
{
|
||||||
unsigned long ua_flags;
|
unsigned long ua_flags;
|
||||||
|
|
||||||
if (uaccess_kernel()) {
|
|
||||||
memset((void *)addr, 0, n);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mmap_read_lock(current->mm);
|
mmap_read_lock(current->mm);
|
||||||
while (n) {
|
while (n) {
|
||||||
pte_t *pte;
|
pte_t *pte;
|
||||||
|
@ -519,7 +519,7 @@ void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr)
|
|||||||
NOKPROBE_SYMBOL(do_ptrauth_fault);
|
NOKPROBE_SYMBOL(do_ptrauth_fault);
|
||||||
|
|
||||||
#define __user_cache_maint(insn, address, res) \
|
#define __user_cache_maint(insn, address, res) \
|
||||||
if (address >= user_addr_max()) { \
|
if (address >= TASK_SIZE_MAX) { \
|
||||||
res = -EFAULT; \
|
res = -EFAULT; \
|
||||||
} else { \
|
} else { \
|
||||||
uaccess_ttbr0_enable(); \
|
uaccess_ttbr0_enable(); \
|
||||||
|
@ -79,7 +79,6 @@ config CSKY
|
|||||||
select PCI_DOMAINS_GENERIC if PCI
|
select PCI_DOMAINS_GENERIC if PCI
|
||||||
select PCI_SYSCALL if PCI
|
select PCI_SYSCALL if PCI
|
||||||
select PCI_MSI if PCI
|
select PCI_MSI if PCI
|
||||||
select SET_FS
|
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
|
|
||||||
config LOCKDEP_SUPPORT
|
config LOCKDEP_SUPPORT
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#define __ASM_CSKY_PROCESSOR_H
|
#define __ASM_CSKY_PROCESSOR_H
|
||||||
|
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/current.h>
|
#include <asm/current.h>
|
||||||
#include <asm/cache.h>
|
#include <asm/cache.h>
|
||||||
@ -59,7 +58,6 @@ struct thread_struct {
|
|||||||
*/
|
*/
|
||||||
#define start_thread(_regs, _pc, _usp) \
|
#define start_thread(_regs, _pc, _usp) \
|
||||||
do { \
|
do { \
|
||||||
set_fs(USER_DS); /* reads from user space */ \
|
|
||||||
(_regs)->pc = (_pc); \
|
(_regs)->pc = (_pc); \
|
||||||
(_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */ \
|
(_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */ \
|
||||||
(_regs)->regs[2] = 0; \
|
(_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;
|
unsigned long flags;
|
||||||
int preempt_count;
|
int preempt_count;
|
||||||
unsigned long tp_value;
|
unsigned long tp_value;
|
||||||
mm_segment_t addr_limit;
|
|
||||||
struct restart_block restart_block;
|
struct restart_block restart_block;
|
||||||
struct pt_regs *regs;
|
struct pt_regs *regs;
|
||||||
unsigned int cpu;
|
unsigned int cpu;
|
||||||
@ -26,7 +25,6 @@ struct thread_info {
|
|||||||
{ \
|
{ \
|
||||||
.task = &tsk, \
|
.task = &tsk, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.restart_block = { \
|
.restart_block = { \
|
||||||
.fn = do_no_restart_syscall, \
|
.fn = do_no_restart_syscall, \
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
#ifndef __ASM_CSKY_UACCESS_H
|
#ifndef __ASM_CSKY_UACCESS_H
|
||||||
#define __ASM_CSKY_UACCESS_H
|
#define __ASM_CSKY_UACCESS_H
|
||||||
|
|
||||||
#define user_addr_max() (current_thread_info()->addr_limit.seg)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* __put_user_fn
|
* __put_user_fn
|
||||||
*/
|
*/
|
||||||
@ -200,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);
|
unsigned long __clear_user(void __user *to, unsigned long n);
|
||||||
#define __clear_user __clear_user
|
#define __clear_user __clear_user
|
||||||
|
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm-generic/uaccess.h>
|
#include <asm-generic/uaccess.h>
|
||||||
|
|
||||||
#endif /* __ASM_CSKY_UACCESS_H */
|
#endif /* __ASM_CSKY_UACCESS_H */
|
||||||
|
@ -25,7 +25,6 @@ int main(void)
|
|||||||
/* offsets into the thread_info struct */
|
/* offsets into the thread_info struct */
|
||||||
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
||||||
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
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_TP_VALUE, offsetof(struct thread_info, tp_value));
|
||||||
DEFINE(TINFO_TASK, offsetof(struct thread_info, task));
|
DEFINE(TINFO_TASK, offsetof(struct thread_info, task));
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@ config H8300
|
|||||||
select HAVE_ARCH_KGDB
|
select HAVE_ARCH_KGDB
|
||||||
select HAVE_ARCH_HASH
|
select HAVE_ARCH_HASH
|
||||||
select CPU_NO_EFFICIENT_FFS
|
select CPU_NO_EFFICIENT_FFS
|
||||||
select SET_FS
|
|
||||||
select UACCESS_MEMCPY
|
select UACCESS_MEMCPY
|
||||||
|
|
||||||
config CPU_BIG_ENDIAN
|
config CPU_BIG_ENDIAN
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#define __ASM_H8300_PROCESSOR_H
|
#define __ASM_H8300_PROCESSOR_H
|
||||||
|
|
||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/current.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
|
#define _ASM_THREAD_INFO_H
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
|
|
||||||
@ -31,7 +30,6 @@ struct thread_info {
|
|||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
int cpu; /* cpu we're on */
|
int cpu; /* cpu we're on */
|
||||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||||
mm_segment_t addr_limit;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -43,7 +41,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how to get the thread information struct from C */
|
/* how to get the thread information struct from C */
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include <linux/sys.h>
|
#include <linux/sys.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/linkage.h>
|
#include <asm/linkage.h>
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <asm/unistd.h>
|
#include <asm/unistd.h>
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/linkage.h>
|
#include <asm/linkage.h>
|
||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/thread_info.h>
|
#include <asm/thread_info.h>
|
||||||
|
@ -34,7 +34,6 @@
|
|||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/sections.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",
|
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||||
__func__, PAGE_SIZE, PAGE_SIZE);
|
__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("before free_area_init\n");
|
||||||
|
|
||||||
pr_debug("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
|
pr_debug("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/segment.h>
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/traps.h>
|
#include <asm/traps.h>
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
@ -30,7 +30,6 @@ config HEXAGON
|
|||||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||||
select MODULES_USE_ELF_RELA
|
select MODULES_USE_ELF_RELA
|
||||||
select GENERIC_CPU_DEVICES
|
select GENERIC_CPU_DEVICES
|
||||||
select SET_FS
|
|
||||||
select ARCH_WANT_LD_ORPHAN_WARN
|
select ARCH_WANT_LD_ORPHAN_WARN
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
help
|
help
|
||||||
|
@ -22,10 +22,6 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long seg;
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is union'd with the "bottom" of the kernel stack.
|
* This is union'd with the "bottom" of the kernel stack.
|
||||||
* It keeps track of thread info which is handy for routines
|
* It keeps track of thread info which is handy for routines
|
||||||
@ -37,7 +33,6 @@ struct thread_info {
|
|||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
__u32 cpu; /* current cpu */
|
__u32 cpu; /* current cpu */
|
||||||
int preempt_count; /* 0=>preemptible,<0=>BUG */
|
int preempt_count; /* 0=>preemptible,<0=>BUG */
|
||||||
mm_segment_t addr_limit; /* segmentation sux */
|
|
||||||
/*
|
/*
|
||||||
* used for syscalls somehow;
|
* used for syscalls somehow;
|
||||||
* seems to have a function pointer and four arguments
|
* seems to have a function pointer and four arguments
|
||||||
@ -66,7 +61,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = 1, \
|
.preempt_count = 1, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
.sp = 0, \
|
.sp = 0, \
|
||||||
.regs = NULL, \
|
.regs = NULL, \
|
||||||
}
|
}
|
||||||
|
@ -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
|
* Parent sees new pid -- not necessary, not even possible at
|
||||||
* this point in the fork process
|
* this point in the fork process
|
||||||
* Might also want to set things like ti->addr_limit
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -42,7 +42,6 @@ config MICROBLAZE
|
|||||||
select CPU_NO_EFFICIENT_FFS
|
select CPU_NO_EFFICIENT_FFS
|
||||||
select MMU_GATHER_NO_RANGE
|
select MMU_GATHER_NO_RANGE
|
||||||
select SPARSE_IRQ
|
select SPARSE_IRQ
|
||||||
select SET_FS
|
|
||||||
select ZONE_DMA
|
select ZONE_DMA
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
|
|
||||||
|
@ -56,17 +56,12 @@ struct cpu_context {
|
|||||||
__u32 fsr;
|
__u32 fsr;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long seg;
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
struct thread_info {
|
struct thread_info {
|
||||||
struct task_struct *task; /* main task structure */
|
struct task_struct *task; /* main task structure */
|
||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
unsigned long status; /* thread-synchronous flags */
|
unsigned long status; /* thread-synchronous flags */
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||||
mm_segment_t addr_limit; /* thread address space */
|
|
||||||
|
|
||||||
struct cpu_context cpu_context;
|
struct cpu_context cpu_context;
|
||||||
};
|
};
|
||||||
@ -80,7 +75,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how to get the thread information struct from C */
|
/* how to get the thread information struct from C */
|
||||||
|
@ -15,30 +15,6 @@
|
|||||||
#include <linux/pgtable.h>
|
#include <linux/pgtable.h>
|
||||||
#include <asm/extable.h>
|
#include <asm/extable.h>
|
||||||
#include <linux/string.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)
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
||||||
|
@ -86,7 +86,6 @@ int main(int argc, char *argv[])
|
|||||||
/* struct thread_info */
|
/* struct thread_info */
|
||||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
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_CPU_CONTEXT, offsetof(struct thread_info, cpu_context));
|
||||||
DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count));
|
DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count));
|
||||||
BLANK();
|
BLANK();
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
#include <linux/tick.h>
|
#include <linux/tick.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/uaccess.h> /* for USER_DS macros */
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
|
|
||||||
void show_regs(struct pt_regs *regs)
|
void show_regs(struct pt_regs *regs)
|
||||||
|
@ -44,7 +44,6 @@ config NDS32
|
|||||||
select HAVE_FUNCTION_GRAPH_TRACER
|
select HAVE_FUNCTION_GRAPH_TRACER
|
||||||
select HAVE_FTRACE_MCOUNT_RECORD
|
select HAVE_FTRACE_MCOUNT_RECORD
|
||||||
select HAVE_DYNAMIC_FTRACE
|
select HAVE_DYNAMIC_FTRACE
|
||||||
select SET_FS
|
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
help
|
help
|
||||||
Andes(nds32) Linux support.
|
Andes(nds32) Linux support.
|
||||||
|
@ -16,8 +16,6 @@ struct task_struct;
|
|||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
|
|
||||||
typedef unsigned long mm_segment_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* low level task data that entry.S needs immediate access to.
|
* low level task data that entry.S needs immediate access to.
|
||||||
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
|
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
|
||||||
@ -25,12 +23,10 @@ typedef unsigned long mm_segment_t;
|
|||||||
struct thread_info {
|
struct thread_info {
|
||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
__s32 preempt_count; /* 0 => preemptable, <0 => bug */
|
__s32 preempt_count; /* 0 => preemptable, <0 => bug */
|
||||||
mm_segment_t addr_limit; /* address limit */
|
|
||||||
};
|
};
|
||||||
#define INIT_THREAD_INFO(tsk) \
|
#define INIT_THREAD_INFO(tsk) \
|
||||||
{ \
|
{ \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
#define thread_saved_pc(tsk) ((unsigned long)(tsk->thread.cpu_context.pc))
|
#define thread_saved_pc(tsk) ((unsigned long)(tsk->thread.cpu_context.pc))
|
||||||
#define thread_saved_fp(tsk) ((unsigned long)(tsk->thread.cpu_context.fp))
|
#define thread_saved_fp(tsk) ((unsigned long)(tsk->thread.cpu_context.fp))
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <asm/errno.h>
|
#include <asm/errno.h>
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
|
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
|
||||||
|
|
||||||
@ -33,20 +34,6 @@ struct exception_table_entry {
|
|||||||
|
|
||||||
extern int fixup_exception(struct pt_regs *regs);
|
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
|
|
||||||
#define uaccess_kernel() (get_fs() == KERNEL_DS)
|
|
||||||
|
|
||||||
static inline void set_fs(mm_segment_t fs)
|
|
||||||
{
|
|
||||||
current_thread_info()->addr_limit = fs;
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Single-value transfer routines. They automatically use the right
|
* Single-value transfer routines. They automatically use the right
|
||||||
* size if we just have the right pointer type. Note that the functions
|
* size if we just have the right pointer type. Note that the functions
|
||||||
|
@ -119,9 +119,8 @@ void show_regs(struct pt_regs *regs)
|
|||||||
regs->uregs[7], regs->uregs[6], regs->uregs[5], regs->uregs[4]);
|
regs->uregs[7], regs->uregs[6], regs->uregs[5], regs->uregs[4]);
|
||||||
pr_info("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
|
pr_info("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
|
||||||
regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
|
regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
|
||||||
pr_info(" IRQs o%s Segment %s\n",
|
pr_info(" IRQs o%s Segment user\n",
|
||||||
interrupts_enabled(regs) ? "n" : "ff",
|
interrupts_enabled(regs) ? "n" : "ff");
|
||||||
uaccess_kernel() ? "kernel" : "user");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL(show_regs);
|
EXPORT_SYMBOL(show_regs);
|
||||||
|
@ -512,7 +512,6 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
|
|||||||
{
|
{
|
||||||
unsigned long inst;
|
unsigned long inst;
|
||||||
int ret = -EFAULT;
|
int ret = -EFAULT;
|
||||||
mm_segment_t seg;
|
|
||||||
|
|
||||||
inst = get_inst(regs->ipc);
|
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,
|
"Faulting addr: 0x%08lx, pc: 0x%08lx [inst: 0x%08lx ]\n", addr,
|
||||||
regs->ipc, inst);
|
regs->ipc, inst);
|
||||||
|
|
||||||
seg = force_uaccess_begin();
|
|
||||||
if (inst & NDS32_16BIT_INSTRUCTION)
|
if (inst & NDS32_16BIT_INSTRUCTION)
|
||||||
ret = do_16((inst >> 16) & 0xffff, regs);
|
ret = do_16((inst >> 16) & 0xffff, regs);
|
||||||
else
|
else
|
||||||
ret = do_32(inst, regs);
|
ret = do_32(inst, regs);
|
||||||
force_uaccess_end(seg);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ config NIOS2
|
|||||||
select USB_ARCH_HAS_HCD if USB_SUPPORT
|
select USB_ARCH_HAS_HCD if USB_SUPPORT
|
||||||
select CPU_NO_EFFICIENT_FFS
|
select CPU_NO_EFFICIENT_FFS
|
||||||
select MMU_GATHER_NO_RANGE if MMU
|
select MMU_GATHER_NO_RANGE if MMU
|
||||||
select SET_FS
|
|
||||||
|
|
||||||
config GENERIC_CSUM
|
config GENERIC_CSUM
|
||||||
def_bool y
|
def_bool y
|
||||||
|
@ -26,10 +26,6 @@
|
|||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long seg;
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* low level task data that entry.S needs immediate access to
|
* low level task data that entry.S needs immediate access to
|
||||||
* - this struct should fit entirely inside of one cache line
|
* - this struct should fit entirely inside of one cache line
|
||||||
@ -42,10 +38,6 @@ struct thread_info {
|
|||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
int preempt_count; /* 0 => preemptable,<0 => BUG */
|
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;
|
struct pt_regs *regs;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,7 +52,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how to get the thread information struct from C */
|
/* how to get the thread information struct from C */
|
||||||
|
@ -18,18 +18,6 @@
|
|||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
|
|
||||||
#include <asm/extable.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))
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||||
|
@ -36,7 +36,6 @@ config OPENRISC
|
|||||||
select ARCH_WANT_FRAME_POINTERS
|
select ARCH_WANT_FRAME_POINTERS
|
||||||
select GENERIC_IRQ_MULTI_HANDLER
|
select GENERIC_IRQ_MULTI_HANDLER
|
||||||
select MMU_GATHER_NO_RANGE if MMU
|
select MMU_GATHER_NO_RANGE if MMU
|
||||||
select SET_FS
|
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
|
|
||||||
config CPU_BIG_ENDIAN
|
config CPU_BIG_ENDIAN
|
||||||
|
@ -40,18 +40,12 @@
|
|||||||
*/
|
*/
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
typedef unsigned long mm_segment_t;
|
|
||||||
|
|
||||||
struct thread_info {
|
struct thread_info {
|
||||||
struct task_struct *task; /* main task structure */
|
struct task_struct *task; /* main task structure */
|
||||||
unsigned long flags; /* low level flags */
|
unsigned long flags; /* low level flags */
|
||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
|
__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];
|
__u8 supervisor_stack[0];
|
||||||
|
|
||||||
/* saved context data */
|
/* saved context data */
|
||||||
@ -71,7 +65,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
.ksp = 0, \
|
.ksp = 0, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,29 +22,6 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/extable.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)
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -96,12 +96,6 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
|
|||||||
u32 val;
|
u32 val;
|
||||||
unsigned long flags;
|
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)))
|
if (!access_ok(uaddr, sizeof(u32)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
@ -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);
|
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
|
||||||
|
|
||||||
start = (unsigned long) frame;
|
start = (unsigned long) frame;
|
||||||
if (start >= user_addr_max() - sigframe_size)
|
if (start >= TASK_SIZE_MAX - sigframe_size)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
@ -518,7 +518,7 @@ insert_restart_trampoline(struct pt_regs *regs)
|
|||||||
long err = 0;
|
long err = 0;
|
||||||
|
|
||||||
/* check that we don't exceed the stack */
|
/* 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;
|
return;
|
||||||
|
|
||||||
/* Setup a trampoline to restart the syscall
|
/* Setup a trampoline to restart the syscall
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include <linux/compiler.h>
|
#include <linux/compiler.h>
|
||||||
#include <linux/uaccess.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)
|
#define get_kernel_space() (0)
|
||||||
|
|
||||||
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
|
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
|
||||||
|
@ -58,7 +58,6 @@ config SPARC32
|
|||||||
select HAVE_UID16
|
select HAVE_UID16
|
||||||
select OLD_SIGACTION
|
select OLD_SIGACTION
|
||||||
select ZONE_DMA
|
select ZONE_DMA
|
||||||
select SET_FS
|
|
||||||
|
|
||||||
config SPARC64
|
config SPARC64
|
||||||
def_bool 64BIT
|
def_bool 64BIT
|
||||||
|
@ -32,10 +32,6 @@ struct fpq {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
int seg;
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
/* The Sparc processor specific thread struct. */
|
/* The Sparc processor specific thread struct. */
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
struct pt_regs *kregs;
|
struct pt_regs *kregs;
|
||||||
@ -50,11 +46,9 @@ struct thread_struct {
|
|||||||
unsigned long fsr;
|
unsigned long fsr;
|
||||||
unsigned long fpqdepth;
|
unsigned long fpqdepth;
|
||||||
struct fpq fpqueue[16];
|
struct fpq fpqueue[16];
|
||||||
mm_segment_t current_ds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INIT_THREAD { \
|
#define INIT_THREAD { \
|
||||||
.current_ds = KERNEL_DS, \
|
|
||||||
.kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
|
.kregs = (struct pt_regs *)(init_stack+THREAD_SIZE)-1 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,19 +12,6 @@
|
|||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
|
||||||
#include <asm/processor.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))
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
/* Uh, these should become the main single-value transfer routines..
|
/* Uh, these should become the main single-value transfer routines..
|
||||||
|
@ -300,7 +300,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
|
|||||||
extern int nwindows;
|
extern int nwindows;
|
||||||
unsigned long psr;
|
unsigned long psr;
|
||||||
memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
|
memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);
|
||||||
p->thread.current_ds = KERNEL_DS;
|
|
||||||
ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
|
ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);
|
||||||
childregs->u_regs[UREG_G1] = sp; /* function */
|
childregs->u_regs[UREG_G1] = sp; /* function */
|
||||||
childregs->u_regs[UREG_G2] = arg;
|
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);
|
memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);
|
||||||
childregs->u_regs[UREG_FP] = sp;
|
childregs->u_regs[UREG_FP] = sp;
|
||||||
p->thread.current_ds = USER_DS;
|
|
||||||
ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
|
ti->kpc = (((unsigned long) ret_from_fork) - 0x8);
|
||||||
ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
|
ti->kpsr = current->thread.fork_kpsr | PSR_PIL;
|
||||||
ti->kwim = current->thread.fork_kwim;
|
ti->kwim = current->thread.fork_kwim;
|
||||||
|
@ -40,7 +40,6 @@ config XTENSA
|
|||||||
select IRQ_DOMAIN
|
select IRQ_DOMAIN
|
||||||
select MODULES_USE_ELF_RELA
|
select MODULES_USE_ELF_RELA
|
||||||
select PERF_USE_VMALLOC
|
select PERF_USE_VMALLOC
|
||||||
select SET_FS
|
|
||||||
select TRACE_IRQFLAGS_SUPPORT
|
select TRACE_IRQFLAGS_SUPPORT
|
||||||
select VIRT_TO_BUS
|
select VIRT_TO_BUS
|
||||||
help
|
help
|
||||||
|
@ -23,76 +23,6 @@
|
|||||||
#include <asm/asm-offsets.h>
|
#include <asm/asm-offsets.h>
|
||||||
#include <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
|
|
||||||
/*
|
|
||||||
* These assembly macros mirror the C macros in asm/uaccess.h. They
|
|
||||||
* should always have identical functionality. See
|
|
||||||
* arch/xtensa/kernel/sys.S for usage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define KERNEL_DS 0
|
|
||||||
#define USER_DS 1
|
|
||||||
|
|
||||||
/*
|
|
||||||
* get_fs reads current->thread.current_ds into a register.
|
|
||||||
* On Entry:
|
|
||||||
* <ad> anything
|
|
||||||
* <sp> stack
|
|
||||||
* On Exit:
|
|
||||||
* <ad> contains current->thread.current_ds
|
|
||||||
*/
|
|
||||||
.macro get_fs ad, sp
|
|
||||||
GET_CURRENT(\ad,\sp)
|
|
||||||
#if THREAD_CURRENT_DS > 1020
|
|
||||||
addi \ad, \ad, TASK_THREAD
|
|
||||||
l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD
|
|
||||||
#else
|
|
||||||
l32i \ad, \ad, THREAD_CURRENT_DS
|
|
||||||
#endif
|
|
||||||
.endm
|
|
||||||
|
|
||||||
/*
|
|
||||||
* set_fs sets current->thread.current_ds to some value.
|
|
||||||
* On Entry:
|
|
||||||
* <at> anything (temp register)
|
|
||||||
* <av> value to write
|
|
||||||
* <sp> stack
|
|
||||||
* On Exit:
|
|
||||||
* <at> destroyed (actually, current)
|
|
||||||
* <av> preserved, value to write
|
|
||||||
*/
|
|
||||||
.macro set_fs at, av, sp
|
|
||||||
GET_CURRENT(\at,\sp)
|
|
||||||
s32i \av, \at, THREAD_CURRENT_DS
|
|
||||||
.endm
|
|
||||||
|
|
||||||
/*
|
|
||||||
* kernel_ok determines whether we should bypass addr/size checking.
|
|
||||||
* See the equivalent C-macro version below for clarity.
|
|
||||||
* On success, kernel_ok branches to a label indicated by parameter
|
|
||||||
* <success>. This implies that the macro falls through to the next
|
|
||||||
* insruction on an error.
|
|
||||||
*
|
|
||||||
* Note that while this macro can be used independently, we designed
|
|
||||||
* in for optimal use in the access_ok macro below (i.e., we fall
|
|
||||||
* through on error).
|
|
||||||
*
|
|
||||||
* On Entry:
|
|
||||||
* <at> anything (temp register)
|
|
||||||
* <success> label to branch to on success; implies
|
|
||||||
* fall-through macro on error
|
|
||||||
* <sp> stack pointer
|
|
||||||
* On Exit:
|
|
||||||
* <at> destroyed (actually, current->thread.current_ds)
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if ((KERNEL_DS != 0) || (USER_DS == 0))
|
|
||||||
# error Assembly macro kernel_ok fails
|
|
||||||
#endif
|
|
||||||
.macro kernel_ok at, sp, success
|
|
||||||
get_fs \at, \sp
|
|
||||||
beqz \at, \success
|
|
||||||
.endm
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* user_ok determines whether the access to user-space memory is allowed.
|
* user_ok determines whether the access to user-space memory is allowed.
|
||||||
* See the equivalent C-macro version below for clarity.
|
* See the equivalent C-macro version below for clarity.
|
||||||
@ -147,7 +77,6 @@
|
|||||||
* <at> destroyed
|
* <at> destroyed
|
||||||
*/
|
*/
|
||||||
.macro access_ok aa, as, at, sp, error
|
.macro access_ok aa, as, at, sp, error
|
||||||
kernel_ok \at, \sp, .Laccess_ok_\@
|
|
||||||
user_ok \aa, \as, \at, \error
|
user_ok \aa, \as, \at, \error
|
||||||
.Laccess_ok_\@:
|
.Laccess_ok_\@:
|
||||||
.endm
|
.endm
|
||||||
|
@ -152,18 +152,12 @@
|
|||||||
*/
|
*/
|
||||||
#define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg)))
|
#define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg)))
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
unsigned long seg;
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
struct thread_struct {
|
struct thread_struct {
|
||||||
|
|
||||||
/* kernel's return address and stack pointer for context switching */
|
/* kernel's return address and stack pointer for context switching */
|
||||||
unsigned long ra; /* kernel's a0: return address and window call size */
|
unsigned long ra; /* kernel's a0: return address and window call size */
|
||||||
unsigned long sp; /* kernel's a1: stack pointer */
|
unsigned long sp; /* kernel's a1: stack pointer */
|
||||||
|
|
||||||
mm_segment_t current_ds; /* see uaccess.h for example uses */
|
|
||||||
|
|
||||||
/* struct xtensa_cpuinfo info; */
|
/* struct xtensa_cpuinfo info; */
|
||||||
|
|
||||||
unsigned long bad_vaddr; /* last user fault */
|
unsigned long bad_vaddr; /* last user fault */
|
||||||
@ -186,7 +180,6 @@ struct thread_struct {
|
|||||||
{ \
|
{ \
|
||||||
ra: 0, \
|
ra: 0, \
|
||||||
sp: sizeof(init_stack) + (long) &init_stack, \
|
sp: sizeof(init_stack) + (long) &init_stack, \
|
||||||
current_ds: {0}, \
|
|
||||||
/*info: {0}, */ \
|
/*info: {0}, */ \
|
||||||
bad_vaddr: 0, \
|
bad_vaddr: 0, \
|
||||||
bad_uaddr: 0, \
|
bad_uaddr: 0, \
|
||||||
|
@ -52,8 +52,6 @@ struct thread_info {
|
|||||||
__u32 cpu; /* current CPU */
|
__u32 cpu; /* current CPU */
|
||||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||||
|
|
||||||
mm_segment_t addr_limit; /* thread address space */
|
|
||||||
|
|
||||||
unsigned long cpenable;
|
unsigned long cpenable;
|
||||||
#if XCHAL_HAVE_EXCLUSIVE
|
#if XCHAL_HAVE_EXCLUSIVE
|
||||||
/* result of the most recent exclusive store */
|
/* result of the most recent exclusive store */
|
||||||
@ -81,7 +79,6 @@ struct thread_info {
|
|||||||
.flags = 0, \
|
.flags = 0, \
|
||||||
.cpu = 0, \
|
.cpu = 0, \
|
||||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||||
.addr_limit = KERNEL_DS, \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how to get the thread information struct from C */
|
/* how to get the thread information struct from C */
|
||||||
|
@ -19,22 +19,6 @@
|
|||||||
#include <linux/prefetch.h>
|
#include <linux/prefetch.h>
|
||||||
#include <asm/types.h>
|
#include <asm/types.h>
|
||||||
#include <asm/extable.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 (Data Segment Register?), these macros are
|
|
||||||
* grossly misnamed.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#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))
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -87,7 +87,6 @@ int main(void)
|
|||||||
OFFSET(TI_STSTUS, thread_info, status);
|
OFFSET(TI_STSTUS, thread_info, status);
|
||||||
OFFSET(TI_CPU, thread_info, cpu);
|
OFFSET(TI_CPU, thread_info, cpu);
|
||||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
|
||||||
|
|
||||||
/* struct thread_info (offset from start_struct) */
|
/* struct thread_info (offset from start_struct) */
|
||||||
DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
|
DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
|
||||||
@ -108,8 +107,6 @@ int main(void)
|
|||||||
#endif
|
#endif
|
||||||
DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user));
|
DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user));
|
||||||
DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t));
|
DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t));
|
||||||
DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, \
|
|
||||||
thread.current_ds));
|
|
||||||
|
|
||||||
/* struct mm_struct */
|
/* struct mm_struct */
|
||||||
DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
|
DEFINE(MM_USERS, offsetof(struct mm_struct, mm_users));
|
||||||
|
@ -747,7 +747,7 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,
|
|||||||
* copied from, so it's unsafe to allow this with elevated
|
* copied from, so it's unsafe to allow this with elevated
|
||||||
* privileges (e.g. from a setuid binary) or via kernel_write().
|
* privileges (e.g. from a setuid binary) or via kernel_write().
|
||||||
*/
|
*/
|
||||||
if (file->f_cred != current_cred() || uaccess_kernel()) {
|
if (file->f_cred != current_cred()) {
|
||||||
pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
|
pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n",
|
||||||
task_tgid_vnr(current), current->comm);
|
task_tgid_vnr(current), current->comm);
|
||||||
ret = -EACCES;
|
ret = -EACCES;
|
||||||
|
@ -224,11 +224,6 @@ static int sg_check_file_access(struct file *filp, const char *caller)
|
|||||||
caller, task_tgid_vnr(current), current->comm);
|
caller, task_tgid_vnr(current), current->comm);
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
}
|
}
|
||||||
if (uaccess_kernel()) {
|
|
||||||
pr_err_once("%s: process %d (%s) called from kernel context, this is not allowed.\n",
|
|
||||||
caller, task_tgid_vnr(current), current->comm);
|
|
||||||
return -EACCES;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1303,12 +1303,6 @@ int begin_new_exec(struct linux_binprm * bprm)
|
|||||||
if (retval)
|
if (retval)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
/*
|
|
||||||
* Ensure that the uaccess routines can actually operate on userspace
|
|
||||||
* pointers:
|
|
||||||
*/
|
|
||||||
force_uaccess_begin();
|
|
||||||
|
|
||||||
if (me->flags & PF_KTHREAD)
|
if (me->flags & PF_KTHREAD)
|
||||||
free_kthread_struct(me);
|
free_kthread_struct(me);
|
||||||
me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
|
me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
|
||||||
|
@ -16,18 +16,6 @@
|
|||||||
#define TASK_SIZE_MAX TASK_SIZE
|
#define TASK_SIZE_MAX TASK_SIZE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef uaccess_kernel
|
|
||||||
#ifdef CONFIG_SET_FS
|
|
||||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
|
||||||
#else
|
|
||||||
#define uaccess_kernel() (0)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef user_addr_max
|
|
||||||
#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE_MAX)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __access_ok
|
#ifndef __access_ok
|
||||||
/*
|
/*
|
||||||
* 'size' is a compile-time constant for most callers, so optimize for
|
* 'size' is a compile-time constant for most callers, so optimize for
|
||||||
@ -42,7 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
static inline int __access_ok(const void __user *ptr, unsigned long size)
|
static inline int __access_ok(const void __user *ptr, unsigned long size)
|
||||||
{
|
{
|
||||||
unsigned long limit = user_addr_max();
|
unsigned long limit = TASK_SIZE_MAX;
|
||||||
unsigned long addr = (unsigned long)ptr;
|
unsigned long addr = (unsigned long)ptr;
|
||||||
|
|
||||||
if (IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) ||
|
if (IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) ||
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* address space, e.g. all NOMMU machines.
|
* address space, e.g. all NOMMU machines.
|
||||||
*/
|
*/
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
|
#include <asm-generic/access_ok.h>
|
||||||
|
|
||||||
#ifdef CONFIG_UACCESS_MEMCPY
|
#ifdef CONFIG_UACCESS_MEMCPY
|
||||||
#include <asm/unaligned.h>
|
#include <asm/unaligned.h>
|
||||||
@ -94,30 +95,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
|
|||||||
#define INLINE_COPY_TO_USER
|
#define INLINE_COPY_TO_USER
|
||||||
#endif /* CONFIG_UACCESS_MEMCPY */
|
#endif /* CONFIG_UACCESS_MEMCPY */
|
||||||
|
|
||||||
#ifdef CONFIG_SET_FS
|
|
||||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
|
||||||
|
|
||||||
#ifndef KERNEL_DS
|
|
||||||
#define KERNEL_DS MAKE_MM_SEG(~0UL)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef USER_DS
|
|
||||||
#define USER_DS MAKE_MM_SEG(TASK_SIZE - 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef get_fs
|
|
||||||
#define get_fs() (current_thread_info()->addr_limit)
|
|
||||||
|
|
||||||
static inline void set_fs(mm_segment_t fs)
|
|
||||||
{
|
|
||||||
current_thread_info()->addr_limit = fs;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* CONFIG_SET_FS */
|
|
||||||
|
|
||||||
#include <asm-generic/access_ok.h>
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are the main single-value transfer routines. They automatically
|
* These are the main single-value transfer routines. They automatically
|
||||||
* use the right size if we just have the right pointer type.
|
* use the right size if we just have the right pointer type.
|
||||||
|
@ -290,10 +290,6 @@ static inline void addr_limit_user_check(void)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (CHECK_DATA_CORRUPTION(uaccess_kernel(),
|
|
||||||
"Invalid address limit on user-mode return"))
|
|
||||||
force_sig(SIGKILL);
|
|
||||||
|
|
||||||
#ifdef TIF_FSCHECK
|
#ifdef TIF_FSCHECK
|
||||||
clear_thread_flag(TIF_FSCHECK);
|
clear_thread_flag(TIF_FSCHECK);
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,39 +10,6 @@
|
|||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
#ifdef CONFIG_SET_FS
|
|
||||||
/*
|
|
||||||
* Force the uaccess routines to be wired up for actual userspace access,
|
|
||||||
* overriding any possible set_fs(KERNEL_DS) still lingering around. Undone
|
|
||||||
* using force_uaccess_end below.
|
|
||||||
*/
|
|
||||||
static inline mm_segment_t force_uaccess_begin(void)
|
|
||||||
{
|
|
||||||
mm_segment_t fs = get_fs();
|
|
||||||
|
|
||||||
set_fs(USER_DS);
|
|
||||||
return fs;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void force_uaccess_end(mm_segment_t oldfs)
|
|
||||||
{
|
|
||||||
set_fs(oldfs);
|
|
||||||
}
|
|
||||||
#else /* CONFIG_SET_FS */
|
|
||||||
typedef struct {
|
|
||||||
/* empty dummy */
|
|
||||||
} mm_segment_t;
|
|
||||||
|
|
||||||
static inline mm_segment_t force_uaccess_begin(void)
|
|
||||||
{
|
|
||||||
return (mm_segment_t) { };
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void force_uaccess_end(mm_segment_t oldfs)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_SET_FS */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Architectures should provide two primitives (raw_copy_{to,from}_user())
|
* Architectures should provide two primitives (raw_copy_{to,from}_user())
|
||||||
* and get rid of their private instances of copy_{to,from}_user() and
|
* and get rid of their private instances of copy_{to,from}_user() and
|
||||||
|
@ -75,7 +75,7 @@ struct sockaddr_ib {
|
|||||||
*/
|
*/
|
||||||
static inline bool ib_safe_file_access(struct file *filp)
|
static inline bool ib_safe_file_access(struct file *filp)
|
||||||
{
|
{
|
||||||
return filp->f_cred == current_cred() && !uaccess_kernel();
|
return filp->f_cred == current_cred();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _RDMA_IB_H */
|
#endif /* _RDMA_IB_H */
|
||||||
|
@ -209,17 +209,13 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (regs) {
|
if (regs) {
|
||||||
mm_segment_t fs;
|
|
||||||
|
|
||||||
if (crosstask)
|
if (crosstask)
|
||||||
goto exit_put;
|
goto exit_put;
|
||||||
|
|
||||||
if (add_mark)
|
if (add_mark)
|
||||||
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
|
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
|
||||||
|
|
||||||
fs = force_uaccess_begin();
|
|
||||||
perf_callchain_user(&ctx, regs);
|
perf_callchain_user(&ctx, regs);
|
||||||
force_uaccess_end(fs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6746,7 +6746,6 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
|
|||||||
unsigned long sp;
|
unsigned long sp;
|
||||||
unsigned int rem;
|
unsigned int rem;
|
||||||
u64 dyn_size;
|
u64 dyn_size;
|
||||||
mm_segment_t fs;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We dump:
|
* We dump:
|
||||||
@ -6764,9 +6763,7 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
|
|||||||
|
|
||||||
/* Data. */
|
/* Data. */
|
||||||
sp = perf_user_stack_pointer(regs);
|
sp = perf_user_stack_pointer(regs);
|
||||||
fs = force_uaccess_begin();
|
|
||||||
rem = __output_copy_user(handle, (void *) sp, dump_size);
|
rem = __output_copy_user(handle, (void *) sp, dump_size);
|
||||||
force_uaccess_end(fs);
|
|
||||||
dyn_size = dump_size - rem;
|
dyn_size = dump_size - rem;
|
||||||
|
|
||||||
perf_output_skip(handle, rem);
|
perf_output_skip(handle, rem);
|
||||||
|
@ -737,20 +737,6 @@ void __noreturn do_exit(long code)
|
|||||||
|
|
||||||
WARN_ON(blk_needs_flush_plug(tsk));
|
WARN_ON(blk_needs_flush_plug(tsk));
|
||||||
|
|
||||||
/*
|
|
||||||
* If do_dead is called because this processes oopsed, it's possible
|
|
||||||
* that get_fs() was left as KERNEL_DS, so reset it to USER_DS before
|
|
||||||
* continuing. Amongst other possible reasons, this is to prevent
|
|
||||||
* mm_release()->clear_child_tid() from writing to a user-controlled
|
|
||||||
* kernel address.
|
|
||||||
*
|
|
||||||
* On uptodate architectures force_uaccess_begin is a noop. On
|
|
||||||
* architectures that still have set_fs/get_fs in addition to handling
|
|
||||||
* oopses handles kernel threads that run as set_fs(KERNEL_DS) by
|
|
||||||
* default.
|
|
||||||
*/
|
|
||||||
force_uaccess_begin();
|
|
||||||
|
|
||||||
kcov_task_exit(tsk);
|
kcov_task_exit(tsk);
|
||||||
|
|
||||||
coredump_task_exit(tsk);
|
coredump_task_exit(tsk);
|
||||||
|
@ -55,7 +55,6 @@ struct kthread {
|
|||||||
int result;
|
int result;
|
||||||
int (*threadfn)(void *);
|
int (*threadfn)(void *);
|
||||||
void *data;
|
void *data;
|
||||||
mm_segment_t oldfs;
|
|
||||||
struct completion parked;
|
struct completion parked;
|
||||||
struct completion exited;
|
struct completion exited;
|
||||||
#ifdef CONFIG_BLK_CGROUP
|
#ifdef CONFIG_BLK_CGROUP
|
||||||
@ -1441,8 +1440,6 @@ void kthread_use_mm(struct mm_struct *mm)
|
|||||||
mmdrop(active_mm);
|
mmdrop(active_mm);
|
||||||
else
|
else
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
|
||||||
to_kthread(tsk)->oldfs = force_uaccess_begin();
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kthread_use_mm);
|
EXPORT_SYMBOL_GPL(kthread_use_mm);
|
||||||
|
|
||||||
@ -1457,8 +1454,6 @@ void kthread_unuse_mm(struct mm_struct *mm)
|
|||||||
WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
|
WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
|
||||||
WARN_ON_ONCE(!tsk->mm);
|
WARN_ON_ONCE(!tsk->mm);
|
||||||
|
|
||||||
force_uaccess_end(to_kthread(tsk)->oldfs);
|
|
||||||
|
|
||||||
task_lock(tsk);
|
task_lock(tsk);
|
||||||
/*
|
/*
|
||||||
* When a kthread stops operating on an address space, the loop
|
* When a kthread stops operating on an address space, the loop
|
||||||
|
@ -226,15 +226,12 @@ unsigned int stack_trace_save_user(unsigned long *store, unsigned int size)
|
|||||||
.store = store,
|
.store = store,
|
||||||
.size = size,
|
.size = size,
|
||||||
};
|
};
|
||||||
mm_segment_t fs;
|
|
||||||
|
|
||||||
/* Trace user stack if not a kernel thread */
|
/* Trace user stack if not a kernel thread */
|
||||||
if (current->flags & PF_KTHREAD)
|
if (current->flags & PF_KTHREAD)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fs = force_uaccess_begin();
|
|
||||||
arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
|
arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
|
||||||
force_uaccess_end(fs);
|
|
||||||
|
|
||||||
return c.len;
|
return c.len;
|
||||||
}
|
}
|
||||||
|
@ -332,8 +332,6 @@ BPF_CALL_3(bpf_probe_write_user, void __user *, unsafe_ptr, const void *, src,
|
|||||||
if (unlikely(in_interrupt() ||
|
if (unlikely(in_interrupt() ||
|
||||||
current->flags & (PF_KTHREAD | PF_EXITING)))
|
current->flags & (PF_KTHREAD | PF_EXITING)))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (unlikely(uaccess_kernel()))
|
|
||||||
return -EPERM;
|
|
||||||
if (unlikely(!nmi_uaccess_okay()))
|
if (unlikely(!nmi_uaccess_okay()))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
@ -835,8 +833,6 @@ static int bpf_send_signal_common(u32 sig, enum pid_type type)
|
|||||||
*/
|
*/
|
||||||
if (unlikely(current->flags & (PF_KTHREAD | PF_EXITING)))
|
if (unlikely(current->flags & (PF_KTHREAD | PF_EXITING)))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (unlikely(uaccess_kernel()))
|
|
||||||
return -EPERM;
|
|
||||||
if (unlikely(!nmi_uaccess_okay()))
|
if (unlikely(!nmi_uaccess_okay()))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
|
|||||||
if (unlikely(count <= 0))
|
if (unlikely(count <= 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
max_addr = user_addr_max();
|
max_addr = TASK_SIZE_MAX;
|
||||||
src_addr = (unsigned long)untagged_addr(src);
|
src_addr = (unsigned long)untagged_addr(src);
|
||||||
if (likely(src_addr < max_addr)) {
|
if (likely(src_addr < max_addr)) {
|
||||||
unsigned long max = max_addr - src_addr;
|
unsigned long max = max_addr - src_addr;
|
||||||
|
@ -96,7 +96,7 @@ long strnlen_user(const char __user *str, long count)
|
|||||||
if (unlikely(count <= 0))
|
if (unlikely(count <= 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
max_addr = user_addr_max();
|
max_addr = TASK_SIZE_MAX;
|
||||||
src_addr = (unsigned long)untagged_addr(str);
|
src_addr = (unsigned long)untagged_addr(str);
|
||||||
if (likely(src_addr < max_addr)) {
|
if (likely(src_addr < max_addr)) {
|
||||||
unsigned long max = max_addr - src_addr;
|
unsigned long max = max_addr - src_addr;
|
||||||
|
11
mm/maccess.c
11
mm/maccess.c
@ -113,14 +113,11 @@ Efault:
|
|||||||
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
|
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
|
||||||
{
|
{
|
||||||
long ret = -EFAULT;
|
long ret = -EFAULT;
|
||||||
mm_segment_t old_fs = force_uaccess_begin();
|
|
||||||
|
|
||||||
if (access_ok(src, size)) {
|
if (access_ok(src, size)) {
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
ret = __copy_from_user_inatomic(dst, src, size);
|
ret = __copy_from_user_inatomic(dst, src, size);
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
}
|
}
|
||||||
force_uaccess_end(old_fs);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -140,14 +137,12 @@ EXPORT_SYMBOL_GPL(copy_from_user_nofault);
|
|||||||
long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
|
long copy_to_user_nofault(void __user *dst, const void *src, size_t size)
|
||||||
{
|
{
|
||||||
long ret = -EFAULT;
|
long ret = -EFAULT;
|
||||||
mm_segment_t old_fs = force_uaccess_begin();
|
|
||||||
|
|
||||||
if (access_ok(dst, size)) {
|
if (access_ok(dst, size)) {
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
ret = __copy_to_user_inatomic(dst, src, size);
|
ret = __copy_to_user_inatomic(dst, src, size);
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
}
|
}
|
||||||
force_uaccess_end(old_fs);
|
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
@ -176,17 +171,14 @@ EXPORT_SYMBOL_GPL(copy_to_user_nofault);
|
|||||||
long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
||||||
long count)
|
long count)
|
||||||
{
|
{
|
||||||
mm_segment_t old_fs;
|
|
||||||
long ret;
|
long ret;
|
||||||
|
|
||||||
if (unlikely(count <= 0))
|
if (unlikely(count <= 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
old_fs = force_uaccess_begin();
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
ret = strncpy_from_user(dst, unsafe_addr, count);
|
ret = strncpy_from_user(dst, unsafe_addr, count);
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
force_uaccess_end(old_fs);
|
|
||||||
|
|
||||||
if (ret >= count) {
|
if (ret >= count) {
|
||||||
ret = count;
|
ret = count;
|
||||||
@ -216,14 +208,11 @@ long strncpy_from_user_nofault(char *dst, const void __user *unsafe_addr,
|
|||||||
*/
|
*/
|
||||||
long strnlen_user_nofault(const void __user *unsafe_addr, long count)
|
long strnlen_user_nofault(const void __user *unsafe_addr, long count)
|
||||||
{
|
{
|
||||||
mm_segment_t old_fs;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
old_fs = force_uaccess_begin();
|
|
||||||
pagefault_disable();
|
pagefault_disable();
|
||||||
ret = strnlen_user(unsafe_addr, count);
|
ret = strnlen_user(unsafe_addr, count);
|
||||||
pagefault_enable();
|
pagefault_enable();
|
||||||
force_uaccess_end(old_fs);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -5256,14 +5256,6 @@ void print_vma_addr(char *prefix, unsigned long ip)
|
|||||||
#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP)
|
#if defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP)
|
||||||
void __might_fault(const char *file, int line)
|
void __might_fault(const char *file, int line)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Some code (nfs/sunrpc) uses socket ops on kernel memory while
|
|
||||||
* holding the mmap_lock, this is safe because kernel memory doesn't
|
|
||||||
* get paged out, therefore we'll never actually fault, and the
|
|
||||||
* below annotations will generate false positives.
|
|
||||||
*/
|
|
||||||
if (uaccess_kernel())
|
|
||||||
return;
|
|
||||||
if (pagefault_disabled())
|
if (pagefault_disabled())
|
||||||
return;
|
return;
|
||||||
__might_sleep(file, line);
|
__might_sleep(file, line);
|
||||||
|
@ -70,7 +70,7 @@ static int bpfilter_process_sockopt(struct sock *sk, int optname,
|
|||||||
.addr = (uintptr_t)optval.user,
|
.addr = (uintptr_t)optval.user,
|
||||||
.len = optlen,
|
.len = optlen,
|
||||||
};
|
};
|
||||||
if (uaccess_kernel() || sockptr_is_kernel(optval)) {
|
if (sockptr_is_kernel(optval)) {
|
||||||
pr_err("kernel access not supported\n");
|
pr_err("kernel access not supported\n");
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user