From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from sc8-sf-mx1-b.sourceforge.net ([10.3.1.11] helo=sc8-sf-mx1.sourceforge.net) by sc8-sf-list1.sourceforge.net with esmtp (Exim 4.30) id 1C7wpL-0004Ni-64 for user-mode-linux-devel@lists.sourceforge.net; Thu, 16 Sep 2004 07:01:35 -0700 Received: from hirsch.in-berlin.de ([192.109.42.6] ident=root) by sc8-sf-mx1.sourceforge.net with esmtp (TLSv1:AES256-SHA:256) (Exim 4.34) id 1C7wpJ-0006j0-48 for user-mode-linux-devel@lists.sourceforge.net; Thu, 16 Sep 2004 07:01:35 -0700 From: Gerd Knorr Message-ID: <20040916133921.GA14509@bytesex> References: <200409122004.41777.blaisorblade_spam@yahoo.it> <20040913144250.GA17259@bytesex> <200409132130.00661.blaisorblade_spam@yahoo.it> <20040915144213.GA32509@bytesex> <20040916110323.GB12785@bytesex> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20040916110323.GB12785@bytesex> Subject: [uml-devel] [patch] host-skas3 for 2.6.9-rc2 Sender: user-mode-linux-devel-admin@lists.sourceforge.net Errors-To: user-mode-linux-devel-admin@lists.sourceforge.net List-Unsubscribe: , List-Id: The user-mode Linux development list List-Post: List-Help: List-Subscribe: , List-Archive: Date: Thu, 16 Sep 2004 15:39:21 +0200 To: BlaisorBlade Cc: uml devel On Thu, Sep 16, 2004 at 01:03:23PM +0200, Gerd Knorr wrote: > Some change between -rc1 and -rc1-bk1 broke the skas patch, still > looking ... Found it: init_new_empty_context needs a arch_pick_mmap_layout call, otherwise we'll get a NULL ptr dereferences for the function pointers added recently to mm_struct. enjoy, Gerd Index: host-2.6.9-rc2/arch/i386/Kconfig =================================================================== --- host-2.6.9-rc2.orig/arch/i386/Kconfig 2004-09-13 16:29:41.000000000 +0200 +++ host-2.6.9-rc2/arch/i386/Kconfig 2004-09-15 16:40:00.000000000 +0200 @@ -720,6 +720,10 @@ config X86_PAE depends on HIGHMEM64G default y +config PROC_MM + bool "/proc/mm support" + default y + # Common NUMA Features config NUMA bool "Numa Memory Allocation and Scheduler Support" Index: host-2.6.9-rc2/arch/i386/kernel/entry.S =================================================================== --- host-2.6.9-rc2.orig/arch/i386/kernel/entry.S 2004-09-13 16:29:54.000000000 +0200 +++ host-2.6.9-rc2/arch/i386/kernel/entry.S 2004-09-15 16:40:00.000000000 +0200 @@ -256,7 +256,7 @@ sysenter_past_esp: SAVE_ALL GET_THREAD_INFO(%ebp) - testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) + testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz syscall_trace_entry cmpl $(nr_syscalls), %eax jae syscall_badsys @@ -279,7 +279,7 @@ ENTRY(system_call) SAVE_ALL GET_THREAD_INFO(%ebp) # system call tracing in operation - testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) + testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz syscall_trace_entry cmpl $(nr_syscalls), %eax jae syscall_badsys @@ -340,6 +340,9 @@ syscall_trace_entry: movl %esp, %eax xorl %edx,%edx call do_syscall_trace + cmpl $0, %eax + jne syscall_exit # ret != 0 -> running under PTRACE_SYSEMU, + # so must skip actual syscall movl ORIG_EAX(%esp), %eax cmpl $(nr_syscalls), %eax jnae syscall_call Index: host-2.6.9-rc2/arch/i386/kernel/ldt.c =================================================================== --- host-2.6.9-rc2.orig/arch/i386/kernel/ldt.c 2004-09-13 16:30:53.000000000 +0200 +++ host-2.6.9-rc2/arch/i386/kernel/ldt.c 2004-09-16 14:32:56.000000000 +0200 @@ -18,6 +18,7 @@ #include #include #include +#include #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */ static void flush_ldt(void *null) @@ -54,7 +55,7 @@ static int alloc_ldt(mm_context_t *pc, i pc->size = mincount; wmb(); - if (reload) { + if (reload && (¤t->active_mm->context == pc)) { #ifdef CONFIG_SMP cpumask_t mask; preempt_disable(); @@ -89,14 +90,10 @@ static inline int copy_ldt(mm_context_t * we do not have to muck with descriptors here, that is * done in switch_mm() as needed. */ -int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +int copy_context(struct mm_struct *mm, struct mm_struct *old_mm) { - struct mm_struct * old_mm; int retval = 0; - init_MUTEX(&mm->context.sem); - mm->context.size = 0; - old_mm = current->mm; if (old_mm && old_mm->context.size > 0) { down(&old_mm->context.sem); retval = copy_ldt(&mm->context, &old_mm->context); @@ -105,6 +102,12 @@ int init_new_context(struct task_struct return retval; } +int init_new_context(struct task_struct *tsk, struct mm_struct *mm) +{ + init_new_empty_context(mm); + return copy_context(mm, current->mm); +} + /* * No need to lock the MM as we are the last user */ @@ -121,11 +124,11 @@ void destroy_context(struct mm_struct *m } } -static int read_ldt(void __user * ptr, unsigned long bytecount) +static int read_ldt(struct mm_struct * mm, void __user * ptr, + unsigned long bytecount) { int err; unsigned long size; - struct mm_struct * mm = current->mm; if (!mm->context.size) return 0; @@ -174,9 +177,8 @@ static int read_default_ldt(void __user return err; } -static int write_ldt(void __user * ptr, unsigned long bytecount, int oldmode) +static int write_ldt(struct mm_struct * mm, void __user * ptr, unsigned long bytecount, int oldmode) { - struct mm_struct * mm = current->mm; __u32 entry_1, entry_2, *lp; int error; struct user_desc ldt_info; @@ -200,7 +202,7 @@ static int write_ldt(void __user * ptr, down(&mm->context.sem); if (ldt_info.entry_number >= mm->context.size) { - error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1); + error = alloc_ldt(&mm->context, ldt_info.entry_number+1, 1); if (error < 0) goto out_unlock; } @@ -233,23 +235,29 @@ out: return error; } -asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +int modify_ldt(struct mm_struct * mm, int func, void __user *ptr, + unsigned long bytecount) { int ret = -ENOSYS; switch (func) { case 0: - ret = read_ldt(ptr, bytecount); + ret = read_ldt(mm, ptr, bytecount); break; case 1: - ret = write_ldt(ptr, bytecount, 1); + ret = write_ldt(mm, ptr, bytecount, 1); break; case 2: ret = read_default_ldt(ptr, bytecount); break; case 0x11: - ret = write_ldt(ptr, bytecount, 0); + ret = write_ldt(mm, ptr, bytecount, 0); break; } return ret; } + +asmlinkage int sys_modify_ldt(int func, void __user *ptr, unsigned long bytecount) +{ + return modify_ldt(current->mm, func, ptr, bytecount); +} Index: host-2.6.9-rc2/arch/i386/kernel/ptrace.c =================================================================== --- host-2.6.9-rc2.orig/arch/i386/kernel/ptrace.c 2004-09-13 16:29:56.000000000 +0200 +++ host-2.6.9-rc2/arch/i386/kernel/ptrace.c 2004-09-15 16:40:13.000000000 +0200 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -358,6 +359,7 @@ asmlinkage int sys_ptrace(long request, } break; + case PTRACE_SYSEMU: /* continue and replace next syscall */ case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ case PTRACE_CONT: { /* restart after signal. */ long tmp; @@ -365,6 +367,12 @@ asmlinkage int sys_ptrace(long request, ret = -EIO; if ((unsigned long) data > _NSIG) break; + if (request == PTRACE_SYSEMU) { + set_tsk_thread_flag(child, TIF_SYSCALL_EMU); + } + else { + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); + } if (request == PTRACE_SYSCALL) { set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); } @@ -407,6 +415,7 @@ asmlinkage int sys_ptrace(long request, ret = -EIO; if ((unsigned long) data > _NSIG) break; + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); if ((child->ptrace & PT_DTRACE) == 0) { /* Spurious delayed TF traps may occur */ @@ -513,6 +522,56 @@ asmlinkage int sys_ptrace(long request, (struct user_desc __user *) data); break; +#ifdef CONFIG_PROC_MM + case PTRACE_FAULTINFO: { + struct ptrace_faultinfo fault; + + fault = ((struct ptrace_faultinfo) + { .is_write = child->thread.error_code, + .addr = child->thread.cr2 }); + ret = copy_to_user((unsigned long *) data, &fault, + sizeof(fault)); + if(ret) + break; + break; + } + + case PTRACE_SIGPENDING: + ret = copy_to_user((unsigned long *) data, + &child->pending.signal, + sizeof(child->pending.signal)); + break; + + case PTRACE_LDT: { + struct ptrace_ldt ldt; + + if(copy_from_user(&ldt, (unsigned long *) data, + sizeof(ldt))){ + ret = -EIO; + break; + } + ret = modify_ldt(child->mm, ldt.func, ldt.ptr, ldt.bytecount); + break; + } + + case PTRACE_SWITCH_MM: { + struct mm_struct *old = child->mm; + struct mm_struct *new = proc_mm_get_mm(data); + + if(IS_ERR(new)){ + ret = PTR_ERR(new); + break; + } + + atomic_inc(&new->mm_users); + child->mm = new; + child->active_mm = new; + mmput(old); + ret = 0; + break; + } +#endif + default: ret = ptrace_request(child, request, addr, data); break; @@ -528,7 +587,7 @@ out: * - triggered by current->work.syscall_trace */ __attribute__((regparm(3))) -void do_syscall_trace(struct pt_regs *regs, int entryexit) +int do_syscall_trace(struct pt_regs *regs, int entryexit) { if (unlikely(current->audit_context)) { if (!entryexit) @@ -540,10 +599,11 @@ void do_syscall_trace(struct pt_regs *re } if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SYSCALL_EMU) && !test_thread_flag(TIF_SINGLESTEP)) - return; + return 0; if (!(current->ptrace & PT_PTRACED)) - return; + return 0; /* the 0x80 provides a way for the tracing parent to distinguish between a syscall stop and SIGTRAP delivery */ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && @@ -558,4 +618,6 @@ void do_syscall_trace(struct pt_regs *re send_sig(current->exit_code, current, 1); current->exit_code = 0; } + /* != 0 if nullifying the syscall, 0 if running it normally */ + return test_thread_flag(TIF_SYSCALL_EMU); } Index: host-2.6.9-rc2/arch/i386/kernel/sys_i386.c =================================================================== --- host-2.6.9-rc2.orig/arch/i386/kernel/sys_i386.c 2004-09-13 16:31:28.000000000 +0200 +++ host-2.6.9-rc2/arch/i386/kernel/sys_i386.c 2004-09-15 16:40:00.000000000 +0200 @@ -41,7 +41,7 @@ asmlinkage int sys_pipe(unsigned long __ } /* common code for old and new mmaps */ -static inline long do_mmap2( +long do_mmap2(struct mm_struct *mm, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) @@ -56,9 +56,9 @@ static inline long do_mmap2( goto out; } - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); + down_write(&mm->mmap_sem); + error = __do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); + up_write(&mm->mmap_sem); if (file) fput(file); @@ -70,7 +70,7 @@ asmlinkage long sys_mmap2(unsigned long unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { - return do_mmap2(addr, len, prot, flags, fd, pgoff); + return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); } /* @@ -101,7 +101,7 @@ asmlinkage int old_mmap(struct mmap_arg_ if (a.offset & ~PAGE_MASK) goto out; - err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); + err = do_mmap2(current->mm, a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); out: return err; } Index: host-2.6.9-rc2/include/asm-i386/desc.h =================================================================== --- host-2.6.9-rc2.orig/include/asm-i386/desc.h 2004-09-13 16:29:15.000000000 +0200 +++ host-2.6.9-rc2/include/asm-i386/desc.h 2004-09-15 16:40:00.000000000 +0200 @@ -126,6 +126,9 @@ static inline void load_LDT(mm_context_t put_cpu(); } +extern int modify_ldt(struct mm_struct * mm, int func, void __user *ptr, + unsigned long bytecount); + #endif /* !__ASSEMBLY__ */ #endif Index: host-2.6.9-rc2/include/asm-i386/mmu_context.h =================================================================== --- host-2.6.9-rc2.orig/include/asm-i386/mmu_context.h 2004-09-13 16:29:16.000000000 +0200 +++ host-2.6.9-rc2/include/asm-i386/mmu_context.h 2004-09-16 14:33:56.000000000 +0200 @@ -6,13 +6,26 @@ #include #include #include +#include /* - * Used for LDT copy/destruction. + * Used for LDT initialization/destruction. You cannot copy an LDT with + * init_new_context, since it thinks you are passing it a new LDT and won't + * deallocate its old content. */ int init_new_context(struct task_struct *tsk, struct mm_struct *mm); void destroy_context(struct mm_struct *mm); +/* LDT initialization for a clean environment - needed for SKAS.*/ +static inline void init_new_empty_context(struct mm_struct *mm) +{ + init_MUTEX(&mm->context.sem); + mm->context.size = 0; + arch_pick_mmap_layout(mm); +} + +/* LDT copy for SKAS - for the above problem.*/ +int copy_context(struct mm_struct *mm, struct mm_struct *old_mm); static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) { @@ -29,6 +42,10 @@ static inline void switch_mm(struct mm_s { int cpu = smp_processor_id(); +#ifdef CONFIG_SMP + prev = cpu_tlbstate[cpu].active_mm; +#endif + if (likely(prev != next)) { /* stop flush ipis for the previous mm */ cpu_clear(cpu, prev->cpu_vm_mask); @@ -50,7 +67,6 @@ static inline void switch_mm(struct mm_s #ifdef CONFIG_SMP else { per_cpu(cpu_tlbstate, cpu).state = TLBSTATE_OK; - BUG_ON(per_cpu(cpu_tlbstate, cpu).active_mm != next); if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) { /* We were in lazy tlb mode and leave_mm disabled Index: host-2.6.9-rc2/include/asm-i386/ptrace.h =================================================================== --- host-2.6.9-rc2.orig/include/asm-i386/ptrace.h 2004-09-13 16:29:29.000000000 +0200 +++ host-2.6.9-rc2/include/asm-i386/ptrace.h 2004-09-15 16:40:00.000000000 +0200 @@ -64,4 +64,26 @@ extern unsigned long profile_pc(struct p #endif #endif +/*For SKAS3 support.*/ +#ifndef _LINUX_PTRACE_STRUCT_DEF +#define _LINUX_PTRACE_STRUCT_DEF + +#define PTRACE_FAULTINFO 52 +#define PTRACE_SIGPENDING 53 +#define PTRACE_LDT 54 +#define PTRACE_SWITCH_MM 55 + +struct ptrace_faultinfo { + int is_write; + unsigned long addr; +}; + +struct ptrace_ldt { + int func; + void *ptr; + unsigned long bytecount; +}; + +#endif /*ifndef _LINUX_PTRACE_STRUCT_DEF*/ + #endif Index: host-2.6.9-rc2/include/asm-i386/thread_info.h =================================================================== --- host-2.6.9-rc2.orig/include/asm-i386/thread_info.h 2004-09-13 16:29:39.000000000 +0200 +++ host-2.6.9-rc2/include/asm-i386/thread_info.h 2004-09-15 16:40:00.000000000 +0200 @@ -143,6 +143,7 @@ static inline unsigned long current_stac #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_IRET 5 /* return with iret */ +#define TIF_SYSCALL_EMU 6 /* syscall emulation active */ #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ @@ -152,12 +153,13 @@ static inline unsigned long current_stac #define _TIF_NEED_RESCHED (1<mm, file, addr, len, prot, flag, pgoff); +} static inline unsigned long do_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, Index: host-2.6.9-rc2/include/linux/proc_mm.h =================================================================== --- host-2.6.9-rc2.orig/include/linux/proc_mm.h 2004-04-06 15:27:52.000000000 +0200 +++ host-2.6.9-rc2/include/linux/proc_mm.h 2004-09-15 16:40:00.000000000 +0200 @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#ifndef __PROC_MM_H +#define __PROC_MM_H + +#include "linux/sched.h" + +#define MM_MMAP 54 +#define MM_MUNMAP 55 +#define MM_MPROTECT 56 +#define MM_COPY_SEGMENTS 57 + +struct mm_mmap { + unsigned long addr; + unsigned long len; + unsigned long prot; + unsigned long flags; + unsigned long fd; + unsigned long offset; +}; + +struct mm_munmap { + unsigned long addr; + unsigned long len; +}; + +struct mm_mprotect { + unsigned long addr; + unsigned long len; + unsigned int prot; +}; + +struct proc_mm_op { + int op; + union { + struct mm_mmap mmap; + struct mm_munmap munmap; + struct mm_mprotect mprotect; + int copy_segments; + } u; +}; + +extern struct mm_struct *proc_mm_get_mm(int fd); + +#endif Index: host-2.6.9-rc2/include/linux/ptrace.h =================================================================== --- host-2.6.9-rc2.orig/include/linux/ptrace.h 2004-09-13 16:29:32.000000000 +0200 +++ host-2.6.9-rc2/include/linux/ptrace.h 2004-09-15 16:40:00.000000000 +0200 @@ -20,6 +20,7 @@ #define PTRACE_DETACH 0x11 #define PTRACE_SYSCALL 24 +#define PTRACE_SYSEMU 31 /* 0x4200-0x4300 are reserved for architecture-independent additions. */ #define PTRACE_SETOPTIONS 0x4200 Index: host-2.6.9-rc2/kernel/fork.c =================================================================== --- host-2.6.9-rc2.orig/kernel/fork.c 2004-09-13 16:29:32.000000000 +0200 +++ host-2.6.9-rc2/kernel/fork.c 2004-09-15 16:40:00.000000000 +0200 @@ -1038,6 +1038,7 @@ static task_t *copy_process(unsigned lon * of CLONE_PTRACE. */ clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); + clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); /* Our parent execution domain becomes current domain These must match for thread signalling to apply */ Index: host-2.6.9-rc2/mm/Makefile =================================================================== --- host-2.6.9-rc2.orig/mm/Makefile 2004-09-13 16:30:46.000000000 +0200 +++ host-2.6.9-rc2/mm/Makefile 2004-09-15 16:40:00.000000000 +0200 @@ -17,4 +17,4 @@ obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o obj-$(CONFIG_SHMEM) += shmem.o obj-$(CONFIG_TINY_SHMEM) += tiny-shmem.o - +obj-$(CONFIG_PROC_MM) += proc_mm.o Index: host-2.6.9-rc2/mm/mmap.c =================================================================== --- host-2.6.9-rc2.orig/mm/mmap.c 2004-09-13 16:30:44.000000000 +0200 +++ host-2.6.9-rc2/mm/mmap.c 2004-09-15 16:40:00.000000000 +0200 @@ -759,11 +759,11 @@ void __vm_stat_account(struct mm_struct * The caller must hold down_write(current->mm->mmap_sem). */ -unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flags, unsigned long pgoff) +unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file * file, + unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long pgoff) { - struct mm_struct * mm = current->mm; struct vm_area_struct * vma, * prev; struct inode *inode; unsigned int vm_flags; @@ -1032,7 +1032,7 @@ unacct_error: return error; } -EXPORT_SYMBOL(do_mmap_pgoff); +EXPORT_SYMBOL(__do_mmap_pgoff); /* Get an address range which is currently unmapped. * For shmat() with addr=0. Index: host-2.6.9-rc2/mm/mprotect.c =================================================================== --- host-2.6.9-rc2.orig/mm/mprotect.c 2004-09-13 16:31:39.000000000 +0200 +++ host-2.6.9-rc2/mm/mprotect.c 2004-09-15 16:40:00.000000000 +0200 @@ -92,19 +92,20 @@ change_protection(struct vm_area_struct { pgd_t *dir; unsigned long beg = start; + struct mm_struct * mm = vma->vm_mm; - dir = pgd_offset(current->mm, start); + dir = pgd_offset(mm, start); flush_cache_range(vma, beg, end); if (start >= end) BUG(); - spin_lock(¤t->mm->page_table_lock); + spin_lock(&mm->page_table_lock); do { change_pmd_range(dir, start, end - start, newprot); start = (start + PGDIR_SIZE) & PGDIR_MASK; dir++; } while (start && (start < end)); flush_tlb_range(vma, beg, end); - spin_unlock(¤t->mm->page_table_lock); + spin_unlock(&mm->page_table_lock); return; } @@ -187,8 +188,9 @@ fail: return error; } -asmlinkage long -sys_mprotect(unsigned long start, size_t len, unsigned long prot) +long +do_mprotect(struct mm_struct *mm, unsigned long start, size_t len, + unsigned long prot) { unsigned long vm_flags, nstart, end, tmp; struct vm_area_struct *vma, *prev; @@ -217,9 +219,9 @@ sys_mprotect(unsigned long start, size_t vm_flags = calc_vm_prot_bits(prot); - down_write(¤t->mm->mmap_sem); + down_write(&mm->mmap_sem); - vma = find_vma_prev(current->mm, start, &prev); + vma = find_vma_prev(mm, start, &prev); error = -ENOMEM; if (!vma) goto out; @@ -285,6 +287,11 @@ sys_mprotect(unsigned long start, size_t } } out: - up_write(¤t->mm->mmap_sem); + up_write(&mm->mmap_sem); return error; } + +asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot) +{ + return(do_mprotect(current->mm, start, len, prot)); +} Index: host-2.6.9-rc2/mm/proc_mm.c =================================================================== --- host-2.6.9-rc2.orig/mm/proc_mm.c 2004-04-06 15:27:52.000000000 +0200 +++ host-2.6.9-rc2/mm/proc_mm.c 2004-09-15 16:40:00.000000000 +0200 @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +#include "linux/mm.h" +#include "linux/init.h" +#include "linux/proc_fs.h" +#include "linux/proc_mm.h" +#include "linux/file.h" +#include "linux/mman.h" +#include "asm/uaccess.h" +#include "asm/mmu_context.h" + +static struct file_operations proc_mm_fops; + +struct mm_struct *proc_mm_get_mm(int fd) +{ + struct mm_struct *ret = ERR_PTR(-EBADF); + struct file *file; + + file = fget(fd); + if (!file) + goto out; + + ret = ERR_PTR(-EINVAL); + if(file->f_op != &proc_mm_fops) + goto out_fput; + + ret = file->private_data; + out_fput: + fput(file); + out: + return(ret); +} + +extern long do_mmap2(struct mm_struct *mm, unsigned long addr, + unsigned long len, unsigned long prot, + unsigned long flags, unsigned long fd, + unsigned long pgoff); + +static ssize_t write_proc_mm(struct file *file, const char *buffer, + size_t count, loff_t *ppos) +{ + struct mm_struct *mm = file->private_data; + struct proc_mm_op req; + int n, ret; + + if(count > sizeof(req)) + return(-EINVAL); + + n = copy_from_user(&req, buffer, count); + if(n != 0) + return(-EFAULT); + + ret = count; + switch(req.op){ + case MM_MMAP: { + struct mm_mmap *map = &req.u.mmap; + + /* Nobody ever noticed it, but do_mmap_pgoff() calls + * get_unmapped_area() which checks current->mm, if + * MAP_FIXED is not set, so mmap() could replace + * an old mapping. + */ + if (! (map->flags & MAP_FIXED)) + return(-EINVAL); + + ret = do_mmap2(mm, map->addr, map->len, map->prot, + map->flags, map->fd, map->offset >> PAGE_SHIFT); + if((ret & ~PAGE_MASK) == 0) + ret = count; + + break; + } + case MM_MUNMAP: { + struct mm_munmap *unmap = &req.u.munmap; + + down_write(&mm->mmap_sem); + ret = do_munmap(mm, unmap->addr, unmap->len); + up_write(&mm->mmap_sem); + + if(ret == 0) + ret = count; + break; + } + case MM_MPROTECT: { + struct mm_mprotect *protect = &req.u.mprotect; + + ret = do_mprotect(mm, protect->addr, protect->len, + protect->prot); + if(ret == 0) + ret = count; + break; + } + + case MM_COPY_SEGMENTS: { + struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); + + if(IS_ERR(from)){ + ret = PTR_ERR(from); + break; + } + + ret = copy_context(mm, from); + if(ret == 0) + ret = count; + break; + } + default: + ret = -EINVAL; + break; + } + + return(ret); +} + +static int open_proc_mm(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = mm_alloc(); + int ret; + + ret = -ENOMEM; + if(mm == NULL) + goto out_mem; + + init_new_empty_context(mm); + + spin_lock(&mmlist_lock); + list_add(&mm->mmlist, ¤t->mm->mmlist); + mmlist_nr++; + spin_unlock(&mmlist_lock); + + file->private_data = mm; + + return(0); + + out_mem: + return(ret); +} + +static int release_proc_mm(struct inode *inode, struct file *file) +{ + struct mm_struct *mm = file->private_data; + + mmput(mm); + return(0); +} + +static struct file_operations proc_mm_fops = { + .open = open_proc_mm, + .release = release_proc_mm, + .write = write_proc_mm, +}; + +static int make_proc_mm(void) +{ + struct proc_dir_entry *ent; + + ent = create_proc_entry("mm", 0222, &proc_root); + if(ent == NULL){ + printk("make_proc_mm : Failed to register /proc/mm\n"); + return(0); + } + ent->proc_fops = &proc_mm_fops; + + return(0); +} + +__initcall(make_proc_mm); + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-file-style: "linux" + * End: + */ ------------------------------------------------------- This SF.Net email is sponsored by: YOU BE THE JUDGE. Be one of 170 Project Admins to receive an Apple iPod Mini FREE for your judgement on who ports your project to Linux PPC the best. Sponsored by IBM. Deadline: Sept. 24. Go here: http://sf.net/ppc_contest.php _______________________________________________ User-mode-linux-devel mailing list User-mode-linux-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel