diff options
Diffstat (limited to 'arch/x86/ia32')
| -rw-r--r-- | arch/x86/ia32/Makefile | 4 | ||||
| -rw-r--r-- | arch/x86/ia32/ia32_aout.c | 183 | ||||
| -rw-r--r-- | arch/x86/ia32/ia32_signal.c | 191 | ||||
| -rw-r--r-- | arch/x86/ia32/ia32entry.S | 486 | ||||
| -rw-r--r-- | arch/x86/ia32/ipc32.c | 54 | ||||
| -rw-r--r-- | arch/x86/ia32/nosyscall.c | 7 | ||||
| -rw-r--r-- | arch/x86/ia32/sys_ia32.c | 320 | ||||
| -rw-r--r-- | arch/x86/ia32/syscall_ia32.c | 25 | 
8 files changed, 235 insertions, 1035 deletions
diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile index 52d0ccfcf6e..e785b422b76 100644 --- a/arch/x86/ia32/Makefile +++ b/arch/x86/ia32/Makefile @@ -3,9 +3,7 @@  #  obj-$(CONFIG_IA32_EMULATION) := ia32entry.o sys_ia32.o ia32_signal.o - -sysv-$(CONFIG_SYSVIPC) := ipc32.o -obj-$(CONFIG_IA32_EMULATION) += $(sysv-y) +obj-$(CONFIG_IA32_EMULATION) += nosyscall.o syscall_ia32.o  obj-$(CONFIG_IA32_AOUT) += ia32_aout.o diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 2d93bdbc9ac..d21ff89207c 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c @@ -25,8 +25,8 @@  #include <linux/personality.h>  #include <linux/init.h>  #include <linux/jiffies.h> +#include <linux/perf_event.h> -#include <asm/system.h>  #include <asm/uaccess.h>  #include <asm/pgalloc.h>  #include <asm/cacheflush.h> @@ -34,14 +34,18 @@  #include <asm/ia32.h>  #undef WARN_OLD -#undef CORE_DUMP /* definitely broken */ -static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); +static int load_aout_binary(struct linux_binprm *);  static int load_aout_library(struct file *); -#ifdef CORE_DUMP -static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, -			  unsigned long limit); +#ifdef CONFIG_COREDUMP +static int aout_core_dump(struct coredump_params *); + +static unsigned long get_dr(int n) +{ +	struct perf_event *bp = current->thread.ptrace_bps[n]; +	return bp ? bp->hw.info.address : 0; +}  /*   * fill in the user structure for a core dump.. @@ -49,6 +53,7 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,  static void dump_thread32(struct pt_regs *regs, struct user32 *dump)  {  	u32 fs, gs; +	memset(dump, 0, sizeof(*dump));  /* changed the size calculations - should hopefully work better. lbt */  	dump->magic = CMAGIC; @@ -58,15 +63,12 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)  	dump->u_dsize = ((unsigned long)  			 (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;  	dump->u_dsize -= dump->u_tsize; -	dump->u_ssize = 0; -	dump->u_debugreg[0] = current->thread.debugreg0; -	dump->u_debugreg[1] = current->thread.debugreg1; -	dump->u_debugreg[2] = current->thread.debugreg2; -	dump->u_debugreg[3] = current->thread.debugreg3; -	dump->u_debugreg[4] = 0; -	dump->u_debugreg[5] = 0; +	dump->u_debugreg[0] = get_dr(0); +	dump->u_debugreg[1] = get_dr(1); +	dump->u_debugreg[2] = get_dr(2); +	dump->u_debugreg[3] = get_dr(3);  	dump->u_debugreg[6] = current->thread.debugreg6; -	dump->u_debugreg[7] = current->thread.debugreg7; +	dump->u_debugreg[7] = current->thread.ptrace_dr7;  	if (dump->start_stack < 0xc0000000) {  		unsigned long tmp; @@ -75,24 +77,24 @@ static void dump_thread32(struct pt_regs *regs, struct user32 *dump)  		dump->u_ssize = tmp >> PAGE_SHIFT;  	} -	dump->regs.bx = regs->bx; -	dump->regs.cx = regs->cx; -	dump->regs.dx = regs->dx; -	dump->regs.si = regs->si; -	dump->regs.di = regs->di; -	dump->regs.bp = regs->bp; -	dump->regs.ax = regs->ax; +	dump->regs.ebx = regs->bx; +	dump->regs.ecx = regs->cx; +	dump->regs.edx = regs->dx; +	dump->regs.esi = regs->si; +	dump->regs.edi = regs->di; +	dump->regs.ebp = regs->bp; +	dump->regs.eax = regs->ax;  	dump->regs.ds = current->thread.ds;  	dump->regs.es = current->thread.es;  	savesegment(fs, fs);  	dump->regs.fs = fs;  	savesegment(gs, gs);  	dump->regs.gs = gs; -	dump->regs.orig_ax = regs->orig_ax; -	dump->regs.ip = regs->ip; +	dump->regs.orig_eax = regs->orig_ax; +	dump->regs.eip = regs->ip;  	dump->regs.cs = regs->cs; -	dump->regs.flags = regs->flags; -	dump->regs.sp = regs->sp; +	dump->regs.eflags = regs->flags; +	dump->regs.esp = regs->sp;  	dump->regs.ss = regs->ss;  #if 1 /* FIXME */ @@ -108,7 +110,7 @@ static struct linux_binfmt aout_format = {  	.module		= THIS_MODULE,  	.load_binary	= load_aout_binary,  	.load_shlib	= load_aout_library, -#ifdef CORE_DUMP +#ifdef CONFIG_COREDUMP  	.core_dump	= aout_core_dump,  #endif  	.min_coredump	= PAGE_SIZE @@ -120,12 +122,10 @@ static void set_brk(unsigned long start, unsigned long end)  	end = PAGE_ALIGN(end);  	if (end <= start)  		return; -	down_write(¤t->mm->mmap_sem); -	do_brk(start, end - start); -	up_write(¤t->mm->mmap_sem); +	vm_brk(start, end - start);  } -#ifdef CORE_DUMP +#ifdef CONFIG_COREDUMP  /*   * These are the only things you should do on a core-file: use only these   * macros to write out all the necessary info. @@ -133,15 +133,7 @@ static void set_brk(unsigned long start, unsigned long end)  #include <linux/coredump.h> -#define DUMP_WRITE(addr, nr)			     \ -	if (!dump_write(file, (void *)(addr), (nr))) \ -		goto end_coredump; - -#define DUMP_SEEK(offset)		\ -	if (!dump_seek(file, offset))	\ -		goto end_coredump; - -#define START_DATA()	(u.u_tsize << PAGE_SHIFT) +#define START_DATA(u)	(u.u_tsize << PAGE_SHIFT)  #define START_STACK(u)	(u.start_stack)  /* @@ -154,8 +146,7 @@ static void set_brk(unsigned long start, unsigned long end)   * dumping of the process results in another error..   */ -static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file, -			  unsigned long limit) +static int aout_core_dump(struct coredump_params *cprm)  {  	mm_segment_t fs;  	int has_dumped = 0; @@ -165,22 +156,21 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,  	fs = get_fs();  	set_fs(KERNEL_DS);  	has_dumped = 1; -	current->flags |= PF_DUMPCORE;  	strncpy(dump.u_comm, current->comm, sizeof(current->comm));  	dump.u_ar0 = offsetof(struct user32, regs); -	dump.signal = signr; -	dump_thread32(regs, &dump); +	dump.signal = cprm->siginfo->si_signo; +	dump_thread32(cprm->regs, &dump);  	/*  	 * If the size of the dump file exceeds the rlimit, then see  	 * what would happen if we wrote the stack, but not the data  	 * area.  	 */ -	if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > limit) +	if ((dump.u_dsize + dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)  		dump.u_dsize = 0;  	/* Make sure we have enough room to write the stack and data areas. */ -	if ((dump.u_ssize + 1) * PAGE_SIZE > limit) +	if ((dump.u_ssize + 1) * PAGE_SIZE > cprm->limit)  		dump.u_ssize = 0;  	/* make sure we actually have a data and stack area to dump */ @@ -194,22 +184,26 @@ static int aout_core_dump(long signr, struct pt_regs *regs, struct file *file,  	set_fs(KERNEL_DS);  	/* struct user */ -	DUMP_WRITE(&dump, sizeof(dump)); +	if (!dump_emit(cprm, &dump, sizeof(dump))) +		goto end_coredump;  	/* Now dump all of the user data.  Include malloced stuff as well */ -	DUMP_SEEK(PAGE_SIZE); +	if (!dump_skip(cprm, PAGE_SIZE - sizeof(dump))) +		goto end_coredump;  	/* now we start writing out the user space info */  	set_fs(USER_DS);  	/* Dump the data area */  	if (dump.u_dsize != 0) {  		dump_start = START_DATA(dump);  		dump_size = dump.u_dsize << PAGE_SHIFT; -		DUMP_WRITE(dump_start, dump_size); +		if (!dump_emit(cprm, (void *)dump_start, dump_size)) +			goto end_coredump;  	}  	/* Now prepare to dump the stack area */  	if (dump.u_ssize != 0) {  		dump_start = START_STACK(dump);  		dump_size = dump.u_ssize << PAGE_SHIFT; -		DUMP_WRITE(dump_start, dump_size); +		if (!dump_emit(cprm, (void *)dump_start, dump_size)) +			goto end_coredump;  	}  end_coredump:  	set_fs(fs); @@ -263,9 +257,10 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm)   * These are the functions used to load a.out style executables and shared   * libraries.  There is no binary dependent code anywhere else.   */ -static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) +static int load_aout_binary(struct linux_binprm *bprm)  {  	unsigned long error, fd_offset, rlim; +	struct pt_regs *regs = current_pt_regs();  	struct exec ex;  	int retval; @@ -273,7 +268,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)  	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC &&  	     N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) ||  	    N_TRSIZE(ex) || N_DRSIZE(ex) || -	    i_size_read(bprm->file->f_path.dentry->d_inode) < +	    i_size_read(file_inode(bprm->file)) <  	    ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {  		return -ENOEXEC;  	} @@ -297,7 +292,7 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)  	/* OK, This is the point of no return */  	set_personality(PER_LINUX); -	set_thread_flag(TIF_IA32); +	set_personality_ia32(false);  	setup_new_exec(bprm); @@ -311,39 +306,35 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)  		(current->mm->start_data = N_DATADDR(ex));  	current->mm->brk = ex.a_bss +  		(current->mm->start_brk = N_BSSADDR(ex)); -	current->mm->free_area_cache = TASK_UNMAPPED_BASE; -	current->mm->cached_hole_size = 0; + +	retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); +	if (retval < 0) { +		/* Someone check-me: is this error path enough? */ +		send_sig(SIGKILL, current, 0); +		return retval; +	}  	install_exec_creds(bprm); -	current->flags &= ~PF_FORKNOEXEC;  	if (N_MAGIC(ex) == OMAGIC) {  		unsigned long text_addr, map_size; -		loff_t pos;  		text_addr = N_TXTADDR(ex); - -		pos = 32;  		map_size = ex.a_text+ex.a_data; -		down_write(¤t->mm->mmap_sem); -		error = do_brk(text_addr & PAGE_MASK, map_size); -		up_write(¤t->mm->mmap_sem); +		error = vm_brk(text_addr & PAGE_MASK, map_size);  		if (error != (text_addr & PAGE_MASK)) {  			send_sig(SIGKILL, current, 0);  			return error;  		} -		error = bprm->file->f_op->read(bprm->file, -			 (char __user *)text_addr, -			  ex.a_text+ex.a_data, &pos); +		error = read_code(bprm->file, text_addr, 32, +				  ex.a_text + ex.a_data);  		if ((signed long)error < 0) {  			send_sig(SIGKILL, current, 0);  			return error;  		} - -		flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);  	} else {  #ifdef WARN_OLD  		static unsigned long error_time, error_time2; @@ -365,40 +356,28 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)  #endif  		if (!bprm->file->f_op->mmap || (fd_offset & ~PAGE_MASK) != 0) { -			loff_t pos = fd_offset; - -			down_write(¤t->mm->mmap_sem); -			do_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); -			up_write(¤t->mm->mmap_sem); -			bprm->file->f_op->read(bprm->file, -					(char __user *)N_TXTADDR(ex), -					ex.a_text+ex.a_data, &pos); -			flush_icache_range((unsigned long) N_TXTADDR(ex), -					   (unsigned long) N_TXTADDR(ex) + -					   ex.a_text+ex.a_data); +			vm_brk(N_TXTADDR(ex), ex.a_text+ex.a_data); +			read_code(bprm->file, N_TXTADDR(ex), fd_offset, +					ex.a_text+ex.a_data);  			goto beyond_if;  		} -		down_write(¤t->mm->mmap_sem); -		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, +		error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,  				PROT_READ | PROT_EXEC,  				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |  				MAP_EXECUTABLE | MAP_32BIT,  				fd_offset); -		up_write(¤t->mm->mmap_sem);  		if (error != N_TXTADDR(ex)) {  			send_sig(SIGKILL, current, 0);  			return error;  		} -		down_write(¤t->mm->mmap_sem); -		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, +		error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,  				PROT_READ | PROT_WRITE | PROT_EXEC,  				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |  				MAP_EXECUTABLE | MAP_32BIT,  				fd_offset + ex.a_text); -		up_write(¤t->mm->mmap_sem);  		if (error != N_DATADDR(ex)) {  			send_sig(SIGKILL, current, 0);  			return error; @@ -409,13 +388,6 @@ beyond_if:  	set_brk(current->mm->start_brk, current->mm->brk); -	retval = setup_arg_pages(bprm, IA32_STACK_TOP, EXSTACK_DEFAULT); -	if (retval < 0) { -		/* Someone check-me: is this error path enough? */ -		send_sig(SIGKILL, current, 0); -		return retval; -	} -  	current->mm->start_stack =  		(unsigned long)create_aout_tables((char __user *)bprm->p, bprm);  	/* start thread */ @@ -436,12 +408,10 @@ beyond_if:  static int load_aout_library(struct file *file)  { -	struct inode *inode;  	unsigned long bss, start_addr, len, error;  	int retval;  	struct exec ex; -	inode = file->f_path.dentry->d_inode;  	retval = -ENOEXEC;  	error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); @@ -451,7 +421,7 @@ static int load_aout_library(struct file *file)  	/* We come in here for the regular a.out style of shared libraries */  	if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) ||  	    N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || -	    i_size_read(inode) < +	    i_size_read(file_inode(file)) <  	    ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) {  		goto out;  	} @@ -465,8 +435,6 @@ static int load_aout_library(struct file *file)  	start_addr =  ex.a_entry & 0xfffff000;  	if ((N_TXTOFF(ex) & ~PAGE_MASK) != 0) { -		loff_t pos = N_TXTOFF(ex); -  #ifdef WARN_OLD  		static unsigned long error_time;  		if (time_after(jiffies, error_time + 5*HZ)) { @@ -477,26 +445,18 @@ static int load_aout_library(struct file *file)  			error_time = jiffies;  		}  #endif -		down_write(¤t->mm->mmap_sem); -		do_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); -		up_write(¤t->mm->mmap_sem); - -		file->f_op->read(file, (char __user *)start_addr, -			ex.a_text + ex.a_data, &pos); -		flush_icache_range((unsigned long) start_addr, -				   (unsigned long) start_addr + ex.a_text + -				   ex.a_data); +		vm_brk(start_addr, ex.a_text + ex.a_data + ex.a_bss); +		read_code(file, start_addr, N_TXTOFF(ex), +			  ex.a_text + ex.a_data);  		retval = 0;  		goto out;  	}  	/* Now use mmap to map the library into memory. */ -	down_write(¤t->mm->mmap_sem); -	error = do_mmap(file, start_addr, ex.a_text + ex.a_data, +	error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,  			PROT_READ | PROT_WRITE | PROT_EXEC,  			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,  			N_TXTOFF(ex)); -	up_write(¤t->mm->mmap_sem);  	retval = error;  	if (error != start_addr)  		goto out; @@ -504,9 +464,7 @@ static int load_aout_library(struct file *file)  	len = PAGE_ALIGN(ex.a_text + ex.a_data);  	bss = ex.a_text + ex.a_data + ex.a_bss;  	if (bss > len) { -		down_write(¤t->mm->mmap_sem); -		error = do_brk(start_addr + len, bss - len); -		up_write(¤t->mm->mmap_sem); +		error = vm_brk(start_addr + len, bss - len);  		retval = error;  		if (error != start_addr + len)  			goto out; @@ -518,7 +476,8 @@ out:  static int __init init_aout_binfmt(void)  { -	return register_binfmt(&aout_format); +	register_binfmt(&aout_format); +	return 0;  }  static void __exit exit_aout_binfmt(void) diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 588a7aa937e..f9e181aaba9 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -12,10 +12,8 @@  #include <linux/mm.h>  #include <linux/smp.h>  #include <linux/kernel.h> -#include <linux/signal.h>  #include <linux/errno.h>  #include <linux/wait.h> -#include <linux/ptrace.h>  #include <linux/unistd.h>  #include <linux/stddef.h>  #include <linux/personality.h> @@ -24,6 +22,7 @@  #include <asm/ucontext.h>  #include <asm/uaccess.h>  #include <asm/i387.h> +#include <asm/fpu-internal.h>  #include <asm/ptrace.h>  #include <asm/ia32_unistd.h>  #include <asm/user32.h> @@ -31,20 +30,14 @@  #include <asm/proto.h>  #include <asm/vdso.h>  #include <asm/sigframe.h> +#include <asm/sighandling.h>  #include <asm/sys_ia32.h> +#include <asm/smap.h> -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -#define FIX_EFLAGS	(X86_EFLAGS_AC | X86_EFLAGS_OF | \ -			 X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \ -			 X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \ -			 X86_EFLAGS_CF) - -void signal_fault(struct pt_regs *regs, void __user *frame, char *where); - -int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) +int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)  {  	int err = 0; +	bool ia32 = test_thread_flag(TIF_IA32);  	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))  		return -EFAULT; @@ -73,9 +66,18 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)  			switch (from->si_code >> 16) {  			case __SI_FAULT >> 16:  				break; +			case __SI_SYS >> 16: +				put_user_ex(from->si_syscall, &to->si_syscall); +				put_user_ex(from->si_arch, &to->si_arch); +				break;  			case __SI_CHLD >> 16: -				put_user_ex(from->si_utime, &to->si_utime); -				put_user_ex(from->si_stime, &to->si_stime); +				if (ia32) { +					put_user_ex(from->si_utime, &to->si_utime); +					put_user_ex(from->si_stime, &to->si_stime); +				} else { +					put_user_ex(from->si_utime, &to->_sifields._sigchld_x32._utime); +					put_user_ex(from->si_stime, &to->_sifields._sigchld_x32._stime); +				}  				put_user_ex(from->si_status, &to->si_status);  				/* FALL THROUGH */  			default: @@ -125,66 +127,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)  	return err;  } -asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) -{ -	mask &= _BLOCKABLE; -	spin_lock_irq(¤t->sighand->siglock); -	current->saved_sigmask = current->blocked; -	siginitset(¤t->blocked, mask); -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); - -	current->state = TASK_INTERRUPTIBLE; -	schedule(); -	set_restore_sigmask(); -	return -ERESTARTNOHAND; -} - -asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, -				  stack_ia32_t __user *uoss_ptr, -				  struct pt_regs *regs) -{ -	stack_t uss, uoss; -	int ret, err = 0; -	mm_segment_t seg; - -	if (uss_ptr) { -		u32 ptr; - -		memset(&uss, 0, sizeof(stack_t)); -		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t))) -			return -EFAULT; - -		get_user_try { -			get_user_ex(ptr, &uss_ptr->ss_sp); -			get_user_ex(uss.ss_flags, &uss_ptr->ss_flags); -			get_user_ex(uss.ss_size, &uss_ptr->ss_size); -		} get_user_catch(err); - -		if (err) -			return -EFAULT; -		uss.ss_sp = compat_ptr(ptr); -	} -	seg = get_fs(); -	set_fs(KERNEL_DS); -	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp); -	set_fs(seg); -	if (ret >= 0 && uoss_ptr)  { -		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t))) -			return -EFAULT; - -		put_user_try { -			put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp); -			put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags); -			put_user_ex(uoss.ss_size, &uoss_ptr->ss_size); -		} put_user_catch(err); - -		if (err) -			ret = -EFAULT; -	} -	return ret; -} -  /*   * Do a signal return; undo the signal stack.   */ @@ -255,16 +197,18 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,  		get_user_ex(tmp, &sc->fpstate);  		buf = compat_ptr(tmp); -		err |= restore_i387_xstate_ia32(buf);  		get_user_ex(*pax, &sc->ax);  	} get_user_catch(err); +	err |= restore_xstate_sig(buf, 1); +  	return err;  } -asmlinkage long sys32_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_sigreturn(void)  { +	struct pt_regs *regs = current_pt_regs();  	struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);  	sigset_t set;  	unsigned int ax; @@ -278,11 +222,7 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)  				    sizeof(frame->extramask))))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); -	spin_lock_irq(¤t->sighand->siglock); -	current->blocked = set; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	set_current_blocked(&set);  	if (ia32_restore_sigcontext(regs, &frame->sc, &ax))  		goto badframe; @@ -293,12 +233,12 @@ badframe:  	return 0;  } -asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs) +asmlinkage long sys32_rt_sigreturn(void)  { +	struct pt_regs *regs = current_pt_regs();  	struct rt_sigframe_ia32 __user *frame;  	sigset_t set;  	unsigned int ax; -	struct pt_regs tregs;  	frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4); @@ -307,17 +247,12 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)  	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))  		goto badframe; -	sigdelsetmask(&set, ~_BLOCKABLE); -	spin_lock_irq(¤t->sighand->siglock); -	current->blocked = set; -	recalc_sigpending(); -	spin_unlock_irq(¤t->sighand->siglock); +	set_current_blocked(&set);  	if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))  		goto badframe; -	tregs = *regs; -	if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT) +	if (compat_restore_altstack(&frame->uc.uc_stack))  		goto badframe;  	return ax; @@ -351,7 +286,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,  		put_user_ex(regs->dx, &sc->dx);  		put_user_ex(regs->cx, &sc->cx);  		put_user_ex(regs->ax, &sc->ax); -		put_user_ex(current->thread.trap_no, &sc->trapno); +		put_user_ex(current->thread.trap_nr, &sc->trapno);  		put_user_ex(current->thread.error_code, &sc->err);  		put_user_ex(regs->ip, &sc->ip);  		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs); @@ -372,9 +307,9 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,  /*   * Determine which stack to use..   */ -static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, +static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,  				 size_t frame_size, -				 void **fpstate) +				 void __user **fpstate)  {  	unsigned long sp; @@ -382,21 +317,21 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,  	sp = regs->sp;  	/* This is the X/Open sanctioned signal stack switching.  */ -	if (ka->sa.sa_flags & SA_ONSTACK) { -		if (sas_ss_flags(sp) == 0) -			sp = current->sas_ss_sp + current->sas_ss_size; -	} - +	if (ksig->ka.sa.sa_flags & SA_ONSTACK) +		sp = sigsp(sp, ksig);  	/* This is the legacy signal stack switching. */  	else if ((regs->ss & 0xffff) != __USER32_DS && -		!(ka->sa.sa_flags & SA_RESTORER) && -		 ka->sa.sa_restorer) -		sp = (unsigned long) ka->sa.sa_restorer; +		!(ksig->ka.sa.sa_flags & SA_RESTORER) && +		 ksig->ka.sa.sa_restorer) +		sp = (unsigned long) ksig->ka.sa.sa_restorer;  	if (used_math()) { -		sp = sp - sig_xstate_ia32_size; -		*fpstate = (struct _fpstate_ia32 *) sp; -		if (save_i387_xstate_ia32(*fpstate) < 0) +		unsigned long fx_aligned, math_size; + +		sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size); +		*fpstate = (struct _fpstate_ia32 __user *) sp; +		if (save_xstate_sig(*fpstate, (void __user *)fx_aligned, +				    math_size) < 0)  			return (void __user *) -1L;  	} @@ -407,7 +342,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,  	return (void __user *) sp;  } -int ia32_setup_frame(int sig, struct k_sigaction *ka, +int ia32_setup_frame(int sig, struct ksignal *ksig,  		     compat_sigset_t *set, struct pt_regs *regs)  {  	struct sigframe_ia32 __user *frame; @@ -426,7 +361,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,  		0x80cd,		/* int $0x80 */  	}; -	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); +	frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))  		return -EFAULT; @@ -443,13 +378,13 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,  			return -EFAULT;  	} -	if (ka->sa.sa_flags & SA_RESTORER) { -		restorer = ka->sa.sa_restorer; +	if (ksig->ka.sa.sa_flags & SA_RESTORER) { +		restorer = ksig->ka.sa.sa_restorer;  	} else {  		/* Return stub is in 32bit vsyscall page */  		if (current->mm->context.vdso) -			restorer = VDSO32_SYMBOL(current->mm->context.vdso, -						 sigreturn); +			restorer = current->mm->context.vdso + +				selected_vdso32->sym___kernel_sigreturn;  		else  			restorer = &frame->retcode;  	} @@ -461,7 +396,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,  		 * These are actually not used anymore, but left because some  		 * gdb versions depend on them as a marker.  		 */ -		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); +		put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);  	} put_user_catch(err);  	if (err) @@ -469,7 +404,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,  	/* Set up registers for signal handler */  	regs->sp = (unsigned long) frame; -	regs->ip = (unsigned long) ka->sa.sa_handler; +	regs->ip = (unsigned long) ksig->ka.sa.sa_handler;  	/* Make -mregparm=3 work */  	regs->ax = sig; @@ -485,7 +420,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,  	return 0;  } -int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, +int ia32_setup_rt_frame(int sig, struct ksignal *ksig,  			compat_sigset_t *set, struct pt_regs *regs)  {  	struct rt_sigframe_ia32 __user *frame; @@ -506,7 +441,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		0,  	}; -	frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); +	frame = get_sigframe(ksig, regs, sizeof(*frame), &fpstate);  	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))  		return -EFAULT; @@ -515,7 +450,6 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		put_user_ex(sig, &frame->sig);  		put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);  		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc); -		err |= copy_siginfo_to_user32(&frame->info, info);  		/* Create the ucontext.  */  		if (cpu_has_xsave) @@ -523,34 +457,33 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,  		else  			put_user_ex(0, &frame->uc.uc_flags);  		put_user_ex(0, &frame->uc.uc_link); -		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp); -		put_user_ex(sas_ss_flags(regs->sp), -			    &frame->uc.uc_stack.ss_flags); -		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size); -		err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, -					     regs, set->sig[0]); -		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - -		if (ka->sa.sa_flags & SA_RESTORER) -			restorer = ka->sa.sa_restorer; +		compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); + +		if (ksig->ka.sa.sa_flags & SA_RESTORER) +			restorer = ksig->ka.sa.sa_restorer;  		else -			restorer = VDSO32_SYMBOL(current->mm->context.vdso, -						 rt_sigreturn); +			restorer = current->mm->context.vdso + +				selected_vdso32->sym___kernel_rt_sigreturn;  		put_user_ex(ptr_to_compat(restorer), &frame->pretcode);  		/*  		 * Not actually used anymore, but left because some gdb  		 * versions need it.  		 */ -		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode); +		put_user_ex(*((u64 *)&code), (u64 __user *)frame->retcode);  	} put_user_catch(err); +	err |= copy_siginfo_to_user32(&frame->info, &ksig->info); +	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate, +				     regs, set->sig[0]); +	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); +  	if (err)  		return -EFAULT;  	/* Set up registers for signal handler */  	regs->sp = (unsigned long) frame; -	regs->ip = (unsigned long) ka->sa.sa_handler; +	regs->ip = (unsigned long) ksig->ka.sa.sa_handler;  	/* Make -mregparm=3 work */  	regs->ax = sig; diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 518bb99c339..4299eb05023 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -13,7 +13,10 @@  #include <asm/thread_info.h>	  #include <asm/segment.h>  #include <asm/irqflags.h> +#include <asm/asm.h> +#include <asm/smap.h>  #include <linux/linkage.h> +#include <linux/err.h>  /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this.  */  #include <linux/elf-em.h> @@ -25,7 +28,7 @@  #define sysretl_audit ia32_ret_from_sys_call  #endif -#define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) +	.section .entry.text, "ax"  	.macro IA32_ARG_FIXUP noebp=0  	movl	%edi,%r8d @@ -126,37 +129,30 @@ ENTRY(ia32_sysenter_target)  	 */  	ENABLE_INTERRUPTS(CLBR_NONE)   	movl	%ebp,%ebp		/* zero extension */ -	pushq	$__USER32_DS -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi $__USER32_DS  	/*CFI_REL_OFFSET ss,0*/ -	pushq	%rbp -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi %rbp  	CFI_REL_OFFSET rsp,0 -	pushfq -	CFI_ADJUST_CFA_OFFSET 8 +	pushfq_cfi  	/*CFI_REL_OFFSET rflags,0*/ -	movl	8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d +	movl	TI_sysenter_return+THREAD_INFO(%rsp,3*8-KERNEL_STACK_OFFSET),%r10d  	CFI_REGISTER rip,r10 -	pushq	$__USER32_CS -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi $__USER32_CS  	/*CFI_REL_OFFSET cs,0*/  	movl	%eax, %eax -	pushq	%r10 -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi %r10  	CFI_REL_OFFSET rip,0 -	pushq	%rax -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi %rax  	cld -	SAVE_ARGS 0,0,1 +	SAVE_ARGS 0,1,0   	/* no need to do an access_ok check here because rbp has been   	   32bit zero extended */  +	ASM_STAC  1:	movl	(%rbp),%ebp - 	.section __ex_table,"a" - 	.quad 1b,ia32_badarg - 	.previous	 -	GET_THREAD_INFO(%r10) -	orl    $TS_COMPAT,TI_status(%r10) -	testl  $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) +	_ASM_EXTABLE(1b,ia32_badarg) +	ASM_CLAC +	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) +	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	CFI_REMEMBER_STATE  	jnz  sysenter_tracesys  	cmpq	$(IA32_NR_syscalls-1),%rax @@ -166,27 +162,24 @@ sysenter_do_call:  sysenter_dispatch:  	call	*ia32_sys_call_table(,%rax,8)  	movq	%rax,RAX-ARGOFFSET(%rsp) -	GET_THREAD_INFO(%r10)  	DISABLE_INTERRUPTS(CLBR_NONE)  	TRACE_IRQS_OFF -	testl	$_TIF_ALLWORK_MASK,TI_flags(%r10) +	testl	$_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jnz	sysexit_audit  sysexit_from_sys_call: -	andl    $~TS_COMPAT,TI_status(%r10) +	andl    $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	/* clear IF, that popfq doesn't enable interrupts early */  	andl  $~0x200,EFLAGS-R11(%rsp)   	movl	RIP-R11(%rsp),%edx		/* User %eip */  	CFI_REGISTER rip,rdx -	RESTORE_ARGS 1,24,1,1,1,1 +	RESTORE_ARGS 0,24,0,0,0,0  	xorq	%r8,%r8  	xorq	%r9,%r9  	xorq	%r10,%r10  	xorq	%r11,%r11 -	popfq -	CFI_ADJUST_CFA_OFFSET -8 +	popfq_cfi  	/*CFI_RESTORE rflags*/ -	popq	%rcx				/* User %esp */ -	CFI_ADJUST_CFA_OFFSET -8 +	popq_cfi %rcx				/* User %esp */  	CFI_REGISTER rsp,rcx  	TRACE_IRQS_ON  	ENABLE_INTERRUPTS_SYSEXIT32 @@ -199,7 +192,7 @@ sysexit_from_sys_call:  	movl %ebx,%edx			/* 3rd arg: 1st syscall arg */  	movl %eax,%esi			/* 2nd arg: syscall number */  	movl $AUDIT_ARCH_I386,%edi	/* 1st arg: audit arch */ -	call audit_syscall_entry +	call __audit_syscall_entry  	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall number */  	cmpq $(IA32_NR_syscalls-1),%rax  	ja ia32_badsys @@ -211,22 +204,22 @@ sysexit_from_sys_call:  	.endm  	.macro auditsys_exit exit -	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) +	testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jnz ia32_ret_from_sys_call  	TRACE_IRQS_ON -	sti +	ENABLE_INTERRUPTS(CLBR_NONE)  	movl %eax,%esi		/* second arg, syscall return value */ -	cmpl $0,%eax		/* is it < 0? */ -	setl %al		/* 1 if so, 0 if not */ +	cmpl $-MAX_ERRNO,%eax	/* is it an error ? */ +	jbe 1f +	movslq %eax, %rsi	/* if error sign extend to 64 bits */ +1:	setbe %al		/* 1 if error, 0 if not */  	movzbl %al,%edi		/* zero-extend that into %edi */ -	inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */ -	call audit_syscall_exit -	GET_THREAD_INFO(%r10) -	movl RAX-ARGOFFSET(%rsp),%eax	/* reload syscall return value */ +	call __audit_syscall_exit +	movq RAX-ARGOFFSET(%rsp),%rax	/* reload syscall return value */  	movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi -	cli +	DISABLE_INTERRUPTS(CLBR_NONE)  	TRACE_IRQS_OFF -	testl %edi,TI_flags(%r10) +	testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jz \exit  	CLEAR_RREGS -ARGOFFSET  	jmp int_with_check @@ -244,7 +237,7 @@ sysexit_audit:  sysenter_tracesys:  #ifdef CONFIG_AUDITSYSCALL -	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) +	testl	$(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jz	sysenter_auditsys  #endif  	SAVE_REST @@ -295,7 +288,7 @@ ENTRY(ia32_cstar_target)  	 * disabled irqs and here we enable it straight after entry:  	 */  	ENABLE_INTERRUPTS(CLBR_NONE) -	SAVE_ARGS 8,1,1 +	SAVE_ARGS 8,0,0  	movl 	%eax,%eax	/* zero extension */  	movq	%rax,ORIG_RAX-ARGOFFSET(%rsp)  	movq	%rcx,RIP-ARGOFFSET(%rsp) @@ -311,13 +304,12 @@ ENTRY(ia32_cstar_target)  	/* no need to do an access_ok check here because r8 has been  	   32bit zero extended */   	/* hardware stack frame is complete now */	 +	ASM_STAC  1:	movl	(%r8),%r9d -	.section __ex_table,"a" -	.quad 1b,ia32_badarg -	.previous	 -	GET_THREAD_INFO(%r10) -	orl   $TS_COMPAT,TI_status(%r10) -	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) +	_ASM_EXTABLE(1b,ia32_badarg) +	ASM_CLAC +	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) +	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	CFI_REMEMBER_STATE  	jnz   cstar_tracesys  	cmpq $IA32_NR_syscalls-1,%rax @@ -327,14 +319,13 @@ cstar_do_call:  cstar_dispatch:  	call *ia32_sys_call_table(,%rax,8)  	movq %rax,RAX-ARGOFFSET(%rsp) -	GET_THREAD_INFO(%r10)  	DISABLE_INTERRUPTS(CLBR_NONE)  	TRACE_IRQS_OFF -	testl $_TIF_ALLWORK_MASK,TI_flags(%r10) +	testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jnz sysretl_audit  sysretl_from_sys_call: -	andl $~TS_COMPAT,TI_status(%r10) -	RESTORE_ARGS 1,-ARG_SKIP,1,1,1 +	andl $~TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) +	RESTORE_ARGS 0,-ARG_SKIP,0,0,0  	movl RIP-ARGOFFSET(%rsp),%ecx  	CFI_REGISTER rip,rcx  	movl EFLAGS-ARGOFFSET(%rsp),%r11d	 @@ -361,7 +352,7 @@ sysretl_audit:  cstar_tracesys:  #ifdef CONFIG_AUDITSYSCALL -	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) +	testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jz cstar_auditsys  #endif  	xchgl %r9d,%ebp @@ -379,6 +370,7 @@ cstar_tracesys:  END(ia32_cstar_target)  ia32_badarg: +	ASM_CLAC  	movq $-EFAULT,%rax  	jmp ia32_sysret  	CFI_ENDPROC @@ -421,15 +413,13 @@ ENTRY(ia32_syscall)  	 */  	ENABLE_INTERRUPTS(CLBR_NONE)  	movl %eax,%eax -	pushq %rax -	CFI_ADJUST_CFA_OFFSET 8 +	pushq_cfi %rax  	cld  	/* note the registers are not zero extended to the sf.  	   this could be a problem. */ -	SAVE_ARGS 0,0,1 -	GET_THREAD_INFO(%r10) -	orl   $TS_COMPAT,TI_status(%r10) -	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags(%r10) +	SAVE_ARGS 0,1,0 +	orl $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET) +	testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)  	jnz ia32_tracesys  	cmpq $(IA32_NR_syscalls-1),%rax  	ja ia32_badsys @@ -460,31 +450,31 @@ ia32_badsys:  	movq $-ENOSYS,%rax  	jmp ia32_sysret -quiet_ni_syscall: -	movq $-ENOSYS,%rax -	ret  	CFI_ENDPROC -	.macro PTREGSCALL label, func, arg -	.globl \label -\label: +	.macro PTREGSCALL label, func +	ALIGN +GLOBAL(\label)  	leaq \func(%rip),%rax -	leaq -ARGOFFSET+8(%rsp),\arg	/* 8 for return address */  	jmp  ia32_ptregs_common	  	.endm  	CFI_STARTPROC32 -	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi -	PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi -	PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx -	PTREGSCALL stub32_execve, sys32_execve, %rcx -	PTREGSCALL stub32_fork, sys_fork, %rdi -	PTREGSCALL stub32_clone, sys32_clone, %rdx -	PTREGSCALL stub32_vfork, sys_vfork, %rdi -	PTREGSCALL stub32_iopl, sys_iopl, %rsi +	PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn +	PTREGSCALL stub32_sigreturn, sys32_sigreturn +	PTREGSCALL stub32_execve, compat_sys_execve +	PTREGSCALL stub32_fork, sys_fork +	PTREGSCALL stub32_vfork, sys_vfork -ENTRY(ia32_ptregs_common) +	ALIGN +GLOBAL(stub32_clone) +	leaq sys_clone(%rip),%rax +	mov	%r8, %rcx +	jmp  ia32_ptregs_common	 + +	ALIGN +ia32_ptregs_common:  	popq %r11  	CFI_ENDPROC  	CFI_STARTPROC32	simple @@ -506,349 +496,3 @@ ENTRY(ia32_ptregs_common)  	jmp  ia32_sysret	/* misbalances the return cache */  	CFI_ENDPROC  END(ia32_ptregs_common) - -	.section .rodata,"a" -	.align 8 -ia32_sys_call_table: -	.quad sys_restart_syscall -	.quad sys_exit -	.quad stub32_fork -	.quad sys_read -	.quad sys_write -	.quad compat_sys_open		/* 5 */ -	.quad sys_close -	.quad sys32_waitpid -	.quad sys_creat -	.quad sys_link -	.quad sys_unlink		/* 10 */ -	.quad stub32_execve -	.quad sys_chdir -	.quad compat_sys_time -	.quad sys_mknod -	.quad sys_chmod		/* 15 */ -	.quad sys_lchown16 -	.quad quiet_ni_syscall			/* old break syscall holder */ -	.quad sys_stat -	.quad sys32_lseek -	.quad sys_getpid		/* 20 */ -	.quad compat_sys_mount	/* mount  */ -	.quad sys_oldumount	/* old_umount  */ -	.quad sys_setuid16 -	.quad sys_getuid16 -	.quad compat_sys_stime	/* stime */		/* 25 */ -	.quad compat_sys_ptrace	/* ptrace */ -	.quad sys_alarm -	.quad sys_fstat	/* (old)fstat */ -	.quad sys_pause -	.quad compat_sys_utime	/* 30 */ -	.quad quiet_ni_syscall	/* old stty syscall holder */ -	.quad quiet_ni_syscall	/* old gtty syscall holder */ -	.quad sys_access -	.quad sys_nice	 -	.quad quiet_ni_syscall	/* 35 */	/* old ftime syscall holder */ -	.quad sys_sync -	.quad sys32_kill -	.quad sys_rename -	.quad sys_mkdir -	.quad sys_rmdir		/* 40 */ -	.quad sys_dup -	.quad sys_pipe -	.quad compat_sys_times -	.quad quiet_ni_syscall			/* old prof syscall holder */ -	.quad sys_brk		/* 45 */ -	.quad sys_setgid16 -	.quad sys_getgid16 -	.quad sys_signal -	.quad sys_geteuid16 -	.quad sys_getegid16	/* 50 */ -	.quad sys_acct -	.quad sys_umount			/* new_umount */ -	.quad quiet_ni_syscall			/* old lock syscall holder */ -	.quad compat_sys_ioctl -	.quad compat_sys_fcntl64		/* 55 */ -	.quad quiet_ni_syscall			/* old mpx syscall holder */ -	.quad sys_setpgid -	.quad quiet_ni_syscall			/* old ulimit syscall holder */ -	.quad sys_olduname -	.quad sys_umask		/* 60 */ -	.quad sys_chroot -	.quad compat_sys_ustat -	.quad sys_dup2 -	.quad sys_getppid -	.quad sys_getpgrp		/* 65 */ -	.quad sys_setsid -	.quad sys32_sigaction -	.quad sys_sgetmask -	.quad sys_ssetmask -	.quad sys_setreuid16	/* 70 */ -	.quad sys_setregid16 -	.quad sys32_sigsuspend -	.quad compat_sys_sigpending -	.quad sys_sethostname -	.quad compat_sys_setrlimit	/* 75 */ -	.quad compat_sys_old_getrlimit	/* old_getrlimit */ -	.quad compat_sys_getrusage -	.quad compat_sys_gettimeofday -	.quad compat_sys_settimeofday -	.quad sys_getgroups16	/* 80 */ -	.quad sys_setgroups16 -	.quad compat_sys_old_select -	.quad sys_symlink -	.quad sys_lstat -	.quad sys_readlink		/* 85 */ -	.quad sys_uselib -	.quad sys_swapon -	.quad sys_reboot -	.quad compat_sys_old_readdir -	.quad sys32_mmap		/* 90 */ -	.quad sys_munmap -	.quad sys_truncate -	.quad sys_ftruncate -	.quad sys_fchmod -	.quad sys_fchown16		/* 95 */ -	.quad sys_getpriority -	.quad sys_setpriority -	.quad quiet_ni_syscall			/* old profil syscall holder */ -	.quad compat_sys_statfs -	.quad compat_sys_fstatfs		/* 100 */ -	.quad sys_ioperm -	.quad compat_sys_socketcall -	.quad sys_syslog -	.quad compat_sys_setitimer -	.quad compat_sys_getitimer	/* 105 */ -	.quad compat_sys_newstat -	.quad compat_sys_newlstat -	.quad compat_sys_newfstat -	.quad sys_uname -	.quad stub32_iopl		/* 110 */ -	.quad sys_vhangup -	.quad quiet_ni_syscall	/* old "idle" system call */ -	.quad sys32_vm86_warning	/* vm86old */  -	.quad compat_sys_wait4 -	.quad sys_swapoff		/* 115 */ -	.quad compat_sys_sysinfo -	.quad sys32_ipc -	.quad sys_fsync -	.quad stub32_sigreturn -	.quad stub32_clone		/* 120 */ -	.quad sys_setdomainname -	.quad sys_newuname -	.quad sys_modify_ldt -	.quad compat_sys_adjtimex -	.quad sys32_mprotect		/* 125 */ -	.quad compat_sys_sigprocmask -	.quad quiet_ni_syscall		/* create_module */ -	.quad sys_init_module -	.quad sys_delete_module -	.quad quiet_ni_syscall		/* 130  get_kernel_syms */ -	.quad sys32_quotactl -	.quad sys_getpgid -	.quad sys_fchdir -	.quad quiet_ni_syscall	/* bdflush */ -	.quad sys_sysfs		/* 135 */ -	.quad sys_personality -	.quad quiet_ni_syscall	/* for afs_syscall */ -	.quad sys_setfsuid16 -	.quad sys_setfsgid16 -	.quad sys_llseek		/* 140 */ -	.quad compat_sys_getdents -	.quad compat_sys_select -	.quad sys_flock -	.quad sys_msync -	.quad compat_sys_readv		/* 145 */ -	.quad compat_sys_writev -	.quad sys_getsid -	.quad sys_fdatasync -	.quad compat_sys_sysctl	/* sysctl */ -	.quad sys_mlock		/* 150 */ -	.quad sys_munlock -	.quad sys_mlockall -	.quad sys_munlockall -	.quad sys_sched_setparam -	.quad sys_sched_getparam   /* 155 */ -	.quad sys_sched_setscheduler -	.quad sys_sched_getscheduler -	.quad sys_sched_yield -	.quad sys_sched_get_priority_max -	.quad sys_sched_get_priority_min  /* 160 */ -	.quad sys32_sched_rr_get_interval -	.quad compat_sys_nanosleep -	.quad sys_mremap -	.quad sys_setresuid16 -	.quad sys_getresuid16	/* 165 */ -	.quad sys32_vm86_warning	/* vm86 */  -	.quad quiet_ni_syscall	/* query_module */ -	.quad sys_poll -	.quad compat_sys_nfsservctl -	.quad sys_setresgid16	/* 170 */ -	.quad sys_getresgid16 -	.quad sys_prctl -	.quad stub32_rt_sigreturn -	.quad sys32_rt_sigaction -	.quad sys32_rt_sigprocmask	/* 175 */ -	.quad sys32_rt_sigpending -	.quad compat_sys_rt_sigtimedwait -	.quad sys32_rt_sigqueueinfo -	.quad sys_rt_sigsuspend -	.quad sys32_pread		/* 180 */ -	.quad sys32_pwrite -	.quad sys_chown16 -	.quad sys_getcwd -	.quad sys_capget -	.quad sys_capset -	.quad stub32_sigaltstack -	.quad sys32_sendfile -	.quad quiet_ni_syscall		/* streams1 */ -	.quad quiet_ni_syscall		/* streams2 */ -	.quad stub32_vfork            /* 190 */ -	.quad compat_sys_getrlimit -	.quad sys_mmap_pgoff -	.quad sys32_truncate64 -	.quad sys32_ftruncate64 -	.quad sys32_stat64		/* 195 */ -	.quad sys32_lstat64 -	.quad sys32_fstat64 -	.quad sys_lchown -	.quad sys_getuid -	.quad sys_getgid		/* 200 */ -	.quad sys_geteuid -	.quad sys_getegid -	.quad sys_setreuid -	.quad sys_setregid -	.quad sys_getgroups	/* 205 */ -	.quad sys_setgroups -	.quad sys_fchown -	.quad sys_setresuid -	.quad sys_getresuid -	.quad sys_setresgid	/* 210 */ -	.quad sys_getresgid -	.quad sys_chown -	.quad sys_setuid -	.quad sys_setgid -	.quad sys_setfsuid		/* 215 */ -	.quad sys_setfsgid -	.quad sys_pivot_root -	.quad sys_mincore -	.quad sys_madvise -	.quad compat_sys_getdents64	/* 220 getdents64 */ -	.quad compat_sys_fcntl64	 -	.quad quiet_ni_syscall		/* tux */ -	.quad quiet_ni_syscall    	/* security */ -	.quad sys_gettid	 -	.quad sys32_readahead	/* 225 */ -	.quad sys_setxattr -	.quad sys_lsetxattr -	.quad sys_fsetxattr -	.quad sys_getxattr -	.quad sys_lgetxattr	/* 230 */ -	.quad sys_fgetxattr -	.quad sys_listxattr -	.quad sys_llistxattr -	.quad sys_flistxattr -	.quad sys_removexattr	/* 235 */ -	.quad sys_lremovexattr -	.quad sys_fremovexattr -	.quad sys_tkill -	.quad sys_sendfile64  -	.quad compat_sys_futex		/* 240 */ -	.quad compat_sys_sched_setaffinity -	.quad compat_sys_sched_getaffinity -	.quad sys_set_thread_area -	.quad sys_get_thread_area -	.quad compat_sys_io_setup	/* 245 */ -	.quad sys_io_destroy -	.quad compat_sys_io_getevents -	.quad compat_sys_io_submit -	.quad sys_io_cancel -	.quad sys32_fadvise64		/* 250 */ -	.quad quiet_ni_syscall 	/* free_huge_pages */ -	.quad sys_exit_group -	.quad sys32_lookup_dcookie -	.quad sys_epoll_create -	.quad sys_epoll_ctl		/* 255 */ -	.quad sys_epoll_wait -	.quad sys_remap_file_pages -	.quad sys_set_tid_address -	.quad compat_sys_timer_create -	.quad compat_sys_timer_settime	/* 260 */ -	.quad compat_sys_timer_gettime -	.quad sys_timer_getoverrun -	.quad sys_timer_delete -	.quad compat_sys_clock_settime -	.quad compat_sys_clock_gettime	/* 265 */ -	.quad compat_sys_clock_getres -	.quad compat_sys_clock_nanosleep -	.quad compat_sys_statfs64 -	.quad compat_sys_fstatfs64 -	.quad sys_tgkill		/* 270 */ -	.quad compat_sys_utimes -	.quad sys32_fadvise64_64 -	.quad quiet_ni_syscall	/* sys_vserver */ -	.quad sys_mbind -	.quad compat_sys_get_mempolicy	/* 275 */ -	.quad sys_set_mempolicy -	.quad compat_sys_mq_open -	.quad sys_mq_unlink -	.quad compat_sys_mq_timedsend -	.quad compat_sys_mq_timedreceive	/* 280 */ -	.quad compat_sys_mq_notify -	.quad compat_sys_mq_getsetattr -	.quad compat_sys_kexec_load	/* reserved for kexec */ -	.quad compat_sys_waitid -	.quad quiet_ni_syscall		/* 285: sys_altroot */ -	.quad sys_add_key -	.quad sys_request_key -	.quad sys_keyctl -	.quad sys_ioprio_set -	.quad sys_ioprio_get		/* 290 */ -	.quad sys_inotify_init -	.quad sys_inotify_add_watch -	.quad sys_inotify_rm_watch -	.quad sys_migrate_pages -	.quad compat_sys_openat		/* 295 */ -	.quad sys_mkdirat -	.quad sys_mknodat -	.quad sys_fchownat -	.quad compat_sys_futimesat -	.quad sys32_fstatat		/* 300 */ -	.quad sys_unlinkat -	.quad sys_renameat -	.quad sys_linkat -	.quad sys_symlinkat -	.quad sys_readlinkat		/* 305 */ -	.quad sys_fchmodat -	.quad sys_faccessat -	.quad compat_sys_pselect6 -	.quad compat_sys_ppoll -	.quad sys_unshare		/* 310 */ -	.quad compat_sys_set_robust_list -	.quad compat_sys_get_robust_list -	.quad sys_splice -	.quad sys32_sync_file_range -	.quad sys_tee			/* 315 */ -	.quad compat_sys_vmsplice -	.quad compat_sys_move_pages -	.quad sys_getcpu -	.quad sys_epoll_pwait -	.quad compat_sys_utimensat	/* 320 */ -	.quad compat_sys_signalfd -	.quad sys_timerfd_create -	.quad sys_eventfd -	.quad sys32_fallocate -	.quad compat_sys_timerfd_settime	/* 325 */ -	.quad compat_sys_timerfd_gettime -	.quad compat_sys_signalfd4 -	.quad sys_eventfd2 -	.quad sys_epoll_create1 -	.quad sys_dup3				/* 330 */ -	.quad sys_pipe2 -	.quad sys_inotify_init1 -	.quad compat_sys_preadv -	.quad compat_sys_pwritev -	.quad compat_sys_rt_tgsigqueueinfo	/* 335 */ -	.quad sys_perf_event_open -	.quad compat_sys_recvmmsg -	.quad sys_fanotify_init -	.quad sys32_fanotify_mark -	.quad sys_prlimit64		/* 340 */ -ia32_syscall_end: diff --git a/arch/x86/ia32/ipc32.c b/arch/x86/ia32/ipc32.c deleted file mode 100644 index 29cdcd02ead..00000000000 --- a/arch/x86/ia32/ipc32.c +++ /dev/null @@ -1,54 +0,0 @@ -#include <linux/kernel.h> -#include <linux/spinlock.h> -#include <linux/list.h> -#include <linux/syscalls.h> -#include <linux/time.h> -#include <linux/sem.h> -#include <linux/msg.h> -#include <linux/shm.h> -#include <linux/ipc.h> -#include <linux/compat.h> -#include <asm/sys_ia32.h> - -asmlinkage long sys32_ipc(u32 call, int first, int second, int third, -			  compat_uptr_t ptr, u32 fifth) -{ -	int version; - -	version = call >> 16; /* hack for backward compatibility */ -	call &= 0xffff; - -	switch (call) { -	case SEMOP: -		/* struct sembuf is the same on 32 and 64bit :)) */ -		return sys_semtimedop(first, compat_ptr(ptr), second, NULL); -	case SEMTIMEDOP: -		return compat_sys_semtimedop(first, compat_ptr(ptr), second, -						compat_ptr(fifth)); -	case SEMGET: -		return sys_semget(first, second, third); -	case SEMCTL: -		return compat_sys_semctl(first, second, third, compat_ptr(ptr)); - -	case MSGSND: -		return compat_sys_msgsnd(first, second, third, compat_ptr(ptr)); -	case MSGRCV: -		return compat_sys_msgrcv(first, second, fifth, third, -					 version, compat_ptr(ptr)); -	case MSGGET: -		return sys_msgget((key_t) first, second); -	case MSGCTL: -		return compat_sys_msgctl(first, second, compat_ptr(ptr)); - -	case SHMAT: -		return compat_sys_shmat(first, second, third, version, -					compat_ptr(ptr)); -	case SHMDT: -		return sys_shmdt(compat_ptr(ptr)); -	case SHMGET: -		return sys_shmget(first, (unsigned)second, third); -	case SHMCTL: -		return compat_sys_shmctl(first, second, compat_ptr(ptr)); -	} -	return -ENOSYS; -} diff --git a/arch/x86/ia32/nosyscall.c b/arch/x86/ia32/nosyscall.c new file mode 100644 index 00000000000..51ecd5b4e78 --- /dev/null +++ b/arch/x86/ia32/nosyscall.c @@ -0,0 +1,7 @@ +#include <linux/kernel.h> +#include <linux/errno.h> + +long compat_ni_syscall(void) +{ +	return -ENOSYS; +} diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 849813f398e..8e0ceecdc95 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c @@ -28,7 +28,6 @@  #include <linux/syscalls.h>  #include <linux/times.h>  #include <linux/utsname.h> -#include <linux/smp_lock.h>  #include <linux/mm.h>  #include <linux/uio.h>  #include <linux/poll.h> @@ -44,7 +43,7 @@  #include <asm/mman.h>  #include <asm/types.h>  #include <asm/uaccess.h> -#include <asm/atomic.h> +#include <linux/atomic.h>  #include <asm/vgtod.h>  #include <asm/sys_ia32.h> @@ -72,8 +71,8 @@ static int cp_stat64(struct stat64 __user *ubuf, struct kstat *stat)  {  	typeof(ubuf->st_uid) uid = 0;  	typeof(ubuf->st_gid) gid = 0; -	SET_UID(uid, stat->uid); -	SET_GID(gid, stat->gid); +	SET_UID(uid, from_kuid_munged(current_user_ns(), stat->uid)); +	SET_GID(gid, from_kgid_munged(current_user_ns(), stat->gid));  	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||  	    __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||  	    __put_user(stat->ino, &ubuf->__st_ino) || @@ -167,239 +166,12 @@ asmlinkage long sys32_mmap(struct mmap_arg_struct32 __user *arg)  			       a.offset>>PAGE_SHIFT);  } -asmlinkage long sys32_mprotect(unsigned long start, size_t len, -			       unsigned long prot) -{ -	return sys_mprotect(start, len, prot); -} - -asmlinkage long sys32_rt_sigaction(int sig, struct sigaction32 __user *act, -				   struct sigaction32 __user *oact, -				   unsigned int sigsetsize) -{ -	struct k_sigaction new_ka, old_ka; -	int ret; -	compat_sigset_t set32; - -	/* XXX: Don't preclude handling different sized sigset_t's.  */ -	if (sigsetsize != sizeof(compat_sigset_t)) -		return -EINVAL; - -	if (act) { -		compat_uptr_t handler, restorer; - -		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -		    __get_user(handler, &act->sa_handler) || -		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || -		    __get_user(restorer, &act->sa_restorer) || -		    __copy_from_user(&set32, &act->sa_mask, -				     sizeof(compat_sigset_t))) -			return -EFAULT; -		new_ka.sa.sa_handler = compat_ptr(handler); -		new_ka.sa.sa_restorer = compat_ptr(restorer); - -		/* -		 * FIXME: here we rely on _COMPAT_NSIG_WORS to be >= -		 * than _NSIG_WORDS << 1 -		 */ -		switch (_NSIG_WORDS) { -		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6] -				| (((long)set32.sig[7]) << 32); -		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4] -				| (((long)set32.sig[5]) << 32); -		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2] -				| (((long)set32.sig[3]) << 32); -		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0] -				| (((long)set32.sig[1]) << 32); -		} -	} - -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - -	if (!ret && oact) { -		/* -		 * FIXME: here we rely on _COMPAT_NSIG_WORS to be >= -		 * than _NSIG_WORDS << 1 -		 */ -		switch (_NSIG_WORDS) { -		case 4: -			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32); -			set32.sig[6] = old_ka.sa.sa_mask.sig[3]; -		case 3: -			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32); -			set32.sig[4] = old_ka.sa.sa_mask.sig[2]; -		case 2: -			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32); -			set32.sig[2] = old_ka.sa.sa_mask.sig[1]; -		case 1: -			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32); -			set32.sig[0] = old_ka.sa.sa_mask.sig[0]; -		} -		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), -			       &oact->sa_handler) || -		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), -			       &oact->sa_restorer) || -		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || -		    __copy_to_user(&oact->sa_mask, &set32, -				   sizeof(compat_sigset_t))) -			return -EFAULT; -	} - -	return ret; -} - -asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 __user *act, -				struct old_sigaction32 __user *oact) -{ -	struct k_sigaction new_ka, old_ka; -	int ret; - -	if (act) { -		compat_old_sigset_t mask; -		compat_uptr_t handler, restorer; - -		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || -		    __get_user(handler, &act->sa_handler) || -		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || -		    __get_user(restorer, &act->sa_restorer) || -		    __get_user(mask, &act->sa_mask)) -			return -EFAULT; - -		new_ka.sa.sa_handler = compat_ptr(handler); -		new_ka.sa.sa_restorer = compat_ptr(restorer); - -		siginitset(&new_ka.sa.sa_mask, mask); -	} - -	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - -	if (!ret && oact) { -		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || -		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), -			       &oact->sa_handler) || -		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), -			       &oact->sa_restorer) || -		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || -		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) -			return -EFAULT; -	} - -	return ret; -} - -asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, -				     compat_sigset_t __user *oset, -				     unsigned int sigsetsize) -{ -	sigset_t s; -	compat_sigset_t s32; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	if (set) { -		if (copy_from_user(&s32, set, sizeof(compat_sigset_t))) -			return -EFAULT; -		switch (_NSIG_WORDS) { -		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); -		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); -		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); -		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); -		} -	} -	set_fs(KERNEL_DS); -	ret = sys_rt_sigprocmask(how, -				 set ? (sigset_t __user *)&s : NULL, -				 oset ? (sigset_t __user *)&s : NULL, -				 sigsetsize); -	set_fs(old_fs); -	if (ret) -		return ret; -	if (oset) { -		switch (_NSIG_WORDS) { -		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; -		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; -		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; -		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; -		} -		if (copy_to_user(oset, &s32, sizeof(compat_sigset_t))) -			return -EFAULT; -	} -	return 0; -} - -asmlinkage long sys32_alarm(unsigned int seconds) -{ -	return alarm_setitimer(seconds); -} - -asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int *stat_addr, +asmlinkage long sys32_waitpid(compat_pid_t pid, unsigned int __user *stat_addr,  			      int options)  {  	return compat_sys_wait4(pid, stat_addr, options, NULL);  } -/* 32-bit timeval and related flotsam.  */ - -asmlinkage long sys32_sysfs(int option, u32 arg1, u32 arg2) -{ -	return sys_sysfs(option, arg1, arg2); -} - -asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, -				    struct compat_timespec __user *interval) -{ -	struct timespec t; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	set_fs(KERNEL_DS); -	ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); -	set_fs(old_fs); -	if (put_compat_timespec(&t, interval)) -		return -EFAULT; -	return ret; -} - -asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, -				    compat_size_t sigsetsize) -{ -	sigset_t s; -	compat_sigset_t s32; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	set_fs(KERNEL_DS); -	ret = sys_rt_sigpending((sigset_t __user *)&s, sigsetsize); -	set_fs(old_fs); -	if (!ret) { -		switch (_NSIG_WORDS) { -		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; -		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2]; -		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1]; -		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0]; -		} -		if (copy_to_user(set, &s32, sizeof(compat_sigset_t))) -			return -EFAULT; -	} -	return ret; -} - -asmlinkage long sys32_rt_sigqueueinfo(int pid, int sig, -				      compat_siginfo_t __user *uinfo) -{ -	siginfo_t info; -	int ret; -	mm_segment_t old_fs = get_fs(); - -	if (copy_siginfo_from_user32(&info, uinfo)) -		return -EFAULT; -	set_fs(KERNEL_DS); -	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); -	set_fs(old_fs); -	return ret; -} -  /* warning: next two assume little endian */  asmlinkage long sys32_pread(unsigned int fd, char __user *ubuf, u32 count,  			    u32 poslo, u32 poshi) @@ -416,79 +188,10 @@ asmlinkage long sys32_pwrite(unsigned int fd, const char __user *ubuf,  } -asmlinkage long sys32_personality(unsigned long personality) -{ -	int ret; - -	if (personality(current->personality) == PER_LINUX32 && -		personality == PER_LINUX) -		personality = PER_LINUX32; -	ret = sys_personality(personality); -	if (ret == PER_LINUX32) -		ret = PER_LINUX; -	return ret; -} - -asmlinkage long sys32_sendfile(int out_fd, int in_fd, -			       compat_off_t __user *offset, s32 count) -{ -	mm_segment_t old_fs = get_fs(); -	int ret; -	off_t of; - -	if (offset && get_user(of, offset)) -		return -EFAULT; - -	set_fs(KERNEL_DS); -	ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, -			   count); -	set_fs(old_fs); - -	if (offset && put_user(of, offset)) -		return -EFAULT; -	return ret; -} - -asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv, -			     compat_uptr_t __user *envp, struct pt_regs *regs) -{ -	long error; -	char *filename; - -	filename = getname(name); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		return error; -	error = compat_do_execve(filename, argv, envp, regs); -	putname(filename); -	return error; -} - -asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, -			    struct pt_regs *regs) -{ -	void __user *parent_tid = (void __user *)regs->dx; -	void __user *child_tid = (void __user *)regs->di; - -	if (!newsp) -		newsp = regs->sp; -	return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); -} -  /*   * Some system calls that need sign extended arguments. This could be   * done by a generic wrapper.   */ -long sys32_lseek(unsigned int fd, int offset, unsigned int whence) -{ -	return sys_lseek(fd, offset, whence); -} - -long sys32_kill(int pid, int sig) -{ -	return sys_kill(pid, sig); -} -  long sys32_fadvise64_64(int fd, __u32 offset_low, __u32 offset_high,  			__u32 len_low, __u32 len_high, int advice)  { @@ -512,12 +215,6 @@ long sys32_vm86_warning(void)  	return -ENOSYS;  } -long sys32_lookup_dcookie(u32 addr_low, u32 addr_high, -			  char __user *buf, size_t len) -{ -	return sys_lookup_dcookie(((u64)addr_high << 32) | addr_low, buf, len); -} -  asmlinkage ssize_t sys32_readahead(int fd, unsigned off_lo, unsigned off_hi,  				   size_t count)  { @@ -546,12 +243,3 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_lo,  	return sys_fallocate(fd, mode, ((u64)offset_hi << 32) | offset_lo,  			     ((u64)len_hi << 32) | len_lo);  } - -asmlinkage long sys32_fanotify_mark(int fanotify_fd, unsigned int flags, -				    u32 mask_lo, u32 mask_hi, -				    int fd, const char  __user *pathname) -{ -	return sys_fanotify_mark(fanotify_fd, flags, -				 ((u64)mask_hi << 32) | mask_lo, -				 fd, pathname); -} diff --git a/arch/x86/ia32/syscall_ia32.c b/arch/x86/ia32/syscall_ia32.c new file mode 100644 index 00000000000..4754ba0f5d9 --- /dev/null +++ b/arch/x86/ia32/syscall_ia32.c @@ -0,0 +1,25 @@ +/* System call table for ia32 emulation. */ + +#include <linux/linkage.h> +#include <linux/sys.h> +#include <linux/cache.h> +#include <asm/asm-offsets.h> + +#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void compat(void) ; +#include <asm/syscalls_32.h> +#undef __SYSCALL_I386 + +#define __SYSCALL_I386(nr, sym, compat) [nr] = compat, + +typedef void (*sys_call_ptr_t)(void); + +extern void compat_ni_syscall(void); + +const sys_call_ptr_t ia32_sys_call_table[__NR_ia32_syscall_max+1] = { +	/* +	 * Smells like a compiler bug -- it doesn't work +	 * when the & below is removed. +	 */ +	[0 ... __NR_ia32_syscall_max] = &compat_ni_syscall, +#include <asm/syscalls_32.h> +};  | 
