[uml-devel] [-mm Patch] arch/um/kernel/mem.c: fix a shadowed variable
Fix a shadowed variable in arch/um/kernel/mem.c, since there is a global variable has the same name. Cc: Jeff Dike <[EMAIL PROTECTED]> Signed-off-by: WANG Cong <[EMAIL PROTECTED]> --- Index: linux/arch/um/kernel/mem.c === --- linux.orig/arch/um/kernel/mem.c +++ linux/arch/um/kernel/mem.c @@ -299,7 +299,7 @@ void show_mem(void) { int pfn, total = 0, reserved = 0; int shared = 0, cached = 0; - int highmem = 0; + int high_mem = 0; struct page *page; printk(KERN_INFO "Mem-info:\n"); @@ -311,7 +311,7 @@ void show_mem(void) page = pfn_to_page(pfn); total++; if (PageHighMem(page)) - highmem++; + high_mem++; if (PageReserved(page)) reserved++; else if (PageSwapCache(page)) @@ -320,7 +320,7 @@ void show_mem(void) shared += page_count(page) - 1; } printk(KERN_INFO "%d pages of RAM\n", total); - printk(KERN_INFO "%d pages of HIGHMEM\n", highmem); + printk(KERN_INFO "%d pages of HIGHMEM\n", high_mem); printk(KERN_INFO "%d reserved pages\n", reserved); printk(KERN_INFO "%d pages shared\n", shared); printk(KERN_INFO "%d pages swap cached\n", cached); - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[uml-devel] [-mm Patch] arch/um/kernel/initrd.c: fix a missed conversion specifier
Fix a missed conversion specifier of a printk in arch/um/kernel/initrd.c. Signed-off-by: WANG Cong <[EMAIL PROTECTED]> Cc: Jeff Dike <[EMAIL PROTECTED]> --- Index: linux/arch/um/kernel/initrd.c === --- linux.orig/arch/um/kernel/initrd.c +++ linux/arch/um/kernel/initrd.c @@ -32,7 +32,7 @@ static int __init read_initrd(void) * ask for no memory. */ if (size == 0) { - printk(KERN_ERR "\"%\" is a zero-size initrd\n"); + printk(KERN_ERR "\"%s\" is a zero-size initrd\n", initrd); return 0; } - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[uml-devel] [RFC PATCH 4/11] SKAS4 - Work around compat PTRACE_GETSIGINFO bug
copy_siginfo_to_user correctly strips off the high bits of si->si_code before copying it to userspace. Unfortunately, ptrace32_siginfo calls copy_siginfo_to_user to put the siginfo into a temporary userspace buffer and counts on the high bits still being present so that it may initialize the union in the final 32-bit siginfo. This patch works around this problem by having copy_siginfo_to_user copy si->si_code intact to userspace. This introduces a bug in native 64-bit PTRACE_GETSIGINFO, but I haven't noticed anything being bothered by it. diff --git a/kernel/signal.c b/kernel/signal.c index 1e067a1..28813b1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2088,7 +2088,7 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) */ err = __put_user(from->si_signo, &to->si_signo); err |= __put_user(from->si_errno, &to->si_errno); - err |= __put_user((short)from->si_code, &to->si_code); + err |= __put_user(from->si_code, &to->si_code); switch (from->si_code & __SI_MASK) { case __SI_KILL: err |= __put_user(from->si_pid, &to->si_pid); - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[uml-devel] [RFC PATCH 8/11] SKAS4 - stub management preparation
Tidy the existing stub code so that the skas4 code can be dropped in. diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 484e68f..efda5e1 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -40,35 +40,69 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { + unsigned long *stub_entry; + get_safe_registers(syscall_regs); + stub_entry = &batch_syscall_stub; + syscall_regs[REGS_IP_INDEX] = STUB_CODE + - ((unsigned long) &batch_syscall_stub - + ((unsigned long) stub_entry - (unsigned long) &__syscall_stub_start); return 0; } __initcall(init_syscall_regs); -extern int proc_mm; +static int syscall_stub_done(unsigned long stack) +{ + unsigned long *syscall, *data, offset; + int ret, n; + + /* +* When the stub stops, we find the following values on the +* beginning of the stack: +* (long) return_value +* (long) offset to failed sycall data (0 if no error) +*/ + ret = *((unsigned long *) stack); + offset = *((unsigned long *) stack + 1); + if (offset == 0) + return 0; -int single_count = 0; -int multi_count = 0; -int multi_op_count = 0; + data = (unsigned long *)(stack + offset - STUB_DATA); + printk(UM_KERN_ERR "syscall_stub_done : ret = %d, offset = %ld, " + "data = %p\n", ret, offset, data); + syscall = (unsigned long *)((unsigned long)data + data[0]); + printk(UM_KERN_ERR "syscall_stub_done : syscall %ld failed, " + "return value = 0x%x, expected return value = 0x%lx\n", + syscall[0], ret, syscall[7]); + printk(UM_KERN_ERR "syscall parameters: " + "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", + syscall[1], syscall[2], syscall[3], + syscall[4], syscall[5], syscall[6]); + for (n = 1; n < data[0]/sizeof(long); n++) { + if (n == 1) + printk(UM_KERN_ERR "additional syscall " + "data:"); + if (n % 4 == 1) + printk("\n" UM_KERN_ERR " "); + printk(" 0x%lx", data[n]); + } + if (n > 1) + printk("\n"); -static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) + return ret; +} + +static long do_syscall_stub(struct mm_id *mm_idp, void **addr) { - int n, i; - long ret, offset; - unsigned long * data; - unsigned long * syscall; - int err, pid = mm_idp->u.pid; + long ret; + int n, i, err, pid = mm_idp->u.pid; if (proc_mm) /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; - multi_count++; - n = ptrace_setregs(pid, syscall_regs); if (n < 0) { printk(UM_KERN_ERR "Registers - \n"); @@ -85,52 +119,39 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) wait_stub_done(pid); - /* -* When the stub stops, we find the following values on the -* beginning of the stack: -* (long )return_value -* (long )offset to failed sycall-data (0, if no error) -*/ - ret = *((unsigned long *) mm_idp->stack); - offset = *((unsigned long *) mm_idp->stack + 1); - if (offset) { - data = (unsigned long *)(mm_idp->stack + offset - STUB_DATA); - printk(UM_KERN_ERR "do_syscall_stub : ret = %ld, offset = %ld, " - "data = %p\n", ret, offset, data); - syscall = (unsigned long *)((unsigned long)data + data[0]); - printk(UM_KERN_ERR "do_syscall_stub: syscall %ld failed, " - "return value = 0x%lx, expected return value = 0x%lx\n", - syscall[0], ret, syscall[7]); - printk(UM_KERN_ERR "syscall parameters: " - "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", - syscall[1], syscall[2], syscall[3], - syscall[4], syscall[5], syscall[6]); - for (n = 1; n < data[0]/sizeof(long); n++) { - if (n == 1) - printk(UM_KERN_ERR "additional syscall " - "data:"); - if (n % 4 == 1) - printk("\n" UM_KERN_ERR " "); - printk(" 0x%lx", data[n]); - } - if (n > 1) - printk("\n"); - } - else ret = 0; + ret = syscall_stub_done(mm_idp->stack); *addr = check_init_stack(mm_idp, NULL); return ret; } -long run_syscall_stub(struct mm_id * mm_idp, int syscall, +static int flush_syscalls(struct mm_id *mm_idp, void **addr, int extra) +{ + un
[uml-devel] [RFC PATCH 5/11] SKAS4 - start_up.c preparation
Tidy arch/um/os-Linux/start_up.c in preparation for host SKAS4 testing. There are now explicit variables for disabling any particular host capability. init_registers is moved out of the skas3 testing because it needs to happen every time, and the skas3 checks will become optional. diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 6f0d1c7..f1c26f5 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -168,7 +168,7 @@ extern int os_fchange_dir(int fd); /* start_up.c */ extern void os_early_checks(void); -extern int can_do_skas(void); +extern void can_do_skas(void); extern void os_check_bugs(void); extern void check_host_supports_tls(int *supports_tls, int *tls_min); diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 7b81f6c..2576d70 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -23,6 +23,7 @@ #include "mem_user.h" #include "ptrace_user.h" #include "registers.h" +#include "skas.h" #include "skas_ptrace.h" static int ptrace_child(void) @@ -141,14 +142,27 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) } /* Changed only during early boot */ -int ptrace_faultinfo = 1; -int ptrace_ldt = 1; -int proc_mm = 1; -int skas_needs_stub = 0; +int ptrace_faultinfo; +static int disable_ptrace_faultinfo; + +int ptrace_ldt; +static int disable_ptrace_ldt; + +int proc_mm; +static int disable_proc_mm; + +int have_switch_mm; +static int disable_switch_mm; + +int skas_needs_stub; static int __init skas0_cmd_param(char *str, int* add) { - ptrace_faultinfo = proc_mm = 0; + disable_ptrace_faultinfo = 1; + disable_ptrace_ldt = 1; + disable_proc_mm = 1; + disable_switch_mm = 1; + return 0; } @@ -158,15 +172,12 @@ static int __init mode_skas0_cmd_param(char *str, int* add) __attribute__((alias("skas0_cmd_param"))); __uml_setup("skas0", skas0_cmd_param, - "skas0\n" - "Disables SKAS3 usage, so that SKAS0 is used, unless \n" - "you specify mode=tt.\n\n"); +"skas0\n" +"Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); __uml_setup("mode=skas0", mode_skas0_cmd_param, - "mode=skas0\n" - "Disables SKAS3 usage, so that SKAS0 is used, unless you \n" - "specify mode=tt. Note that this was recently added - on \n" - "older kernels you must use simply \"skas0\".\n\n"); +"mode=skas0\n" +"Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); /* Changed only during early boot */ static int force_sysemu_disabled = 0; @@ -341,6 +352,8 @@ static void __init check_coredump_limit(void) void __init os_early_checks(void) { + int pid; + /* Print out the core dump limits early */ check_coredump_limit(); @@ -350,11 +363,15 @@ void __init os_early_checks(void) * kernel is running. */ check_tmpexec(); + + pid = start_ptraced_child(); + init_registers(pid); + stop_ptraced_child(pid, 1, 1); } static int __init noprocmm_cmd_param(char *str, int* add) { - proc_mm = 0; + disable_proc_mm = 1; return 0; } @@ -366,7 +383,7 @@ __uml_setup("noprocmm", noprocmm_cmd_param, static int __init noptracefaultinfo_cmd_param(char *str, int* add) { - ptrace_faultinfo = 0; + disable_ptrace_faultinfo = 1; return 0; } @@ -378,7 +395,7 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, static int __init noptraceldt_cmd_param(char *str, int* add) { - ptrace_ldt = 0; + disable_ptrace_ldt = 1; return 0; } @@ -398,20 +415,18 @@ static inline void check_skas3_ptrace_faultinfo(void) n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { - ptrace_faultinfo = 0; if (errno == EIO) non_fatal("not found\n"); else perror("not found"); } + else if (disable_ptrace_faultinfo) + non_fatal("found but disabled on command line\n"); else { - if (!ptrace_faultinfo) - non_fatal("found but disabled on command line\n"); - else - non_fatal("found\n"); + ptrace_faultinfo = 1; + non_fatal("found\n"); } - init_registers(pid); stop_ptraced_child(pid, 1, 1); } @@ -435,38 +450,32 @@ static inline void check_skas3_ptrace_ldt(void) else { perror("not found"); } - ptrace_ldt = 0; } + else if (disable_ptrace_ldt) + non_fatal("found, but use is disabled\n"); else { - if (ptrace_ldt) - non_fatal("found\n"); - else - non_fatal("found, but use is disabled\n"); +
[uml-devel] [RFC PATCH 7/11] SKAS4 - Host get_mm and switch_mm
This is the new_mm, switch_mm, and /proc//mm implementation for 32- and 64-bit x86 and UML, plus 32-bit support on 64-bit x86. diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h index cd2327d..6b55c52 100644 --- a/arch/um/include/skas_ptrace.h +++ b/arch/um/include/skas_ptrace.h @@ -7,7 +7,9 @@ #define __SKAS_PTRACE_H #define PTRACE_FAULTINFO 52 -#define PTRACE_SWITCH_MM 55 +#ifndef OLD_PTRACE_SWITCH_MM +#define OLD_PTRACE_SWITCH_MM 55 +#endif #include "sysdep/skas_ptrace.h" diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 47b57b4..25721bf 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -192,7 +192,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } #endif #ifdef CONFIG_PROC_MM - case PTRACE_SWITCH_MM: { + case OLD_PTRACE_SWITCH_MM: { struct mm_struct *old = child->mm; struct mm_struct *new = proc_mm_get_mm(data); @@ -292,3 +292,14 @@ void syscall_trace(struct uml_pt_regs *regs, int entryexit) current->exit_code = 0; } } + +int ptrace_to_pt_regs(struct pt_regs *to, struct user_regs __user *from) +{ + memcpy(to, &from->regs, sizeof(from->regs)); + return 0; +} + +int pt_regs_to_ptrace(struct user_regs __user *to, struct pt_regs *from) +{ + return copy_to_user(&to->regs, &from->regs.gp, sizeof(from->regs.gp)); +} diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index b9d92b2..9e6c11a 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -151,3 +151,13 @@ int kernel_execve(const char *filename, char *const argv[], char *const envp[]) return ret; } + +extern long do_switch_mm(int fd, long __user *save, long __user *new, +unsigned long ip, unsigned long sp, +struct pt_regs *regs); + +long sys_switch_mm(int fd, long __user *save, long __user *new, + unsigned long ip, unsigned long sp) +{ + return do_switch_mm(fd, save, new, ip, sp, ¤t->thread.regs); +} diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 82a0780..522d0f1 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -627,7 +627,7 @@ void __switch_mm(struct mm_id *mm_idp) /* FIXME: need cpu pid in __switch_mm */ if (proc_mm) { - err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, + err = ptrace(OLD_PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); if (err) panic("__switch_mm - PTRACE_SWITCH_MM failed, " diff --git a/arch/um/sys-x86_64/syscall_table.c b/arch/um/sys-x86_64/syscall_table.c index 71b2ae4..c2567dd 100644 --- a/arch/um/sys-x86_64/syscall_table.c +++ b/arch/um/sys-x86_64/syscall_table.c @@ -33,6 +33,7 @@ #define stub_rt_sigsuspend sys_rt_sigsuspend #define stub_sigaltstack sys_sigaltstack #define stub_rt_sigreturn sys_rt_sigreturn +#define stub_switch_mm sys_switch_mm #define __SYSCALL(nr, sym) extern asmlinkage void sym(void) ; #undef _ASM_X86_64_UNISTD_H_ diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index df588f0..2d97495 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -374,6 +374,7 @@ quiet_ni_syscall: PTREGSCALL stub32_vfork, sys_vfork, %rdi PTREGSCALL stub32_iopl, sys_iopl, %rsi PTREGSCALL stub32_rt_sigsuspend, sys_rt_sigsuspend, %rdx + PTREGSCALL stub32_switch_mm, sys_switch_mm, %r9 ENTRY(ia32_ptregs_common) popq %r11 @@ -726,4 +727,6 @@ ia32_sys_call_table: .quad compat_sys_timerfd .quad sys_eventfd .quad sys32_fallocate + .quad sys_new_mm/* 325 */ + .quad stub32_switch_mm ia32_syscall_end: diff --git a/arch/x86/ia32/ptrace32.c b/arch/x86/ia32/ptrace32.c index 4a233ad..5c0caa4 100644 --- a/arch/x86/ia32/ptrace32.c +++ b/arch/x86/ia32/ptrace32.c @@ -38,7 +38,7 @@ #define R32(l,q) \ case offsetof(struct user32, regs.l): stack[offsetof(struct pt_regs, q)/8] = val; break -static int putreg32(struct task_struct *child, unsigned regno, u32 val) +int putreg32(struct task_struct *child, unsigned regno, u32 val) { int i; __u64 *stack = (__u64 *)task_pt_regs(child); @@ -139,7 +139,7 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) #define R32(l,q) \ case offsetof(struct user32, regs.l): *val = stack[offsetof(struct pt_regs, q)/8]; break -static int getreg32(struct task_struct *child, unsigned regno, u32 *val) +int getreg32(struct task_struct *child, unsigned regno, u32 *val) { __u64 *stack = (__u64 *)task_pt_regs(child); @@ -248,6 +248,7 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) case PTRACE_SETOPTIONS: case PTRACE_SET_THREAD_AREA: case PTRACE_GET_THREAD_
[uml-devel] [RFC PATCH 11/11] SKAS4 - Guest get_mm and switch_mm support
UML guest SKAS4 support. diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index a5cdf95..90ee798 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -17,6 +17,7 @@ #define ASM_STUB_CODE (UML_CONFIG_TOP_ADDR - 2 * UM_KERN_PAGE_SIZE) #define ASM_STUB_DATA (UML_CONFIG_TOP_ADDR - UM_KERN_PAGE_SIZE) #define ASM_STUB_START ASM_STUB_CODE +#define ASM_STUB_END UML_CONFIG_TOP_ADDR /* * This file is included by the assembly stubs, which just want the @@ -27,6 +28,7 @@ #define STUB_CODE ((unsigned long) ASM_STUB_CODE) #define STUB_DATA ((unsigned long) ASM_STUB_DATA) #define STUB_START ((unsigned long) ASM_STUB_START) +#define STUB_END ((unsigned long) ASM_STUB_END) #include "sysdep/ptrace.h" diff --git a/arch/um/include/skas/mm_id.h b/arch/um/include/skas/mm_id.h index 48dd098..a2e7643 100644 --- a/arch/um/include/skas/mm_id.h +++ b/arch/um/include/skas/mm_id.h @@ -7,7 +7,7 @@ #define __MM_ID_H struct mm_id { - union { + struct { int mm_fd; int pid; } u; diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 331f343..6cc9e2a 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -6,9 +6,25 @@ #ifndef __SKAS_H #define __SKAS_H -#include "sysdep/ptrace.h" +#ifndef __KERNEL__ +#include +#include +#endif +#include "uml-config.h" -extern int have_siginfo_segv; +#ifdef UML_CONFIG_X86_32 +#define __NR_new_mm 325 +#define __NR_switch_mm 326 +#else +#define __NR_new_mm 286 +#define __NR_switch_mm 287 +#endif + +#define PTRACE_SWITCH_MM 33 + +#ifndef __ASSEMBLY__ + +#include "sysdep/ptrace.h" #define STUB_ADDR(x) (STUB_CODE + (unsigned long) (x) - \ (unsigned long) &__syscall_stub_start) @@ -17,6 +33,11 @@ extern int userspace_pid[]; extern int proc_mm, ptrace_faultinfo, ptrace_ldt; extern int skas_needs_stub; +extern int have_switch_mm; +extern int have_ptrace_switch_mm; +extern int have_siginfo_segv; +extern int self_mm_fd; + extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); extern void handle_syscall(struct uml_pt_regs *regs); @@ -25,4 +46,32 @@ extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); extern unsigned long current_stub_stack(void); +#ifndef __KERNEL__ +#include + +static inline long new_mm(void) +{ + int ret = syscall(__NR_new_mm, 0, 0, 0, 0, 0, 0); + + if (ret < 0) + return -errno; + + return ret; +} + +static inline long switch_mm(int mm_fd, unsigned long *save_regs, +unsigned long *new_regs, unsigned long ip, +unsigned long sp) +{ + int ret = syscall(__NR_switch_mm, mm_fd, save_regs, new_regs, ip, sp, 0); + + if (ret < 0) + return -errno; + + return 0; +} +#endif + +#endif + #endif diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 04cebcf..0a5468e 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -11,7 +11,7 @@ void (*pm_power_off)(void); static void kill_off_processes(void) { - if(proc_mm) + if(proc_mm || have_switch_mm) /* * FIXME: need to loop over userspace_pids */ diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 7595f77..2672829 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -65,6 +65,9 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, return -ENOMEM; } +extern int copy_context_skas4(struct mm_id *id); +extern int get_new_mm(void); + int init_new_context(struct task_struct *task, struct mm_struct *mm) { struct mm_context *from_mm = NULL; @@ -109,6 +112,20 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) } to_mm->id.u.mm_fd = ret; } + else if (have_switch_mm) { + to_mm->id.u.mm_fd = get_new_mm(); + if(to_mm->id.u.mm_fd < 0) { + ret = to_mm->id.u.mm_fd; + goto out_free; + } + + ret = copy_context_skas4(&to_mm->id); + if (ret < 0) { + os_close_file(to_mm->id.u.mm_fd); + to_mm->id.u.mm_fd = -1; + goto out_free; + } + } else { if (from_mm) to_mm->id.u.pid = copy_context_skas0(stack, @@ -136,11 +153,15 @@ void destroy_context(struct mm_struct *mm) { struct mm_context *mmu = &mm->context; - if (proc_mm) + if (proc_mm || have_switch_mm) os_close_file(mmu->id.u.mm_fd); - else + else { os_kill_ptraced_process(mmu->id.u.pid, 1); + if (have_switch_mm) +
[uml-devel] [RFC PATCH 6/11] SKAS4 - Guest support for using PTRACE_GETSIGINFO
The nastiness in arch/um/include/siginfo_segv.h is defining the new siginfo_t structure in place of the old one, which requires using CPP to rename the old one out of the way. diff --git a/arch/um/include/siginfo_segv.h b/arch/um/include/siginfo_segv.h new file mode 100644 index 000..c000267 --- /dev/null +++ b/arch/um/include/siginfo_segv.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2002- 2007 Jeff Dike ([EMAIL PROTECTED],linux.intel}.com) + * Licensed under the GPL + */ + +#ifndef __SIGINFO_SIGSEGV_H_ +#define __SIGINFO_SIGSEGV_H_ + +/* + * Provide signal.h, except for replacing siginfo_t with one that has + * the CPU trap number and error code in the SIGSEGV case. + */ + +#include + +/* Rename the signal.h siginfo and siginfo_t out of the way */ +#define siginfo old_siginfo +#define siginfo_t old_siginfo_t + +#include + +#undef siginfo +#undef siginfo_t + +#define __ARCH_SI_TRAPNO +#define __ARCH_SI_ERROR + +/* The new siginfo_t, plus associated definitions */ + +/* + * This is the size (including padding) of the part of the + * struct siginfo that is before the union. + */ +#ifndef __ARCH_SI_PREAMBLE_SIZE +#define __ARCH_SI_PREAMBLE_SIZE(3 * sizeof(int)) +#endif + +#define SI_MAX_SIZE128 +#ifndef SI_PAD_SIZE +#define SI_PAD_SIZE((SI_MAX_SIZE - __ARCH_SI_PREAMBLE_SIZE) / sizeof(int)) +#endif + +#ifndef __ARCH_SI_UID_T +#define __ARCH_SI_UID_Tuid_t +#endif + +/* + * The default "si_band" type is "long", as specified by POSIX. + * However, some architectures want to override this to "int" + * for historical compatibility reasons, so we allow that. + */ +#ifndef __ARCH_SI_BAND_T +#define __ARCH_SI_BAND_T long +#endif + +#define __user + +typedef struct siginfo { + int si_signo; + int si_errno; + int si_code; + + union { + int _pad[SI_PAD_SIZE]; + + /* kill() */ + struct { + pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; + sigval_t _sigval; /* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + pid_t _pid; /* sender's pid */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + pid_t _pid; /* which child */ + __ARCH_SI_UID_T _uid; /* sender's uid */ + int _status;/* exit code */ + clock_t _utime; + clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + void __user *_addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_TRAPNO + int _trapno;/* TRAP # which caused the signal */ +#endif +#ifdef __ARCH_SI_ERROR + int _error; /* CPU error code */ +#endif + } _sigfault; + + /* SIGPOLL */ + struct { + __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + int _fd; + } _sigpoll; + } _sifields; +} siginfo_t; + +#ifdef __ARCH_SI_TRAPNO +#define si_trapno _sifields._sigfault._trapno +#endif +#ifdef __ARCH_SI_ERROR +#define si_error _sifields._sigfault._error +#endif + +#undef si_addr +#define si_addr_sifields._sigfault._addr + +#define GET_FAULTINFO_FROM_SI(fi, si) \ + { \ + (fi).cr2 = (unsigned long) (si).si_addr; \ + (fi).error_code = (si).si_error; \ + (fi).trap_no = (si).si_trapno; \ + } + +#endif diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index b073f8a..d6cbb4f 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -8,6 +8,8 @@ #include "sysdep/ptrace.h" +extern int have_siginfo_segv; + extern int userspace_pid[]; extern int proc_mm, ptrace_faultinfo, ptrace_ldt; extern int skas_needs_stub; diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index e8b7a97..82a0780 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -3,6 +3,9 @@ * Licensed under the GPL */ +/* Include this first, before anything else includes */ +#include "siginfo_segv.h" + #include #include #include @@ -91,11 +94,23 @@ bad_wait: extern unsigned long current
[uml-devel] [RFC PATCH 3/11] SKAS4 - Host SIGSEGV siginfo_t extensions
Add CPU trap number and error code to siginfo_t in the SIGSEGV case for x86. diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 6ea19c2..2f74adf 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -65,6 +65,8 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) err |= __put_user(from->_sifields._pad[0], &to->_sifields._pad[0]); switch (from->si_code >> 16) { case __SI_FAULT >> 16: + err |= __put_user(from->si_trapno, &to->si_trapno); + err |= __put_user(from->si_error, &to->si_error); break; case __SI_CHLD >> 16: err |= __put_user(from->si_utime, &to->si_utime); diff --git a/arch/x86/mm/fault_32.c b/arch/x86/mm/fault_32.c index a2273d4..0e7940d 100644 --- a/arch/x86/mm/fault_32.c +++ b/arch/x86/mm/fault_32.c @@ -211,6 +211,8 @@ static noinline void force_sig_info_fault(int si_signo, int si_code, info.si_errno = 0; info.si_code = si_code; info.si_addr = (void __user *)address; + info.si_trapno = tsk->thread.trap_no; + info.si_error = tsk->thread.error_code; force_sig_info(si_signo, &info, tsk); } diff --git a/arch/x86/mm/fault_64.c b/arch/x86/mm/fault_64.c index 0e26230..9f5009e 100644 --- a/arch/x86/mm/fault_64.c +++ b/arch/x86/mm/fault_64.c @@ -501,6 +501,8 @@ bad_area_nosemaphore: info.si_signo = SIGSEGV; info.si_errno = 0; /* info.si_code has been set above */ + info.si_trapno = tsk->thread.trap_no; + info.si_error = tsk->thread.error_code; info.si_addr = (void __user *)address; force_sig_info(SIGSEGV, &info, tsk); return; @@ -576,6 +578,8 @@ do_sigbus: info.si_signo = SIGBUS; info.si_errno = 0; info.si_code = BUS_ADRERR; + info.si_trapno = tsk->thread.trap_no; + info.si_error = tsk->thread.error_code; info.si_addr = (void __user *)address; force_sig_info(SIGBUS, &info, tsk); return; diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h index 8786e01..b295e86 100644 --- a/include/asm-generic/siginfo.h +++ b/include/asm-generic/siginfo.h @@ -82,6 +82,9 @@ typedef struct siginfo { #ifdef __ARCH_SI_TRAPNO int _trapno;/* TRAP # which caused the signal */ #endif +#ifdef __ARCH_SI_ERROR + int _error; /* CPU error code */ +#endif } _sigfault; /* SIGPOLL */ @@ -112,6 +115,9 @@ typedef struct siginfo { #ifdef __ARCH_SI_TRAPNO #define si_trapno _sifields._sigfault._trapno #endif +#ifdef __ARCH_SI_ERROR +#define si_error _sifields._sigfault._error +#endif #define si_band_sifields._sigpoll._band #define si_fd _sifields._sigpoll._fd diff --git a/include/asm-x86/ia32.h b/include/asm-x86/ia32.h index 0190b7c..afc75c3 100644 --- a/include/asm-x86/ia32.h +++ b/include/asm-x86/ia32.h @@ -119,6 +119,8 @@ typedef struct compat_siginfo{ /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ struct { unsigned int _addr; /* faulting insn/memory ref. */ + int _trapno;/* TRAP # which caused the signal */ + int _error; /* CPU error code */ } _sigfault; /* SIGPOLL */ diff --git a/include/asm-x86/siginfo.h b/include/asm-x86/siginfo.h index a477bea..59c8d37 100644 --- a/include/asm-x86/siginfo.h +++ b/include/asm-x86/siginfo.h @@ -5,6 +5,9 @@ # define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int)) #endif +#define __ARCH_SI_TRAPNO +#define __ARCH_SI_ERROR + #include #endif diff --git a/include/linux/signalfd.h b/include/linux/signalfd.h index 86f9b1e..71e3c45 100644 --- a/include/linux/signalfd.h +++ b/include/linux/signalfd.h @@ -26,6 +26,8 @@ struct signalfd_siginfo { __u64 ssi_utime; __u64 ssi_stime; __u64 ssi_addr; + __u32 ssi_trap_no; + __u32 ssi_error_code; /* * Pad strcture to 128 bytes. Remember to update the @@ -36,7 +38,7 @@ struct signalfd_siginfo { * comes out of a read(2) and we really don't want to have * a compat on read(2). */ - __u8 __pad[48]; + __u8 __pad[40]; }; diff --git a/kernel/signal.c b/kernel/signal.c index afa4f78..1e067a1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2108,6 +2108,9 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from) #ifdef __ARCH_SI_TRAPNO err |= __put_user(from->si_trapno, &to->si_trapno); #endif +#ifdef __ARCH_SI_ERROR + err |= __put_user(from->si_error, &to->si_error); +#endif break; case __SI_CHLD: err |= __put_user(from->si_pid, &to->si_pid); ---
[uml-devel] [RFC PATCH 1/11] SKAS4 - Fix x86_64 arch_copy_thread
Fix a bug which will be important later. x86_64 copy_thread needs to copy %fs from parent to child. diff --git a/include/asm-um/processor-x86_64.h b/include/asm-um/processor-x86_64.h index d946bf2..0528d9e 100644 --- a/include/asm-um/processor-x86_64.h +++ b/include/asm-um/processor-x86_64.h @@ -37,6 +37,7 @@ static inline void arch_flush_thread(struct arch_thread *thread) static inline void arch_copy_thread(struct arch_thread *from, struct arch_thread *to) { + to->fs = from->fs; } #include "asm/arch/user.h" - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[uml-devel] [RFC PATCH 2/11] SKAS4 - Macroize stub system call execution loop
Extract the system call execution loop in the stubs into a macro A later patch will need this loop, so this makes it available. diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S index e730772..890dc50 100644 --- a/arch/um/sys-i386/stub.S +++ b/arch/um/sys-i386/stub.S @@ -1,52 +1,45 @@ #include "uml-config.h" #include "as-layout.h" +#define PROCESS_LIST \ + /* load pointer to first operation */ \ + mov $(ASM_STUB_DATA + 8), %esp; \ +1: \ + /* load length of additional data */ \ + mov 0x0(%esp), %eax; \ + /* if(length == 0) : end of list */ \ + /* write possible 0 to header */ \ + mov %eax, ASM_STUB_DATA + 4; \ + cmpl$0, %eax; \ + jz 2f; \ + /* save current pointer */ \ + mov %esp, ASM_STUB_DATA + 4; \ + /* skip additional data */ \ + add %eax, %esp; \ + /* load syscall-# */ \ + pop %eax; \ + /* load syscall params */ \ + pop %ebx; \ + pop %ecx; \ + pop %edx; \ + pop %esi; \ + pop %edi; \ + pop %ebp; \ + /* execute syscall */ \ + int $0x80; \ + /* check return value */ \ + pop %ebx; \ + cmp %ebx, %eax; \ + je 1b; \ +2: \ + /* save return value */ \ + mov %eax, ASM_STUB_DATA; + .globl syscall_stub .section .__syscall_stub, "x" .globl batch_syscall_stub batch_syscall_stub: - /* load pointer to first operation */ - mov $(ASM_STUB_DATA+8), %esp - -again: - /* load length of additional data */ - mov 0x0(%esp), %eax - - /* if(length == 0) : end of list */ - /* write possible 0 to header */ - mov %eax, ASM_STUB_DATA+4 - cmpl$0, %eax - jz done - - /* save current pointer */ - mov %esp, ASM_STUB_DATA+4 - - /* skip additional data */ - add %eax, %esp - - /* load syscall-# */ - pop %eax - - /* load syscall params */ - pop %ebx - pop %ecx - pop %edx - pop %esi - pop %edi - pop %ebp - - /* execute syscall */ - int $0x80 - - /* check return value */ - pop %ebx - cmp %ebx, %eax - je again - -done: - /* save return value */ - mov %eax, ASM_STUB_DATA - + PROCESS_LIST /* stop */ int3 diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S index 4afe204..143a16c 100644 --- a/arch/um/sys-x86_64/stub.S +++ b/arch/um/sys-x86_64/stub.S @@ -1,67 +1,48 @@ #include "uml-config.h" #include "as-layout.h" - .globl syscall_stub -.section .__syscall_stub, "x" -syscall_stub: - syscall - /* We don't have 64-bit constants, so this constructs the address -* we need. -*/ - movq$(ASM_STUB_DATA >> 32), %rbx - salq$32, %rbx - movq$(ASM_STUB_DATA & 0x), %rcx - or %rcx, %rbx - movq%rax, (%rbx) - int3 +#define PROCESS_LIST \ + mov $(ASM_STUB_DATA >> 32), %rbx; \ + sal $32, %rbx; \ + mov $(ASM_STUB_DATA & 0x), %rax; \ + or %rax, %rbx; \ + /* load pointer to first operation */ \ + mov %rbx, %rsp; \ + add $0x10, %rsp; \ +1: \ + /* load length of additional data */ \ + mov 0x0(%rsp), %rax; \ + /* if(length == 0) : end of list */ \ + /* write possible 0 to header */ \ + mov %rax, 8(%rbx); \ + cmp $0, %rax; \ + jz 2f; \ + /* save current pointer */ \ + mov %rsp, 8(%rbx); \ + /* skip additional data */ \ + add %rax, %rsp; \ + /* load syscall-# */ \ + pop %rax; \ + /* load syscall params */ \ + pop %rdi; \ + pop %rsi; \ + pop %rdx; \ + pop %r10; \ + pop %r8; \ + pop %r9; \ + /* execute syscall */ \ + syscall; \ + /* check return value */ \ + pop %rcx; \ + cmp %rcx, %rax; \ + je 1b; \ +2: \ + /* save return value */ \ + mov %rax, (%rbx); \ +.section .__syscall_stub, "x" .globl batch_syscall_stub batch_syscall_stub: - mov $(ASM_STUB_DATA >> 32), %rbx - sal $32, %rbx - mov $(ASM_STUB_DATA & 0x), %rax - or %rax, %rbx - /* load pointer to first operation */ - mov %rbx, %rsp - add $0x10, %rsp -again: - /* load length of additional data */ - mov 0x0(%rsp), %rax - - /* if(length == 0) : end of list */ - /* write possible 0 to header */ - mov %rax, 8(%rbx) - cmp $0, %rax - jz done - - /* save current pointer */ - mov %rsp, 8(%rbx) - - /* skip additional data */ - add %rax, %rsp - - /* load syscall-# */
[uml-devel] [RFC PATCH 10/11] SKAS4 - Introduce STUB_ADDR
There were a number of repetitions of the calculation of an stub address in a process address space. This introduces STUB_ADDR to eliminate the common code. diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 061a362..331f343 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -10,6 +10,9 @@ extern int have_siginfo_segv; +#define STUB_ADDR(x) (STUB_CODE + (unsigned long) (x) - \ + (unsigned long) &__syscall_stub_start) + extern int userspace_pid[]; extern int proc_mm, ptrace_faultinfo, ptrace_ldt; extern int skas_needs_stub; diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index efda5e1..a737d6d 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -45,9 +45,7 @@ static int __init init_syscall_regs(void) get_safe_registers(syscall_regs); stub_entry = &batch_syscall_stub; - syscall_regs[REGS_IP_INDEX] = STUB_CODE + - ((unsigned long) stub_entry - -(unsigned long) &__syscall_stub_start); + syscall_regs[REGS_IP_INDEX] = STUB_ADDR(stub_entry); return 0; } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 522d0f1..fc92a5d 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -229,10 +229,7 @@ static int userspace_tramp(void *stack) } if (!ptrace_faultinfo && (stack != NULL)) { struct sigaction sa; - - unsigned long v = STUB_CODE + - (unsigned long) stub_segv_handler - - (unsigned long) &__syscall_stub_start; + unsigned long v = STUB_ADDR(stub_segv_handler); set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE); sigemptyset(&sa.sa_mask); @@ -400,9 +397,7 @@ static int __init init_thread_regs(void) { get_safe_registers(thread_regs); /* Set parent's instruction pointer to start of clone-stub */ - thread_regs[REGS_IP_INDEX] = STUB_CODE + - (unsigned long) stub_clone_handler - - (unsigned long) &__syscall_stub_start; + thread_regs[REGS_IP_INDEX] = STUB_ADDR(stub_clone_handler); thread_regs[REGS_SP_INDEX] = STUB_DATA + UM_KERN_PAGE_SIZE - sizeof(void *); #ifdef __SIGNAL_FRAMESIZE - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
[uml-devel] [RFC PATCH 9/11] SKAS4 - rename new_mm
UML already had a new_mm(). This is renamed to make_new_mm(). diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index d6cbb4f..061a362 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -17,7 +17,7 @@ extern int skas_needs_stub; extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); extern void handle_syscall(struct uml_pt_regs *regs); -extern int new_mm(unsigned long stack); +extern int make_new_mm(unsigned long stack); extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); extern unsigned long current_stub_stack(void); diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index f859ec3..7595f77 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -101,10 +101,10 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) from_mm = ¤t->mm->context; if (proc_mm) { - ret = new_mm(stack); + ret = make_new_mm(stack); if (ret < 0) { printk(KERN_ERR "init_new_context_skas - " - "new_mm failed, errno = %d\n", ret); + "make_new_mm failed, errno = %d\n", ret); goto out_free; } to_mm->id.u.mm_fd = ret; diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index fce389c..2c6de0a 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -9,7 +9,7 @@ #include "os.h" #include "skas.h" -int new_mm(unsigned long stack) +int make_new_mm(unsigned long stack) { int fd; diff --git a/arch/um/sys-i386/ldt.c b/arch/um/sys-i386/ldt.c index 67c0958..c06c66c 100644 --- a/arch/um/sys-i386/ldt.c +++ b/arch/um/sys-i386/ldt.c @@ -436,7 +436,7 @@ long init_new_ldt(struct mm_context *new_mm, struct mm_context *from_mm) /* * We have a valid from_mm, so we now have to copy the LDT of * from_mm to new_mm, because using proc_mm an new mm with -* an empty/default LDT was created in new_mm() +* an empty/default LDT was created in make_new_mm() */ copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, .u= - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel
Re: [uml-devel] [-mm Patch] arch/um/kernel/initrd.c: fix a missed conversion specifier
On Wed, Feb 06, 2008 at 12:25:57AM +0800, WANG Cong wrote: > > Fix a missed conversion specifier of a printk in > arch/um/kernel/initrd.c. > > Signed-off-by: WANG Cong <[EMAIL PROTECTED]> > Cc: Jeff Dike <[EMAIL PROTECTED]> ACK - 2.6.25 material. Sigh. Jeff - This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse012070mrt/direct/01/ ___ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel