forked from Minki/linux
Merge branch 'x86/entry' into core/entry
Prepare for the merging of the syscall_work series which conflicts with the TIF bits overhaul in X86.
This commit is contained in:
commit
4cffe21d4a
@ -413,10 +413,10 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
int uses_interp)
|
||||
int uses_interp, bool x32)
|
||||
{
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
if (test_thread_flag(TIF_X32)) {
|
||||
if (x32) {
|
||||
if (!vdso64_enabled)
|
||||
return 0;
|
||||
return map_vdso_randomized(&vdso_image_x32);
|
||||
|
@ -316,7 +316,7 @@ static struct vm_area_struct gate_vma __ro_after_init = {
|
||||
struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
|
||||
{
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (!mm || mm->context.ia32_compat)
|
||||
if (!mm || !(mm->context.flags & MM_CONTEXT_HAS_VSYSCALL))
|
||||
return NULL;
|
||||
#endif
|
||||
if (vsyscall_mode == NONE)
|
||||
|
@ -2602,7 +2602,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry_ctx *ent
|
||||
struct stack_frame_ia32 frame;
|
||||
const struct stack_frame_ia32 __user *fp;
|
||||
|
||||
if (!test_thread_flag(TIF_IA32))
|
||||
if (user_64bit_mode(regs))
|
||||
return 0;
|
||||
|
||||
cs_base = get_segment_base(regs->cs);
|
||||
|
@ -1259,7 +1259,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
|
||||
old_to = to;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
|
||||
is_64bit = kernel_ip(to) || any_64bit_mode(regs);
|
||||
#endif
|
||||
insn_init(&insn, kaddr, size, is_64bit);
|
||||
insn_get_length(&insn);
|
||||
|
@ -1221,7 +1221,7 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
|
||||
* on 64-bit systems running 32-bit apps
|
||||
*/
|
||||
#ifdef CONFIG_X86_64
|
||||
is64 = kernel_ip((unsigned long)addr) || !test_thread_flag(TIF_IA32);
|
||||
is64 = kernel_ip((unsigned long)addr) || any_64bit_mode(current_pt_regs());
|
||||
#endif
|
||||
insn_init(&insn, addr, bytes_read, is64);
|
||||
insn_get_opcode(&insn);
|
||||
|
@ -177,14 +177,13 @@ typedef struct user_regs_struct compat_elf_gregset_t;
|
||||
|
||||
static inline void __user *arch_compat_alloc_user_space(long len)
|
||||
{
|
||||
compat_uptr_t sp;
|
||||
compat_uptr_t sp = task_pt_regs(current)->sp;
|
||||
|
||||
if (test_thread_flag(TIF_IA32)) {
|
||||
sp = task_pt_regs(current)->sp;
|
||||
} else {
|
||||
/* -128 for the x32 ABI redzone */
|
||||
sp = task_pt_regs(current)->sp - 128;
|
||||
}
|
||||
/*
|
||||
* -128 for the x32 ABI redzone. For IA32, it is not strictly
|
||||
* necessary, but not harmful.
|
||||
*/
|
||||
sp -= 128;
|
||||
|
||||
return (void __user *)round_down(sp - len, 16);
|
||||
}
|
||||
|
@ -186,8 +186,9 @@ static inline void elf_common_init(struct thread_struct *t,
|
||||
#define COMPAT_ELF_PLAT_INIT(regs, load_addr) \
|
||||
elf_common_init(¤t->thread, regs, __USER_DS)
|
||||
|
||||
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp);
|
||||
#define compat_start_thread compat_start_thread
|
||||
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp, bool x32);
|
||||
#define COMPAT_START_THREAD(ex, regs, new_ip, new_sp) \
|
||||
compat_start_thread(regs, new_ip, new_sp, ex->e_machine == EM_X86_64)
|
||||
|
||||
void set_personality_ia32(bool);
|
||||
#define COMPAT_SET_PERSONALITY(ex) \
|
||||
@ -361,7 +362,7 @@ do { \
|
||||
#define AT_SYSINFO 32
|
||||
|
||||
#define COMPAT_ARCH_DLINFO \
|
||||
if (test_thread_flag(TIF_X32)) \
|
||||
if (exec->e_machine == EM_X86_64) \
|
||||
ARCH_DLINFO_X32; \
|
||||
else \
|
||||
ARCH_DLINFO_IA32
|
||||
@ -382,8 +383,10 @@ struct linux_binprm;
|
||||
extern int arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
int uses_interp);
|
||||
extern int compat_arch_setup_additional_pages(struct linux_binprm *bprm,
|
||||
int uses_interp);
|
||||
#define compat_arch_setup_additional_pages compat_arch_setup_additional_pages
|
||||
int uses_interp, bool x32);
|
||||
#define COMPAT_ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
|
||||
compat_arch_setup_additional_pages(bprm, interpreter, \
|
||||
(ex->e_machine == EM_X86_64))
|
||||
|
||||
/* Do not change the values. See get_align_mask() */
|
||||
enum align_flags {
|
||||
|
@ -6,6 +6,12 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
/* Uprobes on this MM assume 32-bit code */
|
||||
#define MM_CONTEXT_UPROBE_IA32 BIT(0)
|
||||
/* vsyscall page is accessible on this MM */
|
||||
#define MM_CONTEXT_HAS_VSYSCALL BIT(1)
|
||||
|
||||
/*
|
||||
* x86 has arch-specific MMU state beyond what lives in mm_struct.
|
||||
@ -33,8 +39,7 @@ typedef struct {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
/* True if mm supports a task running in 32 bit compatibility mode. */
|
||||
unsigned short ia32_compat;
|
||||
unsigned short flags;
|
||||
#endif
|
||||
|
||||
struct mutex lock;
|
||||
|
@ -177,7 +177,7 @@ static inline void arch_exit_mmap(struct mm_struct *mm)
|
||||
static inline bool is_64bit_mm(struct mm_struct *mm)
|
||||
{
|
||||
return !IS_ENABLED(CONFIG_IA32_EMULATION) ||
|
||||
!(mm->context.ia32_compat == TIF_IA32);
|
||||
!(mm->context.flags & MM_CONTEXT_UPROBE_IA32);
|
||||
}
|
||||
#else
|
||||
static inline bool is_64bit_mm(struct mm_struct *mm)
|
||||
|
@ -91,7 +91,7 @@ struct thread_info {
|
||||
#define TIF_NEED_FPU_LOAD 14 /* load FPU on return to userspace */
|
||||
#define TIF_NOCPUID 15 /* CPUID is not accessible in userland */
|
||||
#define TIF_NOTSC 16 /* TSC is not accessible in userland */
|
||||
#define TIF_IA32 17 /* IA32 compatibility process */
|
||||
#define TIF_NOTIFY_SIGNAL 17 /* signal notifications exist */
|
||||
#define TIF_SLD 18 /* Restore split lock detection on context switch */
|
||||
#define TIF_MEMDIE 20 /* is terminating due to OOM killer */
|
||||
#define TIF_POLLING_NRFLAG 21 /* idle is polling for TIF_NEED_RESCHED */
|
||||
@ -101,7 +101,6 @@ struct thread_info {
|
||||
#define TIF_LAZY_MMU_UPDATES 27 /* task is updating the mmu lazily */
|
||||
#define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */
|
||||
#define TIF_ADDR32 29 /* 32-bit address space on 64 bits */
|
||||
#define TIF_X32 30 /* 32-bit native x86-64 binary */
|
||||
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
|
||||
@ -120,7 +119,7 @@ struct thread_info {
|
||||
#define _TIF_NEED_FPU_LOAD (1 << TIF_NEED_FPU_LOAD)
|
||||
#define _TIF_NOCPUID (1 << TIF_NOCPUID)
|
||||
#define _TIF_NOTSC (1 << TIF_NOTSC)
|
||||
#define _TIF_IA32 (1 << TIF_IA32)
|
||||
#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL)
|
||||
#define _TIF_SLD (1 << TIF_SLD)
|
||||
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
||||
#define _TIF_IO_BITMAP (1 << TIF_IO_BITMAP)
|
||||
@ -129,7 +128,6 @@ struct thread_info {
|
||||
#define _TIF_LAZY_MMU_UPDATES (1 << TIF_LAZY_MMU_UPDATES)
|
||||
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
|
||||
#define _TIF_ADDR32 (1 << TIF_ADDR32)
|
||||
#define _TIF_X32 (1 << TIF_X32)
|
||||
|
||||
/* flags to check in __switch_to() */
|
||||
#define _TIF_WORK_CTXSW_BASE \
|
||||
|
@ -123,7 +123,7 @@ int perf_reg_validate(u64 mask)
|
||||
|
||||
u64 perf_reg_abi(struct task_struct *task)
|
||||
{
|
||||
if (test_tsk_thread_flag(task, TIF_IA32))
|
||||
if (!user_64bit_mode(task_pt_regs(task)))
|
||||
return PERF_SAMPLE_REGS_ABI_32;
|
||||
else
|
||||
return PERF_SAMPLE_REGS_ABI_64;
|
||||
|
@ -511,11 +511,10 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
|
||||
EXPORT_SYMBOL_GPL(start_thread);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp)
|
||||
void compat_start_thread(struct pt_regs *regs, u32 new_ip, u32 new_sp, bool x32)
|
||||
{
|
||||
start_thread_common(regs, new_ip, new_sp,
|
||||
test_thread_flag(TIF_X32)
|
||||
? __USER_CS : __USER32_CS,
|
||||
x32 ? __USER_CS : __USER32_CS,
|
||||
__USER_DS, __USER_DS);
|
||||
}
|
||||
#endif
|
||||
@ -641,16 +640,12 @@ void set_personality_64bit(void)
|
||||
/* inherit personality from parent */
|
||||
|
||||
/* Make sure to be in 64bit mode */
|
||||
clear_thread_flag(TIF_IA32);
|
||||
clear_thread_flag(TIF_ADDR32);
|
||||
clear_thread_flag(TIF_X32);
|
||||
/* Pretend that this comes from a 64bit execve */
|
||||
task_pt_regs(current)->orig_ax = __NR_execve;
|
||||
current_thread_info()->status &= ~TS_COMPAT;
|
||||
|
||||
/* Ensure the corresponding mm is not marked. */
|
||||
if (current->mm)
|
||||
current->mm->context.ia32_compat = 0;
|
||||
current->mm->context.flags = MM_CONTEXT_HAS_VSYSCALL;
|
||||
|
||||
/* TBD: overwrites user setup. Should have two bits.
|
||||
But 64bit processes have always behaved this way,
|
||||
@ -662,10 +657,9 @@ void set_personality_64bit(void)
|
||||
static void __set_personality_x32(void)
|
||||
{
|
||||
#ifdef CONFIG_X86_X32
|
||||
clear_thread_flag(TIF_IA32);
|
||||
set_thread_flag(TIF_X32);
|
||||
if (current->mm)
|
||||
current->mm->context.ia32_compat = TIF_X32;
|
||||
current->mm->context.flags = 0;
|
||||
|
||||
current->personality &= ~READ_IMPLIES_EXEC;
|
||||
/*
|
||||
* in_32bit_syscall() uses the presence of the x32 syscall bit
|
||||
@ -683,10 +677,14 @@ static void __set_personality_x32(void)
|
||||
static void __set_personality_ia32(void)
|
||||
{
|
||||
#ifdef CONFIG_IA32_EMULATION
|
||||
set_thread_flag(TIF_IA32);
|
||||
clear_thread_flag(TIF_X32);
|
||||
if (current->mm)
|
||||
current->mm->context.ia32_compat = TIF_IA32;
|
||||
if (current->mm) {
|
||||
/*
|
||||
* uprobes applied to this MM need to know this and
|
||||
* cannot use user_64bit_mode() at that time.
|
||||
*/
|
||||
current->mm->context.flags = MM_CONTEXT_UPROBE_IA32;
|
||||
}
|
||||
|
||||
current->personality |= force_personality32;
|
||||
/* Prepare the first "return" to user space */
|
||||
task_pt_regs(current)->orig_ax = __NR_ia32_execve;
|
||||
|
@ -49,7 +49,7 @@ x86_backtrace_32(struct pt_regs * const regs, unsigned int depth)
|
||||
struct stack_frame_ia32 *head;
|
||||
|
||||
/* User process is IA32 */
|
||||
if (!current || !test_thread_flag(TIF_IA32))
|
||||
if (!current || user_64bit_mode(regs))
|
||||
return 0;
|
||||
|
||||
head = (struct stack_frame_ia32 *) regs->bp;
|
||||
|
@ -1246,7 +1246,7 @@ out_free_interp:
|
||||
set_binfmt(&elf_format);
|
||||
|
||||
#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||
retval = arch_setup_additional_pages(bprm, !!interpreter);
|
||||
retval = ARCH_SETUP_ADDITIONAL_PAGES(bprm, elf_ex, !!interpreter);
|
||||
if (retval < 0)
|
||||
goto out;
|
||||
#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
|
||||
@ -1307,7 +1307,7 @@ out_free_interp:
|
||||
#endif
|
||||
|
||||
finalize_exec(bprm);
|
||||
start_thread(regs, elf_entry, bprm->p);
|
||||
START_THREAD(elf_ex, regs, elf_entry, bprm->p);
|
||||
retval = 0;
|
||||
out:
|
||||
return retval;
|
||||
|
@ -106,15 +106,25 @@
|
||||
#endif
|
||||
|
||||
#ifdef compat_start_thread
|
||||
#undef start_thread
|
||||
#define start_thread compat_start_thread
|
||||
#define COMPAT_START_THREAD(ex, regs, new_ip, new_sp) \
|
||||
compat_start_thread(regs, new_ip, new_sp)
|
||||
#endif
|
||||
|
||||
#ifdef compat_arch_setup_additional_pages
|
||||
#ifdef COMPAT_START_THREAD
|
||||
#undef START_THREAD
|
||||
#define START_THREAD COMPAT_START_THREAD
|
||||
#endif
|
||||
|
||||
#ifdef compat_arch_setup_additional_pages
|
||||
#define COMPAT_ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
|
||||
compat_arch_setup_additional_pages(bprm, interpreter)
|
||||
#endif
|
||||
|
||||
#ifdef COMPAT_ARCH_SETUP_ADDITIONAL_PAGES
|
||||
#undef ARCH_HAS_SETUP_ADDITIONAL_PAGES
|
||||
#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1
|
||||
#undef arch_setup_additional_pages
|
||||
#define arch_setup_additional_pages compat_arch_setup_additional_pages
|
||||
#undef ARCH_SETUP_ADDITIONAL_PAGES
|
||||
#define ARCH_SETUP_ADDITIONAL_PAGES COMPAT_ARCH_SETUP_ADDITIONAL_PAGES
|
||||
#endif
|
||||
|
||||
#ifdef compat_elf_read_implies_exec
|
||||
|
@ -22,6 +22,16 @@
|
||||
SET_PERSONALITY(ex)
|
||||
#endif
|
||||
|
||||
#ifndef START_THREAD
|
||||
#define START_THREAD(elf_ex, regs, elf_entry, start_stack) \
|
||||
start_thread(regs, elf_entry, start_stack)
|
||||
#endif
|
||||
|
||||
#if defined(ARCH_HAS_SETUP_ADDITIONAL_PAGES) && !defined(ARCH_SETUP_ADDITIONAL_PAGES)
|
||||
#define ARCH_SETUP_ADDITIONAL_PAGES(bprm, ex, interpreter) \
|
||||
arch_setup_additional_pages(bprm, interpreter)
|
||||
#endif
|
||||
|
||||
#define ELF32_GNU_PROPERTY_ALIGN 4
|
||||
#define ELF64_GNU_PROPERTY_ALIGN 8
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user