Commit a97f52e6 authored by Roland McGrath's avatar Roland McGrath Committed by Ingo Molnar

x86: compat_binfmt_elf

This switches x86-64's 32-bit ELF support to use the shared
fs/compat_binfmt_elf.c code instead of our own ia32_binfmt.c.
Signed-off-by: default avatarRoland McGrath <roland@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 60b3b9af
...@@ -1532,6 +1532,7 @@ source "fs/Kconfig.binfmt" ...@@ -1532,6 +1532,7 @@ source "fs/Kconfig.binfmt"
config IA32_EMULATION config IA32_EMULATION
bool "IA32 Emulation" bool "IA32 Emulation"
depends on X86_64 depends on X86_64
select COMPAT_BINFMT_ELF
help help
Include code to run 32-bit programs under a 64-bit kernel. You should Include code to run 32-bit programs under a 64-bit kernel. You should
likely turn this on, unless you're 100% sure that you don't have any likely turn this on, unless you're 100% sure that you don't have any
......
...@@ -2,8 +2,7 @@ ...@@ -2,8 +2,7 @@
# Makefile for the ia32 kernel emulation subsystem. # Makefile for the ia32 kernel emulation subsystem.
# #
obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o \ obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o
ia32_binfmt.o
sysv-$(CONFIG_SYSVIPC) := ipc32.o sysv-$(CONFIG_SYSVIPC) := ipc32.o
obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) obj-$(CONFIG_IA32_EMULATION) += $(sysv-y)
......
...@@ -377,6 +377,39 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack) ...@@ -377,6 +377,39 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int exstack)
__initcall(sysenter_setup); __initcall(sysenter_setup);
#ifdef CONFIG_SYSCTL
/* Register vsyscall32 into the ABI table */
#include <linux/sysctl.h>
static ctl_table abi_table2[] = {
{
.procname = "vsyscall32",
.data = &sysctl_vsyscall32,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec
},
{}
};
static ctl_table abi_root_table2[] = {
{
.ctl_name = CTL_ABI,
.procname = "abi",
.mode = 0555,
.child = abi_table2
},
{}
};
static __init int ia32_binfmt_init(void)
{
register_sysctl_table(abi_root_table2);
return 0;
}
__initcall(ia32_binfmt_init);
#endif
#else /* CONFIG_X86_32 */ #else /* CONFIG_X86_32 */
const char *arch_vma_name(struct vm_area_struct *vma) const char *arch_vma_name(struct vm_area_struct *vma)
......
...@@ -73,6 +73,9 @@ typedef struct user_fxsr_struct elf_fpxregset_t; ...@@ -73,6 +73,9 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
#endif #endif
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <asm/vdso.h>
extern unsigned int vdso_enabled;
/* /*
* This is used to ensure we don't load something for the wrong architecture. * This is used to ensure we don't load something for the wrong architecture.
...@@ -84,7 +87,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t; ...@@ -84,7 +87,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/system.h> /* for savesegment */ #include <asm/system.h> /* for savesegment */
#include <asm/desc.h> #include <asm/desc.h>
#include <asm/vdso.h>
#define elf_check_arch(x) elf_check_arch_ia32(x) #define elf_check_arch(x) elf_check_arch_ia32(x)
...@@ -106,7 +108,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t; ...@@ -106,7 +108,6 @@ typedef struct user_fxsr_struct elf_fpxregset_t;
#define ELF_PLATFORM (utsname()->machine) #define ELF_PLATFORM (utsname()->machine)
#define set_personality_64bit() do { } while (0) #define set_personality_64bit() do { } while (0)
extern unsigned int vdso_enabled;
#else /* CONFIG_X86_32 */ #else /* CONFIG_X86_32 */
...@@ -118,29 +119,57 @@ extern unsigned int vdso_enabled; ...@@ -118,29 +119,57 @@ extern unsigned int vdso_enabled;
#define elf_check_arch(x) \ #define elf_check_arch(x) \
((x)->e_machine == EM_X86_64) ((x)->e_machine == EM_X86_64)
#define compat_elf_check_arch(x) elf_check_arch_ia32(x)
static inline void start_ia32_thread(struct pt_regs *regs, u32 ip, u32 sp)
{
asm volatile("movl %0,%%fs" :: "r" (0));
asm volatile("movl %0,%%es; movl %0,%%ds" : : "r" (__USER32_DS));
load_gs_index(0);
regs->ip = ip;
regs->sp = sp;
regs->flags = X86_EFLAGS_IF;
regs->cs = __USER32_CS;
regs->ss = __USER32_DS;
}
static inline void elf_common_init(struct thread_struct *t,
struct pt_regs *regs, const u16 ds)
{
regs->ax = regs->bx = regs->cx = regs->dx = 0;
regs->si = regs->di = regs->bp = 0;
regs->r8 = regs->r9 = regs->r10 = regs->r11 = 0;
regs->r12 = regs->r13 = regs->r14 = regs->r15 = 0;
t->fs = t->gs = 0;
t->fsindex = t->gsindex = 0;
t->ds = t->es = ds;
}
#define ELF_PLAT_INIT(_r, load_addr) do { \ #define ELF_PLAT_INIT(_r, load_addr) do { \
struct task_struct *cur = current; \ elf_common_init(&current->thread, _r, 0); \
(_r)->bx = 0; (_r)->cx = 0; (_r)->dx = 0; \
(_r)->si = 0; (_r)->di = 0; (_r)->bp = 0; \
(_r)->ax = 0; \
(_r)->r8 = 0; \
(_r)->r9 = 0; \
(_r)->r10 = 0; \
(_r)->r11 = 0; \
(_r)->r12 = 0; \
(_r)->r13 = 0; \
(_r)->r14 = 0; \
(_r)->r15 = 0; \
cur->thread.fs = 0; cur->thread.gs = 0; \
cur->thread.fsindex = 0; cur->thread.gsindex = 0; \
cur->thread.ds = 0; cur->thread.es = 0; \
clear_thread_flag(TIF_IA32); \ clear_thread_flag(TIF_IA32); \
} while (0) } while (0)
#define COMPAT_ELF_PLAT_INIT(regs, load_addr) \
elf_common_init(&current->thread, regs, __USER_DS)
#define compat_start_thread(regs, ip, sp) do { \
start_ia32_thread(regs, ip, sp); \
set_fs(USER_DS); \
} while (0)
#define COMPAT_SET_PERSONALITY(ex, ibcs2) do { \
if (test_thread_flag(TIF_IA32)) \
clear_thread_flag(TIF_ABI_PENDING); \
else \
set_thread_flag(TIF_ABI_PENDING); \
current->personality |= force_personality32; \
} while (0)
#define COMPAT_ELF_PLATFORM ("i686")
/* I'm not sure if we can use '-' here */ /* I'm not sure if we can use '-' here */
#define ELF_PLATFORM ("x86_64") #define ELF_PLATFORM ("x86_64")
extern void set_personality_64bit(void); extern void set_personality_64bit(void);
extern int vdso_enabled; extern unsigned int sysctl_vsyscall32;
extern int force_personality32;
#endif /* !CONFIG_X86_32 */ #endif /* !CONFIG_X86_32 */
...@@ -179,17 +208,19 @@ extern int vdso_enabled; ...@@ -179,17 +208,19 @@ extern int vdso_enabled;
struct task_struct; struct task_struct;
#define ARCH_DLINFO_IA32(vdso_enabled) \
do if (vdso_enabled) { \
NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
} while (0)
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
#define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO)) #define VDSO_HIGH_BASE (__fix_to_virt(FIX_VDSO))
/* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ #define ARCH_DLINFO ARCH_DLINFO_IA32(vdso_enabled)
#define ARCH_DLINFO \ /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */
do if (vdso_enabled) { \
NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \
NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \
} while (0)
#else /* CONFIG_X86_32 */ #else /* CONFIG_X86_32 */
...@@ -203,6 +234,12 @@ do if (vdso_enabled) { \ ...@@ -203,6 +234,12 @@ do if (vdso_enabled) { \
NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\ NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\
} while (0) } while (0)
#define AT_SYSINFO 32
#define COMPAT_ARCH_DLINFO ARCH_DLINFO_IA32(sysctl_vsyscall32)
#define COMPAT_ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
#endif /* !CONFIG_X86_32 */ #endif /* !CONFIG_X86_32 */
#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso) #define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso)
...@@ -216,6 +253,9 @@ struct linux_binprm; ...@@ -216,6 +253,9 @@ struct linux_binprm;
extern int arch_setup_additional_pages(struct linux_binprm *bprm, extern int arch_setup_additional_pages(struct linux_binprm *bprm,
int executable_stack); int executable_stack);
extern int syscall32_setup_pages(struct linux_binprm *, int exstack);
#define compat_arch_setup_additional_pages syscall32_setup_pages
extern unsigned long arch_randomize_brk(struct mm_struct *mm); extern unsigned long arch_randomize_brk(struct mm_struct *mm);
#define arch_randomize_brk arch_randomize_brk #define arch_randomize_brk arch_randomize_brk
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment