Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- vanilla-linux-2.6.7-SKAS-paolo/Makefile | 2 vanilla-linux-2.6.7-SKAS-paolo/arch/i386/Kconfig | 4 vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/entry.S | 9 vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/ldt.c | 38 +- vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/ptrace.c | 71 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/sys_i386.c | 12 vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/desc.h | 3 vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/mmu_context.h | 19 - vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/ptrace.h | 22 + vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/thread_info.h | 4 vanilla-linux-2.6.7-SKAS-paolo/include/linux/mm.h | 13 vanilla-linux-2.6.7-SKAS-paolo/include/linux/proc_mm.h | 48 ++ vanilla-linux-2.6.7-SKAS-paolo/include/linux/ptrace.h | 1 vanilla-linux-2.6.7-SKAS-paolo/kernel/fork.c | 1 vanilla-linux-2.6.7-SKAS-paolo/mm/Makefile | 1 vanilla-linux-2.6.7-SKAS-paolo/mm/mmap.c | 10 vanilla-linux-2.6.7-SKAS-paolo/mm/mprotect.c | 23 - vanilla-linux-2.6.7-SKAS-paolo/mm/proc_mm.c | 181 ++++++++++ 18 files changed, 415 insertions(+), 47 deletions(-) diff -puN arch/i386/Kconfig~host-skas3-2.6.7-v6 arch/i386/Kconfig --- vanilla-linux-2.6.7-SKAS/arch/i386/Kconfig~host-skas3-2.6.7-v6 2004-10-26 02:05:21.844318808 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/Kconfig 2004-10-26 02:05:21.866315464 +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" diff -puN arch/i386/kernel/entry.S~host-skas3-2.6.7-v6 arch/i386/kernel/entry.S --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/entry.S~host-skas3-2.6.7-v6 2004-10-26 02:05:21.846318504 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/entry.S 2004-10-26 02:05:21.869315008 +0200 @@ -258,7 +258,7 @@ sysenter_past_esp: cmpl $(nr_syscalls), %eax jae syscall_badsys - 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 call *sys_call_table(,%eax,4) movl %eax,EAX(%esp) @@ -280,8 +280,8 @@ ENTRY(system_call) GET_THREAD_INFO(%ebp) cmpl $(nr_syscalls), %eax jae syscall_badsys - # system call tracing in operation - testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) + # system call tracing in operation / emulation + testb $(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp) jnz syscall_trace_entry syscall_call: call *sys_call_table(,%eax,4) @@ -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 diff -puN arch/i386/kernel/ldt.c~host-skas3-2.6.7-v6 arch/i386/kernel/ldt.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/ldt.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.847318352 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/ldt.c 2004-10-26 02:05:21.867315312 +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; @@ -169,9 +172,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; @@ -195,7 +197,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; } @@ -228,23 +230,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); +} diff -puN arch/i386/kernel/ptrace.c~host-skas3-2.6.7-v6 arch/i386/kernel/ptrace.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/ptrace.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.848318200 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/ptrace.c 2004-10-26 02:05:21.867315312 +0200 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -357,6 +358,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; @@ -364,6 +366,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); } @@ -404,6 +412,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 */ @@ -509,6 +518,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; @@ -524,8 +583,9 @@ 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) { + int is_sysemu; if (unlikely(current->audit_context)) { if (!entryexit) audit_syscall_entry(current, regs->orig_eax, @@ -534,11 +594,12 @@ void do_syscall_trace(struct pt_regs *re else audit_syscall_exit(current, regs->eax); } + is_sysemu = test_thread_flag(TIF_SYSCALL_EMU); - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; + if (!test_thread_flag(TIF_SYSCALL_TRACE) && !is_sysemu) + 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) @@ -553,4 +614,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 is_sysemu; } diff -puN arch/i386/kernel/sys_i386.c~host-skas3-2.6.7-v6 arch/i386/kernel/sys_i386.c --- vanilla-linux-2.6.7-SKAS/arch/i386/kernel/sys_i386.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.849318048 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/arch/i386/kernel/sys_i386.c 2004-10-26 02:05:21.867315312 +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; } diff -puN include/asm-i386/desc.h~host-skas3-2.6.7-v6 include/asm-i386/desc.h --- vanilla-linux-2.6.7-SKAS/include/asm-i386/desc.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.850317896 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/desc.h 2004-10-26 02:05:21.868315160 +0200 @@ -123,6 +123,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 diff -puN include/asm-i386/mmu_context.h~host-skas3-2.6.7-v6 include/asm-i386/mmu_context.h --- vanilla-linux-2.6.7-SKAS/include/asm-i386/mmu_context.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.851317744 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/mmu_context.h 2004-10-26 02:05:21.868315160 +0200 @@ -6,13 +6,25 @@ #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; +} + +/* 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 +41,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 +66,6 @@ static inline void switch_mm(struct mm_s #ifdef CONFIG_SMP else { cpu_tlbstate[cpu].state = TLBSTATE_OK; - BUG_ON(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 diff -puN include/asm-i386/ptrace.h~host-skas3-2.6.7-v6 include/asm-i386/ptrace.h --- vanilla-linux-2.6.7-SKAS/include/asm-i386/ptrace.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.852317592 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/ptrace.h 2004-10-26 02:05:21.868315160 +0200 @@ -59,4 +59,26 @@ struct pt_regs { #define instruction_pointer(regs) ((regs)->eip) #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 diff -puN include/asm-i386/thread_info.h~host-skas3-2.6.7-v6 include/asm-i386/thread_info.h --- vanilla-linux-2.6.7-SKAS/include/asm-i386/thread_info.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.853317440 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/asm-i386/thread_info.h 2004-10-26 02:05:21.869315008 +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, diff -puN include/linux/proc_mm.h~host-skas3-2.6.7-v6 include/linux/proc_mm.h --- vanilla-linux-2.6.7-SKAS/include/linux/proc_mm.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.855317136 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/linux/proc_mm.h 2004-10-26 02:05:21.864315768 +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 diff -puN include/linux/ptrace.h~host-skas3-2.6.7-v6 include/linux/ptrace.h --- vanilla-linux-2.6.7-SKAS/include/linux/ptrace.h~host-skas3-2.6.7-v6 2004-10-26 02:05:21.856316984 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/include/linux/ptrace.h 2004-10-26 02:05:21.869315008 +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 diff -puN kernel/fork.c~host-skas3-2.6.7-v6 kernel/fork.c --- vanilla-linux-2.6.7-SKAS/kernel/fork.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.857316832 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/kernel/fork.c 2004-10-26 02:05:21.870314856 +0200 @@ -1009,6 +1009,7 @@ struct task_struct *copy_process(unsigne * 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 */ diff -puN Makefile~host-skas3-2.6.7-v6 Makefile --- vanilla-linux-2.6.7-SKAS/Makefile~host-skas3-2.6.7-v6 2004-10-26 02:05:21.858316680 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/Makefile 2004-10-26 02:05:21.870314856 +0200 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 7 -EXTRAVERSION = +EXTRAVERSION = -skas3.v6 NAME=Zonked Quokka # *DOCUMENTATION* diff -puN mm/Makefile~host-skas3-2.6.7-v6 mm/Makefile --- vanilla-linux-2.6.7-SKAS/mm/Makefile~host-skas3-2.6.7-v6 2004-10-26 02:05:21.859316528 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/mm/Makefile 2004-10-26 02:05:21.864315768 +0200 @@ -15,3 +15,4 @@ obj-y := bootmem.o filemap.o mempool.o obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o +obj-$(CONFIG_PROC_MM) += proc_mm.o diff -puN mm/mmap.c~host-skas3-2.6.7-v6 mm/mmap.c --- vanilla-linux-2.6.7-SKAS/mm/mmap.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.860316376 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/mm/mmap.c 2004-10-26 02:05:21.865315616 +0200 @@ -725,11 +725,11 @@ none: * 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; @@ -988,7 +988,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. diff -puN mm/mprotect.c~host-skas3-2.6.7-v6 mm/mprotect.c --- vanilla-linux-2.6.7-SKAS/mm/mprotect.c~host-skas3-2.6.7-v6 2004-10-26 02:05:21.861316224 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/mm/mprotect.c 2004-10-26 02:05:21.865315616 +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; } @@ -185,8 +186,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; @@ -209,9 +211,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; @@ -277,6 +279,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)); +} diff -puN /dev/null mm/proc_mm.c --- /dev/null 2004-06-25 17:47:25.000000000 +0200 +++ vanilla-linux-2.6.7-SKAS-paolo/mm/proc_mm.c 2004-10-26 02:05:21.866315464 +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: + */ _