mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +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
|
||||
bool
|
||||
|
||||
config SET_FS
|
||||
bool
|
||||
|
||||
config HOTPLUG_SMT
|
||||
bool
|
||||
|
||||
|
@ -35,7 +35,6 @@ config ALPHA
|
||||
select OLD_SIGSUSPEND
|
||||
select CPU_NO_EFFICIENT_FFS if !ALPHA_EV67
|
||||
select MMU_GATHER_NO_RANGE
|
||||
select SET_FS
|
||||
select SPARSEMEM_EXTREME if SPARSEMEM
|
||||
select ZONE_DMA
|
||||
help
|
||||
|
@ -26,10 +26,6 @@
|
||||
#define TASK_UNMAPPED_BASE \
|
||||
((current->personality & ADDR_LIMIT_32BIT) ? 0x40000000 : TASK_SIZE / 2)
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/* This is dead. Everything has been moved to thread_info. */
|
||||
struct thread_struct { };
|
||||
#define INIT_THREAD { }
|
||||
|
@ -19,7 +19,6 @@ struct thread_info {
|
||||
unsigned int flags; /* low level flags */
|
||||
unsigned int ieee_state; /* see fpu.h */
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
unsigned cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
unsigned int status; /* thread-synchronous flags */
|
||||
@ -35,7 +34,6 @@ struct thread_info {
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
}
|
||||
|
||||
|
@ -2,26 +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))
|
||||
|
||||
#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.
|
||||
|
@ -45,7 +45,6 @@ config ARC
|
||||
select PCI_SYSCALL if PCI
|
||||
select PERF_USE_VMALLOC if ARC_CACHE_VIPT_ALIASING
|
||||
select HAVE_ARCH_JUMP_LABEL if ISA_ARCV2 && !CPU_ENDIAN_BE32
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
|
@ -1,20 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
|
||||
*/
|
||||
|
||||
#ifndef __ASMARC_SEGMENT_H
|
||||
#define __ASMARC_SEGMENT_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
|
||||
#define KERNEL_DS MAKE_MM_SEG(0)
|
||||
#define USER_DS MAKE_MM_SEG(TASK_SIZE)
|
||||
#define uaccess_kernel() (get_fs() == KERNEL_DS)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASMARC_SEGMENT_H */
|
@ -27,7 +27,6 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/thread_info.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to
|
||||
@ -40,7 +39,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
struct task_struct *task; /* main task structure */
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
__u32 cpu; /* current CPU */
|
||||
unsigned long thr_ptr; /* TLS ptr */
|
||||
};
|
||||
@ -56,7 +54,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
static inline __attribute_const__ struct thread_info *current_thread_info(void)
|
||||
|
@ -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)
|
||||
#endif
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
@ -519,7 +519,7 @@ void do_ptrauth_fault(struct pt_regs *regs, unsigned int esr)
|
||||
NOKPROBE_SYMBOL(do_ptrauth_fault);
|
||||
|
||||
#define __user_cache_maint(insn, address, res) \
|
||||
if (address >= user_addr_max()) { \
|
||||
if (address >= TASK_SIZE_MAX) { \
|
||||
res = -EFAULT; \
|
||||
} else { \
|
||||
uaccess_ttbr0_enable(); \
|
||||
|
@ -79,7 +79,6 @@ config CSKY
|
||||
select PCI_DOMAINS_GENERIC if PCI
|
||||
select PCI_SYSCALL if PCI
|
||||
select PCI_MSI if PCI
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config LOCKDEP_SUPPORT
|
||||
|
@ -4,7 +4,6 @@
|
||||
#define __ASM_CSKY_PROCESSOR_H
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/current.h>
|
||||
#include <asm/cache.h>
|
||||
@ -59,7 +58,6 @@ struct thread_struct {
|
||||
*/
|
||||
#define start_thread(_regs, _pc, _usp) \
|
||||
do { \
|
||||
set_fs(USER_DS); /* reads from user space */ \
|
||||
(_regs)->pc = (_pc); \
|
||||
(_regs)->regs[1] = 0; /* ABIV1 is R7, uClibc_main rtdl arg */ \
|
||||
(_regs)->regs[2] = 0; \
|
||||
|
@ -1,10 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __ASM_CSKY_SEGMENT_H
|
||||
#define __ASM_CSKY_SEGMENT_H
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#endif /* __ASM_CSKY_SEGMENT_H */
|
@ -16,7 +16,6 @@ struct thread_info {
|
||||
unsigned long flags;
|
||||
int preempt_count;
|
||||
unsigned long tp_value;
|
||||
mm_segment_t addr_limit;
|
||||
struct restart_block restart_block;
|
||||
struct pt_regs *regs;
|
||||
unsigned int cpu;
|
||||
@ -26,7 +25,6 @@ struct thread_info {
|
||||
{ \
|
||||
.task = &tsk, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.cpu = 0, \
|
||||
.restart_block = { \
|
||||
.fn = do_no_restart_syscall, \
|
||||
|
@ -3,8 +3,6 @@
|
||||
#ifndef __ASM_CSKY_UACCESS_H
|
||||
#define __ASM_CSKY_UACCESS_H
|
||||
|
||||
#define user_addr_max() (current_thread_info()->addr_limit.seg)
|
||||
|
||||
/*
|
||||
* __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);
|
||||
#define __clear_user __clear_user
|
||||
|
||||
#include <asm/segment.h>
|
||||
#include <asm-generic/uaccess.h>
|
||||
|
||||
#endif /* __ASM_CSKY_UACCESS_H */
|
||||
|
@ -25,7 +25,6 @@ int main(void)
|
||||
/* offsets into the thread_info struct */
|
||||
DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
|
||||
DEFINE(TINFO_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TINFO_TP_VALUE, offsetof(struct thread_info, tp_value));
|
||||
DEFINE(TINFO_TASK, offsetof(struct thread_info, task));
|
||||
|
||||
|
@ -24,7 +24,6 @@ config H8300
|
||||
select HAVE_ARCH_KGDB
|
||||
select HAVE_ARCH_HASH
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select SET_FS
|
||||
select UACCESS_MEMCPY
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
|
@ -13,7 +13,6 @@
|
||||
#define __ASM_H8300_PROCESSOR_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/current.h>
|
||||
|
||||
|
@ -1,40 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _H8300_SEGMENT_H
|
||||
#define _H8300_SEGMENT_H
|
||||
|
||||
/* define constants */
|
||||
#define USER_DATA (1)
|
||||
#ifndef __USER_DS
|
||||
#define __USER_DS (USER_DATA)
|
||||
#endif
|
||||
#define USER_PROGRAM (2)
|
||||
#define SUPER_DATA (3)
|
||||
#ifndef __KERNEL_DS
|
||||
#define __KERNEL_DS (SUPER_DATA)
|
||||
#endif
|
||||
#define SUPER_PROGRAM (4)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) })
|
||||
#define USER_DS MAKE_MM_SEG(__USER_DS)
|
||||
#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS)
|
||||
|
||||
/*
|
||||
* Get/set the SFC/DFC registers for MOVES instructions
|
||||
*/
|
||||
|
||||
static inline mm_segment_t get_fs(void)
|
||||
{
|
||||
return USER_DS;
|
||||
}
|
||||
|
||||
#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg)
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* _H8300_SEGMENT_H */
|
@ -10,7 +10,6 @@
|
||||
#define _ASM_THREAD_INFO_H
|
||||
|
||||
#include <asm/page.h>
|
||||
#include <asm/segment.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
@ -31,7 +30,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
int cpu; /* cpu we're on */
|
||||
int preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
mm_segment_t addr_limit;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -43,7 +41,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <linux/sys.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <linux/init.h>
|
||||
#include <asm/unistd.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/thread_info.h>
|
||||
|
@ -34,7 +34,6 @@
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
@ -71,11 +70,6 @@ void __init paging_init(void)
|
||||
panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
|
||||
__func__, PAGE_SIZE, PAGE_SIZE);
|
||||
|
||||
/*
|
||||
* Set up SFC/DFC registers (user data space).
|
||||
*/
|
||||
set_fs(USER_DS);
|
||||
|
||||
pr_debug("before free_area_init\n");
|
||||
|
||||
pr_debug("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/page.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/io.h>
|
||||
|
@ -30,7 +30,6 @@ config HEXAGON
|
||||
select GENERIC_CLOCKEVENTS_BROADCAST
|
||||
select MODULES_USE_ELF_RELA
|
||||
select GENERIC_CPU_DEVICES
|
||||
select SET_FS
|
||||
select ARCH_WANT_LD_ORPHAN_WARN
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
help
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/*
|
||||
* This is union'd with the "bottom" of the kernel stack.
|
||||
* It keeps track of thread info which is handy for routines
|
||||
@ -37,7 +33,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current cpu */
|
||||
int preempt_count; /* 0=>preemptible,<0=>BUG */
|
||||
mm_segment_t addr_limit; /* segmentation sux */
|
||||
/*
|
||||
* used for syscalls somehow;
|
||||
* seems to have a function pointer and four arguments
|
||||
@ -66,7 +61,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = 1, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.sp = 0, \
|
||||
.regs = NULL, \
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -42,7 +42,6 @@ config MICROBLAZE
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select MMU_GATHER_NO_RANGE
|
||||
select SPARSE_IRQ
|
||||
select SET_FS
|
||||
select ZONE_DMA
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
|
@ -56,17 +56,12 @@ struct cpu_context {
|
||||
__u32 fsr;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
unsigned long status; /* thread-synchronous flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
|
||||
struct cpu_context cpu_context;
|
||||
};
|
||||
@ -80,7 +75,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -15,30 +15,6 @@
|
||||
#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)
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
# define __FIXUP_SECTION ".section .fixup,\"ax\"\n"
|
||||
|
@ -86,7 +86,6 @@ int main(int argc, char *argv[])
|
||||
/* struct thread_info */
|
||||
DEFINE(TI_TASK, offsetof(struct thread_info, task));
|
||||
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
|
||||
DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
|
||||
DEFINE(TI_CPU_CONTEXT, offsetof(struct thread_info, cpu_context));
|
||||
DEFINE(TI_PREEMPT_COUNT, offsetof(struct thread_info, preempt_count));
|
||||
BLANK();
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/tick.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/uaccess.h> /* for USER_DS macros */
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
void show_regs(struct pt_regs *regs)
|
||||
|
@ -44,7 +44,6 @@ config NDS32
|
||||
select HAVE_FUNCTION_GRAPH_TRACER
|
||||
select HAVE_FTRACE_MCOUNT_RECORD
|
||||
select HAVE_DYNAMIC_FTRACE
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
help
|
||||
Andes(nds32) Linux support.
|
||||
|
@ -16,8 +16,6 @@ struct task_struct;
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/types.h>
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to.
|
||||
* __switch_to() assumes cpu_context follows immediately after cpu_domain.
|
||||
@ -25,12 +23,10 @@ typedef unsigned long mm_segment_t;
|
||||
struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__s32 preempt_count; /* 0 => preemptable, <0 => bug */
|
||||
mm_segment_t addr_limit; /* address limit */
|
||||
};
|
||||
#define INIT_THREAD_INFO(tsk) \
|
||||
{ \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
#define thread_saved_pc(tsk) ((unsigned long)(tsk->thread.cpu_context.pc))
|
||||
#define thread_saved_fp(tsk) ((unsigned long)(tsk->thread.cpu_context.fp))
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <asm/errno.h>
|
||||
#include <asm/memory.h>
|
||||
#include <asm/types.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
|
||||
|
||||
@ -33,20 +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
|
||||
#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
|
||||
* 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]);
|
||||
pr_info("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
|
||||
regs->uregs[3], regs->uregs[2], regs->uregs[1], regs->uregs[0]);
|
||||
pr_info(" IRQs o%s Segment %s\n",
|
||||
interrupts_enabled(regs) ? "n" : "ff",
|
||||
uaccess_kernel() ? "kernel" : "user");
|
||||
pr_info(" IRQs o%s Segment user\n",
|
||||
interrupts_enabled(regs) ? "n" : "ff");
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(show_regs);
|
||||
|
@ -512,7 +512,6 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long inst;
|
||||
int ret = -EFAULT;
|
||||
mm_segment_t seg;
|
||||
|
||||
inst = get_inst(regs->ipc);
|
||||
|
||||
@ -520,12 +519,10 @@ int do_unaligned_access(unsigned long addr, struct pt_regs *regs)
|
||||
"Faulting addr: 0x%08lx, pc: 0x%08lx [inst: 0x%08lx ]\n", addr,
|
||||
regs->ipc, inst);
|
||||
|
||||
seg = force_uaccess_begin();
|
||||
if (inst & NDS32_16BIT_INSTRUCTION)
|
||||
ret = do_16((inst >> 16) & 0xffff, regs);
|
||||
else
|
||||
ret = do_32(inst, regs);
|
||||
force_uaccess_end(seg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ config NIOS2
|
||||
select USB_ARCH_HAS_HCD if USB_SUPPORT
|
||||
select CPU_NO_EFFICIENT_FFS
|
||||
select MMU_GATHER_NO_RANGE if MMU
|
||||
select SET_FS
|
||||
|
||||
config GENERIC_CSUM
|
||||
def_bool y
|
||||
|
@ -26,10 +26,6 @@
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
/*
|
||||
* low level task data that entry.S needs immediate access to
|
||||
* - this struct should fit entirely inside of one cache line
|
||||
@ -42,10 +38,6 @@ struct thread_info {
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
int preempt_count; /* 0 => preemptable,<0 => BUG */
|
||||
mm_segment_t addr_limit; /* thread address space:
|
||||
0-0x7FFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
struct pt_regs *regs;
|
||||
};
|
||||
|
||||
@ -60,7 +52,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
}
|
||||
|
||||
/* how to get the thread information struct from C */
|
||||
|
@ -18,18 +18,6 @@
|
||||
#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))
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
# define __EX_TABLE_SECTION ".section __ex_table,\"a\"\n"
|
||||
|
@ -36,7 +36,6 @@ config OPENRISC
|
||||
select ARCH_WANT_FRAME_POINTERS
|
||||
select GENERIC_IRQ_MULTI_HANDLER
|
||||
select MMU_GATHER_NO_RANGE if MMU
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
|
||||
config CPU_BIG_ENDIAN
|
||||
|
@ -40,18 +40,12 @@
|
||||
*/
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
typedef unsigned long mm_segment_t;
|
||||
|
||||
struct thread_info {
|
||||
struct task_struct *task; /* main task structure */
|
||||
unsigned long flags; /* low level flags */
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable, <0 => BUG */
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space:
|
||||
0-0x7FFFFFFF for user-thead
|
||||
0-0xFFFFFFFF for kernel-thread
|
||||
*/
|
||||
__u8 supervisor_stack[0];
|
||||
|
||||
/* saved context data */
|
||||
@ -71,7 +65,6 @@ struct thread_info {
|
||||
.flags = 0, \
|
||||
.cpu = 0, \
|
||||
.preempt_count = INIT_PREEMPT_COUNT, \
|
||||
.addr_limit = KERNEL_DS, \
|
||||
.ksp = 0, \
|
||||
}
|
||||
|
||||
|
@ -22,29 +22,6 @@
|
||||
#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)
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
|
||||
|
@ -251,7 +251,7 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
|
||||
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
|
||||
|
||||
start = (unsigned long) frame;
|
||||
if (start >= user_addr_max() - sigframe_size)
|
||||
if (start >= TASK_SIZE_MAX - sigframe_size)
|
||||
return -EFAULT;
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
@ -518,7 +518,7 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
long err = 0;
|
||||
|
||||
/* check that we don't exceed the stack */
|
||||
if (A(&usp[0]) >= user_addr_max() - 5 * sizeof(int))
|
||||
if (A(&usp[0]) >= TASK_SIZE_MAX - 5 * sizeof(int))
|
||||
return;
|
||||
|
||||
/* Setup a trampoline to restart the syscall
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#define get_user_space() (uaccess_kernel() ? 0 : mfsp(3))
|
||||
#define get_user_space() (mfsp(3))
|
||||
#define get_kernel_space() (0)
|
||||
|
||||
/* Returns 0 for success, otherwise, returns number of bytes not transferred. */
|
||||
|
@ -58,7 +58,6 @@ config SPARC32
|
||||
select HAVE_UID16
|
||||
select OLD_SIGACTION
|
||||
select ZONE_DMA
|
||||
select SET_FS
|
||||
|
||||
config SPARC64
|
||||
def_bool 64BIT
|
||||
|
@ -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 \
|
||||
}
|
||||
|
||||
|
@ -12,19 +12,6 @@
|
||||
#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))
|
||||
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
|
@ -40,7 +40,6 @@ config XTENSA
|
||||
select IRQ_DOMAIN
|
||||
select MODULES_USE_ELF_RELA
|
||||
select PERF_USE_VMALLOC
|
||||
select SET_FS
|
||||
select TRACE_IRQFLAGS_SUPPORT
|
||||
select VIRT_TO_BUS
|
||||
help
|
||||
|
@ -23,76 +23,6 @@
|
||||
#include <asm/asm-offsets.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.
|
||||
* See the equivalent C-macro version below for clarity.
|
||||
@ -147,7 +77,6 @@
|
||||
* <at> destroyed
|
||||
*/
|
||||
.macro access_ok aa, as, at, sp, error
|
||||
kernel_ok \at, \sp, .Laccess_ok_\@
|
||||
user_ok \aa, \as, \at, \error
|
||||
.Laccess_ok_\@:
|
||||
.endm
|
||||
|
@ -152,18 +152,12 @@
|
||||
*/
|
||||
#define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg)))
|
||||
|
||||
typedef struct {
|
||||
unsigned long seg;
|
||||
} mm_segment_t;
|
||||
|
||||
struct thread_struct {
|
||||
|
||||
/* kernel's return address and stack pointer for context switching */
|
||||
unsigned long ra; /* kernel's a0: return address and window call size */
|
||||
unsigned long sp; /* kernel's a1: stack pointer */
|
||||
|
||||
mm_segment_t current_ds; /* see uaccess.h for example uses */
|
||||
|
||||
/* struct xtensa_cpuinfo info; */
|
||||
|
||||
unsigned long bad_vaddr; /* last user fault */
|
||||
@ -186,7 +180,6 @@ struct thread_struct {
|
||||
{ \
|
||||
ra: 0, \
|
||||
sp: sizeof(init_stack) + (long) &init_stack, \
|
||||
current_ds: {0}, \
|
||||
/*info: {0}, */ \
|
||||
bad_vaddr: 0, \
|
||||
bad_uaddr: 0, \
|
||||
|
@ -52,8 +52,6 @@ struct thread_info {
|
||||
__u32 cpu; /* current CPU */
|
||||
__s32 preempt_count; /* 0 => preemptable,< 0 => BUG*/
|
||||
|
||||
mm_segment_t addr_limit; /* thread address space */
|
||||
|
||||
unsigned long cpenable;
|
||||
#if XCHAL_HAVE_EXCLUSIVE
|
||||
/* result of the most recent exclusive store */
|
||||
@ -81,7 +79,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 */
|
||||
|
@ -19,22 +19,6 @@
|
||||
#include <linux/prefetch.h>
|
||||
#include <asm/types.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>
|
||||
|
||||
/*
|
||||
|
@ -87,7 +87,6 @@ int main(void)
|
||||
OFFSET(TI_STSTUS, thread_info, status);
|
||||
OFFSET(TI_CPU, thread_info, cpu);
|
||||
OFFSET(TI_PRE_COUNT, thread_info, preempt_count);
|
||||
OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit);
|
||||
|
||||
/* struct thread_info (offset from start_struct) */
|
||||
DEFINE(THREAD_RA, offsetof (struct task_struct, thread.ra));
|
||||
@ -108,8 +107,6 @@ int main(void)
|
||||
#endif
|
||||
DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user));
|
||||
DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t));
|
||||
DEFINE(THREAD_CURRENT_DS, offsetof (struct task_struct, \
|
||||
thread.current_ds));
|
||||
|
||||
/* struct mm_struct */
|
||||
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
|
||||
* 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",
|
||||
task_tgid_vnr(current), current->comm);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1303,12 +1303,6 @@ int begin_new_exec(struct linux_binprm * bprm)
|
||||
if (retval)
|
||||
goto out_unlock;
|
||||
|
||||
/*
|
||||
* Ensure that the uaccess routines can actually operate on userspace
|
||||
* pointers:
|
||||
*/
|
||||
force_uaccess_begin();
|
||||
|
||||
if (me->flags & PF_KTHREAD)
|
||||
free_kthread_struct(me);
|
||||
me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
|
||||
|
@ -16,18 +16,6 @@
|
||||
#define TASK_SIZE_MAX TASK_SIZE
|
||||
#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
|
||||
/*
|
||||
* '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)
|
||||
{
|
||||
unsigned long limit = user_addr_max();
|
||||
unsigned long limit = TASK_SIZE_MAX;
|
||||
unsigned long addr = (unsigned long)ptr;
|
||||
|
||||
if (IS_ENABLED(CONFIG_ALTERNATE_USER_ADDRESS_SPACE) ||
|
||||
|
@ -8,6 +8,7 @@
|
||||
* address space, e.g. all NOMMU machines.
|
||||
*/
|
||||
#include <linux/string.h>
|
||||
#include <asm-generic/access_ok.h>
|
||||
|
||||
#ifdef CONFIG_UACCESS_MEMCPY
|
||||
#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
|
||||
#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
|
||||
* 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;
|
||||
#endif
|
||||
|
||||
if (CHECK_DATA_CORRUPTION(uaccess_kernel(),
|
||||
"Invalid address limit on user-mode return"))
|
||||
force_sig(SIGKILL);
|
||||
|
||||
#ifdef TIF_FSCHECK
|
||||
clear_thread_flag(TIF_FSCHECK);
|
||||
#endif
|
||||
|
@ -10,39 +10,6 @@
|
||||
|
||||
#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())
|
||||
* 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)
|
||||
{
|
||||
return filp->f_cred == current_cred() && !uaccess_kernel();
|
||||
return filp->f_cred == current_cred();
|
||||
}
|
||||
|
||||
#endif /* _RDMA_IB_H */
|
||||
|
@ -209,17 +209,13 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
|
||||
}
|
||||
|
||||
if (regs) {
|
||||
mm_segment_t fs;
|
||||
|
||||
if (crosstask)
|
||||
goto exit_put;
|
||||
|
||||
if (add_mark)
|
||||
perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
|
||||
|
||||
fs = force_uaccess_begin();
|
||||
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 int rem;
|
||||
u64 dyn_size;
|
||||
mm_segment_t fs;
|
||||
|
||||
/*
|
||||
* We dump:
|
||||
@ -6764,9 +6763,7 @@ perf_output_sample_ustack(struct perf_output_handle *handle, u64 dump_size,
|
||||
|
||||
/* Data. */
|
||||
sp = perf_user_stack_pointer(regs);
|
||||
fs = force_uaccess_begin();
|
||||
rem = __output_copy_user(handle, (void *) sp, dump_size);
|
||||
force_uaccess_end(fs);
|
||||
dyn_size = dump_size - rem;
|
||||
|
||||
perf_output_skip(handle, rem);
|
||||
|
@ -737,20 +737,6 @@ void __noreturn do_exit(long code)
|
||||
|
||||
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);
|
||||
|
||||
coredump_task_exit(tsk);
|
||||
|
@ -55,7 +55,6 @@ struct kthread {
|
||||
int result;
|
||||
int (*threadfn)(void *);
|
||||
void *data;
|
||||
mm_segment_t oldfs;
|
||||
struct completion parked;
|
||||
struct completion exited;
|
||||
#ifdef CONFIG_BLK_CGROUP
|
||||
@ -1441,8 +1440,6 @@ void kthread_use_mm(struct mm_struct *mm)
|
||||
mmdrop(active_mm);
|
||||
else
|
||||
smp_mb();
|
||||
|
||||
to_kthread(tsk)->oldfs = force_uaccess_begin();
|
||||
}
|
||||
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->mm);
|
||||
|
||||
force_uaccess_end(to_kthread(tsk)->oldfs);
|
||||
|
||||
task_lock(tsk);
|
||||
/*
|
||||
* 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,
|
||||
.size = size,
|
||||
};
|
||||
mm_segment_t fs;
|
||||
|
||||
/* Trace user stack if not a kernel thread */
|
||||
if (current->flags & PF_KTHREAD)
|
||||
return 0;
|
||||
|
||||
fs = force_uaccess_begin();
|
||||
arch_stack_walk_user(consume_entry, &c, task_pt_regs(current));
|
||||
force_uaccess_end(fs);
|
||||
|
||||
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() ||
|
||||
current->flags & (PF_KTHREAD | PF_EXITING)))
|
||||
return -EPERM;
|
||||
if (unlikely(uaccess_kernel()))
|
||||
return -EPERM;
|
||||
if (unlikely(!nmi_uaccess_okay()))
|
||||
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)))
|
||||
return -EPERM;
|
||||
if (unlikely(uaccess_kernel()))
|
||||
return -EPERM;
|
||||
if (unlikely(!nmi_uaccess_okay()))
|
||||
return -EPERM;
|
||||
|
||||
|
@ -120,7 +120,7 @@ long strncpy_from_user(char *dst, const char __user *src, long count)
|
||||
if (unlikely(count <= 0))
|
||||
return 0;
|
||||
|
||||
max_addr = user_addr_max();
|
||||
max_addr = TASK_SIZE_MAX;
|
||||
src_addr = (unsigned long)untagged_addr(src);
|
||||
if (likely(src_addr < max_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))
|
||||
return 0;
|
||||
|
||||
max_addr = user_addr_max();
|
||||
max_addr = TASK_SIZE_MAX;
|
||||
src_addr = (unsigned long)untagged_addr(str);
|
||||
if (likely(src_addr < max_addr)) {
|
||||
unsigned long max = max_addr - src_addr;
|
||||
|
11
mm/maccess.c
11
mm/maccess.c
@ -113,14 +113,11 @@ long strncpy_from_kernel_nofault(char *dst, const void *unsafe_addr, long count)
|
||||
long copy_from_user_nofault(void *dst, const void __user *src, size_t size)
|
||||
{
|
||||
long ret = -EFAULT;
|
||||
mm_segment_t old_fs = force_uaccess_begin();
|
||||
|
||||
if (access_ok(src, size)) {
|
||||
pagefault_disable();
|
||||
ret = __copy_from_user_inatomic(dst, src, size);
|
||||
pagefault_enable();
|
||||
}
|
||||
force_uaccess_end(old_fs);
|
||||
|
||||
if (ret)
|
||||
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 ret = -EFAULT;
|
||||
mm_segment_t old_fs = force_uaccess_begin();
|
||||
|
||||
if (access_ok(dst, size)) {
|
||||
pagefault_disable();
|
||||
ret = __copy_to_user_inatomic(dst, src, size);
|
||||
pagefault_enable();
|
||||
}
|
||||
force_uaccess_end(old_fs);
|
||||
|
||||
if (ret)
|
||||
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 count)
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
long ret;
|
||||
|
||||
if (unlikely(count <= 0))
|
||||
return 0;
|
||||
|
||||
old_fs = force_uaccess_begin();
|
||||
pagefault_disable();
|
||||
ret = strncpy_from_user(dst, unsafe_addr, count);
|
||||
pagefault_enable();
|
||||
force_uaccess_end(old_fs);
|
||||
|
||||
if (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)
|
||||
{
|
||||
mm_segment_t old_fs;
|
||||
int ret;
|
||||
|
||||
old_fs = force_uaccess_begin();
|
||||
pagefault_disable();
|
||||
ret = strnlen_user(unsafe_addr, count);
|
||||
pagefault_enable();
|
||||
force_uaccess_end(old_fs);
|
||||
|
||||
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)
|
||||
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())
|
||||
return;
|
||||
__might_sleep(file, line);
|
||||
|
@ -70,7 +70,7 @@ static int bpfilter_process_sockopt(struct sock *sk, int optname,
|
||||
.addr = (uintptr_t)optval.user,
|
||||
.len = optlen,
|
||||
};
|
||||
if (uaccess_kernel() || sockptr_is_kernel(optval)) {
|
||||
if (sockptr_is_kernel(optval)) {
|
||||
pr_err("kernel access not supported\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user