Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9786a8f3 authored by Bodo Stroesser's avatar Bodo Stroesser Committed by Linus Torvalds
Browse files

[PATCH] uml: Proper clone support for skas0



This patch implements the clone-stub mechanism, which allows skas0 to run
with proc_mm==0, even if the clib in UML uses modify_ldt.

Note: There is a bug in skas3.v7 host patch, that avoids UML-skas from
running properly on a SMP-box.  In full skas3, I never really saw problems,
but in skas0 they showed up.

More commentary by jdike - What this patch does is makes sure that the host
parent of each new host process matches the UML parent of the corresponding
UML process.  This ensures that any changed LDTs are inherited.  This is
done by having clone actually called by the UML process from its stub,
rather than by the kernel.  We have special syscall stubs that are loaded
onto the stub code page because that code must be completely
self-contained.  These stubs are given C interfaces, and used like normal C
functions, but there are subtleties.  Principally, we have to be careful
about stack variables in stub_clone_handler after the clone.  The code is
written so that there aren't any - everything boils down to a fixed
address.  If there were any locals, references to them after the clone
would be wrong because the stack just changed.

Signed-off-by: default avatarBodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d67b569f
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -10,9 +10,56 @@
#include <asm/unistd.h>

extern void stub_segv_handler(int sig);
extern void stub_clone_handler(void);

#define STUB_SYSCALL_RET EAX
#define STUB_MMAP_NR __NR_mmap2
#define MMAP_OFFSET(o) ((o) >> PAGE_SHIFT)

static inline long stub_syscall2(long syscall, long arg1, long arg2)
{
	long ret;

	__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
	__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
	__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
	__asm__("int $0x80;" : : : "%eax");
	__asm__ __volatile__("movl %%eax, %0; " : "=g" (ret) :);
	return(ret);
}

static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
{
	__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
	return(stub_syscall2(syscall, arg1, arg2));
}

static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
				 long arg4)
{
	__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
	return(stub_syscall3(syscall, arg1, arg2, arg3));
}

static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
				 long arg4, long arg5, long arg6)
{
	long ret;
	__asm__("movl %0, %%eax; " : : "g" (syscall) : "%eax");
	__asm__("movl %0, %%ebx; " : : "g" (arg1) : "%ebx");
	__asm__("movl %0, %%ecx; " : : "g" (arg2) : "%ecx");
	__asm__("movl %0, %%edx; " : : "g" (arg3) : "%edx");
	__asm__("movl %0, %%esi; " : : "g" (arg4) : "%esi");
	__asm__("movl %0, %%edi; " : : "g" (arg5) : "%edi");
	__asm__ __volatile__("pushl %%ebp ; movl %1, %%ebp; "
		"int $0x80; popl %%ebp ; "
		"movl %%eax, %0; " : "=g" (ret) : "g" (arg6) : "%eax");
	return(ret);
}

static inline void trap_myself(void)
{
	__asm("int3");
}

#endif
+39 −0
Original line number Diff line number Diff line
@@ -11,9 +11,48 @@
#include <sysdep/ptrace_user.h>

extern void stub_segv_handler(int sig);
extern void stub_clone_handler(void);

#define STUB_SYSCALL_RET PT_INDEX(RAX)
#define STUB_MMAP_NR __NR_mmap
#define MMAP_OFFSET(o) (o)

static inline long stub_syscall2(long syscall, long arg1, long arg2)
{
	long ret;

	__asm__("movq %0, %%rsi; " : : "g" (arg2) : "%rsi");
	__asm__("movq %0, %%rdi; " : : "g" (arg1) : "%rdi");
	__asm__("movq %0, %%rax; " : : "g" (syscall) : "%rax");
	__asm__("syscall;" : : : "%rax", "%r11", "%rcx");
	__asm__ __volatile__("movq %%rax, %0; " : "=g" (ret) :);
	return(ret);
}

static inline long stub_syscall3(long syscall, long arg1, long arg2, long arg3)
{
	__asm__("movq %0, %%rdx; " : : "g" (arg3) : "%rdx");
	return(stub_syscall2(syscall, arg1, arg2));
}

static inline long stub_syscall4(long syscall, long arg1, long arg2, long arg3,
				 long arg4)
{
	__asm__("movq %0, %%r10; " : : "g" (arg4) : "%r10");
	return(stub_syscall3(syscall, arg1, arg2, arg3));
}

static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3,
				 long arg4, long arg5, long arg6)
{
	__asm__("movq %0, %%r9; " : : "g" (arg6) : "%r9");
	__asm__("movq %0, %%r8; " : : "g" (arg5) : "%r8");
	return(stub_syscall4(syscall, arg1, arg2, arg3, arg4));
}

static inline void trap_myself(void)
{
	__asm("int3");
}

#endif
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ extern void timer(void);
extern void switch_timers(int to_real);
extern void idle_sleep(int secs);
extern void enable_timer(void);
extern void prepare_timer(void * ptr);
extern void disable_timer(void);
extern unsigned long time_lock(void);
extern void time_unlock(unsigned long);
+5 −2
Original line number Diff line number Diff line
@@ -3,11 +3,14 @@
# Licensed under the GPL
#

obj-y := exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \
	syscall_kern.o syscall_user.o tlb.o trap_user.o uaccess.o \

subdir- := util

USER_OBJS := process.o
USER_OBJS := process.o clone.o

include arch/um/scripts/Makefile.rules

# clone.o is in the stub, so it can't be built with profiling
$(obj)/clone.o : c_flags = -Wp,-MD,$(depfile) $(call unprofile,$(USER_CFLAGS))
+44 −0
Original line number Diff line number Diff line
#include <sched.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <asm/unistd.h>
#include <asm/page.h>
#include "ptrace_user.h"
#include "skas.h"
#include "stub-data.h"
#include "uml-config.h"
#include "sysdep/stub.h"

/* This is in a separate file because it needs to be compiled with any
 * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled
 */
void __attribute__ ((__section__ (".__syscall_stub")))
stub_clone_handler(void)
{
	long err;
	struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA;

	err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD,
			    UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 -
			    sizeof(void *));
	if(err != 0)
		goto out;

	err = stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
	if(err)
		goto out;

	err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL,
			    (long) &from->timer, 0);
	if(err)
		goto out;

	err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE,
			    PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
			    from->fd, from->offset);
 out:
	/* save current result. Parent: pid; child: retcode of mmap */
	from->err = err;
	trap_myself();
}
Loading