Commit 97956605 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus-3.6-rc-final' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml

Pull UML fixes from Richard Weinberger.

* 'for-linus-3.6-rc-final' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml:
  um: Preinclude include/linux/kern_levels.h
  um: Fix IPC on um
  um: kill thread->forking
  um: let signal_delivered() do SIGTRAP on singlestepping into handler
  um: don't leak floating point state and segment registers on execve()
  um: take cleaning singlestep to start_thread()
parents c3a086e6 9429ec96
...@@ -20,14 +20,6 @@ struct mm_struct; ...@@ -20,14 +20,6 @@ struct mm_struct;
struct thread_struct { struct thread_struct {
struct task_struct *saved_task; struct task_struct *saved_task;
/*
* This flag is set to 1 before calling do_fork (and analyzed in
* copy_thread) to mark that we are begin called from userspace (fork /
* vfork / clone), and reset to 0 after. It is left to 0 when called
* from kernelspace (i.e. kernel_thread() or fork_idle(),
* as of 2.6.11).
*/
int forking;
struct pt_regs regs; struct pt_regs regs;
int singlestep_syscall; int singlestep_syscall;
void *fault_addr; void *fault_addr;
...@@ -58,7 +50,6 @@ struct thread_struct { ...@@ -58,7 +50,6 @@ struct thread_struct {
#define INIT_THREAD \ #define INIT_THREAD \
{ \ { \
.forking = 0, \
.regs = EMPTY_REGS, \ .regs = EMPTY_REGS, \
.fault_addr = NULL, \ .fault_addr = NULL, \
.prev_sched = NULL, \ .prev_sched = NULL, \
......
...@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK); ...@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT); DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC); DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
DEFINE_STR(UM_KERN_ERR, KERN_ERR);
DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
DEFINE_STR(UM_KERN_INFO, KERN_INFO);
DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
DEFINE_STR(UM_KERN_CONT, KERN_CONT);
DEFINE(UM_ELF_CLASS, ELF_CLASS); DEFINE(UM_ELF_CLASS, ELF_CLASS);
DEFINE(UM_ELFCLASS32, ELFCLASS32); DEFINE(UM_ELFCLASS32, ELFCLASS32);
DEFINE(UM_ELFCLASS64, ELFCLASS64); DEFINE(UM_ELFCLASS64, ELFCLASS64);
......
...@@ -26,6 +26,17 @@ ...@@ -26,6 +26,17 @@
extern void panic(const char *fmt, ...) extern void panic(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
/* Requires preincluding include/linux/kern_levels.h */
#define UM_KERN_EMERG KERN_EMERG
#define UM_KERN_ALERT KERN_ALERT
#define UM_KERN_CRIT KERN_CRIT
#define UM_KERN_ERR KERN_ERR
#define UM_KERN_WARNING KERN_WARNING
#define UM_KERN_NOTICE KERN_NOTICE
#define UM_KERN_INFO KERN_INFO
#define UM_KERN_DEBUG KERN_DEBUG
#define UM_KERN_CONT KERN_CONT
#ifdef UML_CONFIG_PRINTK #ifdef UML_CONFIG_PRINTK
extern int printk(const char *fmt, ...) extern int printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2))); __attribute__ ((format (printf, 1, 2)));
......
...@@ -39,34 +39,21 @@ void flush_thread(void) ...@@ -39,34 +39,21 @@ void flush_thread(void)
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{ {
get_safe_registers(regs->regs.gp, regs->regs.fp);
PT_REGS_IP(regs) = eip; PT_REGS_IP(regs) = eip;
PT_REGS_SP(regs) = esp; PT_REGS_SP(regs) = esp;
} current->ptrace &= ~PT_DTRACE;
EXPORT_SYMBOL(start_thread);
static long execve1(const char *file,
const char __user *const __user *argv,
const char __user *const __user *env)
{
long error;
error = do_execve(file, argv, env, &current->thread.regs);
if (error == 0) {
task_lock(current);
current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1 #ifdef SUBARCH_EXECVE1
SUBARCH_EXECVE1(&current->thread.regs.regs); SUBARCH_EXECVE1(regs->regs);
#endif #endif
task_unlock(current);
}
return error;
} }
EXPORT_SYMBOL(start_thread);
long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
{ {
long err; long err;
err = execve1(file, argv, env); err = do_execve(file, argv, env, &current->thread.regs);
if (!err) if (!err)
UML_LONGJMP(current->thread.exec_buf, 1); UML_LONGJMP(current->thread.exec_buf, 1);
return err; return err;
...@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv, ...@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
filename = getname(file); filename = getname(file);
error = PTR_ERR(filename); error = PTR_ERR(filename);
if (IS_ERR(filename)) goto out; if (IS_ERR(filename)) goto out;
error = execve1(filename, argv, env); error = do_execve(filename, argv, env, &current->thread.regs);
putname(filename); putname(filename);
out: out:
return error; return error;
......
...@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, ...@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
struct pt_regs *regs) struct pt_regs *regs)
{ {
void (*handler)(void); void (*handler)(void);
int kthread = current->flags & PF_KTHREAD;
int ret = 0; int ret = 0;
p->thread = (struct thread_struct) INIT_THREAD; p->thread = (struct thread_struct) INIT_THREAD;
if (current->thread.forking) { if (!kthread) {
memcpy(&p->thread.regs.regs, &regs->regs, memcpy(&p->thread.regs.regs, &regs->regs,
sizeof(p->thread.regs.regs)); sizeof(p->thread.regs.regs));
PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0); PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
...@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, ...@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
handler = fork_handler; handler = fork_handler;
arch_copy_thread(&current->thread.arch, &p->thread.arch); arch_copy_thread(&current->thread.arch, &p->thread.arch);
} } else {
else {
get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
p->thread.request.u.thread = current->thread.request.u.thread; p->thread.request.u.thread = current->thread.request.u.thread;
handler = new_thread_handler; handler = new_thread_handler;
...@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, ...@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
new_thread(task_stack_page(p), &p->thread.switch_buf, handler); new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
if (current->thread.forking) { if (!kthread) {
clear_flushed_tls(p); clear_flushed_tls(p);
/* /*
......
...@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info) struct k_sigaction *ka, siginfo_t *info)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int singlestep = 0;
unsigned long sp; unsigned long sp;
int err; int err;
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
singlestep = 1;
/* Did we come from a system call? */ /* Did we come from a system call? */
if (PT_REGS_SYSCALL_NR(regs) >= 0) { if (PT_REGS_SYSCALL_NR(regs) >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
if (err) if (err)
force_sigsegv(signr, current); force_sigsegv(signr, current);
else else
signal_delivered(signr, info, ka, regs, 0); signal_delivered(signr, info, ka, regs, singlestep);
} }
static int kern_do_signal(struct pt_regs *regs) static int kern_do_signal(struct pt_regs *regs)
......
...@@ -17,25 +17,25 @@ ...@@ -17,25 +17,25 @@
long sys_fork(void) long sys_fork(void)
{ {
long ret; return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
current->thread.forking = 1;
ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL); &current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0;
return ret;
} }
long sys_vfork(void) long sys_vfork(void)
{ {
long ret; return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
current->thread.forking = 1;
ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
UPT_SP(&current->thread.regs.regs), UPT_SP(&current->thread.regs.regs),
&current->thread.regs, 0, NULL, NULL); &current->thread.regs, 0, NULL, NULL);
current->thread.forking = 0; }
return ret;
long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid)
{
if (!newsp)
newsp = UPT_SP(&current->thread.regs.regs);
return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
child_tid);
} }
long old_mmap(unsigned long addr, unsigned long len, long old_mmap(unsigned long addr, unsigned long len,
......
...@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS)) ...@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m) $(USER_SINGLE_OBJS))
USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file)) USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
$(USER_OBJS:.o=.%): \ $(USER_OBJS:.o=.%): \
c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o) c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o)
# These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
# using it directly. # using it directly.
......
...@@ -21,6 +21,7 @@ config 64BIT ...@@ -21,6 +21,7 @@ config 64BIT
config X86_32 config X86_32
def_bool !64BIT def_bool !64BIT
select HAVE_AOUT select HAVE_AOUT
select ARCH_WANT_IPC_PARSE_VERSION
config X86_64 config X86_64
def_bool 64BIT def_bool 64BIT
......
...@@ -7,9 +7,6 @@ ...@@ -7,9 +7,6 @@
#define DEFINE(sym, val) \ #define DEFINE(sym, val) \
asm volatile("\n->" #sym " %0 " #val : : "i" (val)) asm volatile("\n->" #sym " %0 " #val : : "i" (val))
#define STR(x) #x
#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
#define BLANK() asm volatile("\n->" : : ) #define BLANK() asm volatile("\n->" : : )
#define OFFSET(sym, str, mem) \ #define OFFSET(sym, str, mem) \
......
extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid);
#ifdef __i386__ #ifdef __i386__
#include "syscalls_32.h" #include "syscalls_32.h"
#else #else
......
...@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, ...@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) 0; PT_REGS_DX(regs) = (unsigned long) 0;
PT_REGS_CX(regs) = (unsigned long) 0; PT_REGS_CX(regs) = (unsigned long) 0;
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
return 0; return 0;
} }
...@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) &frame->info; PT_REGS_DX(regs) = (unsigned long) &frame->info;
PT_REGS_CX(regs) = (unsigned long) &frame->uc; PT_REGS_CX(regs) = (unsigned long) &frame->uc;
if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
ptrace_notify(SIGTRAP);
return 0; return 0;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#define ptregs_execve sys_execve #define ptregs_execve sys_execve
#define ptregs_iopl sys_iopl #define ptregs_iopl sys_iopl
#define ptregs_vm86old sys_vm86old #define ptregs_vm86old sys_vm86old
#define ptregs_clone sys_clone #define ptregs_clone i386_clone
#define ptregs_vm86 sys_vm86 #define ptregs_vm86 sys_vm86
#define ptregs_sigaltstack sys_sigaltstack #define ptregs_sigaltstack sys_sigaltstack
#define ptregs_vfork sys_vfork #define ptregs_vfork sys_vfork
......
...@@ -3,37 +3,24 @@ ...@@ -3,37 +3,24 @@
* Licensed under the GPL * Licensed under the GPL
*/ */
#include "linux/sched.h" #include <linux/syscalls.h>
#include "linux/shm.h" #include <sysdep/syscalls.h>
#include "linux/ipc.h"
#include "linux/syscalls.h"
#include "asm/mman.h"
#include "asm/uaccess.h"
#include "asm/unistd.h"
/* /*
* The prototype on i386 is: * The prototype on i386 is:
* *
* int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr) * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
* *
* and the "newtls" arg. on i386 is read by copy_thread directly from the * and the "newtls" arg. on i386 is read by copy_thread directly from the
* register saved on the stack. * register saved on the stack.
*/ */
long sys_clone(unsigned long clone_flags, unsigned long newsp, long i386_clone(unsigned long clone_flags, unsigned long newsp,
int __user *parent_tid, void *newtls, int __user *child_tid) int __user *parent_tid, void *newtls, int __user *child_tid)
{ {
long ret; return sys_clone(clone_flags, newsp, parent_tid, child_tid);
if (!newsp)
newsp = UPT_SP(&current->thread.regs.regs);
current->thread.forking = 1;
ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
child_tid);
current->thread.forking = 0;
return ret;
} }
long sys_sigaction(int sig, const struct old_sigaction __user *act, long sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact) struct old_sigaction __user *oact)
{ {
......
...@@ -5,12 +5,9 @@ ...@@ -5,12 +5,9 @@
* Licensed under the GPL * Licensed under the GPL
*/ */
#include "linux/linkage.h" #include <linux/sched.h>
#include "linux/personality.h" #include <asm/prctl.h> /* XXX This should get the constants from libc */
#include "linux/utsname.h" #include <os.h>
#include "asm/prctl.h" /* XXX This should get the constants from libc */
#include "asm/uaccess.h"
#include "os.h"
long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
{ {
...@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr) ...@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
return arch_prctl(current, code, (unsigned long __user *) addr); return arch_prctl(current, code, (unsigned long __user *) addr);
} }
long sys_clone(unsigned long clone_flags, unsigned long newsp,
void __user *parent_tid, void __user *child_tid)
{
long ret;
if (!newsp)
newsp = UPT_SP(&current->thread.regs.regs);
current->thread.forking = 1;
ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
child_tid);
current->thread.forking = 0;
return ret;
}
void arch_switch_to(struct task_struct *to) void arch_switch_to(struct task_struct *to)
{ {
if ((to->thread.arch.fs == 0) || (to->mm == NULL)) if ((to->thread.arch.fs == 0) || (to->mm == NULL))
......
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