1 diff -Naur host/arch/i386/config.in host-ptrace/arch/i386/config.in
2 --- host/arch/i386/config.in Fri Aug 9 15:57:14 2002
3 +++ host-ptrace/arch/i386/config.in Sun Nov 10 18:40:09 2002
5 bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
8 +bool '/proc/mm' CONFIG_PROC_MM
12 source drivers/mtd/Config.in
13 diff -Naur host/arch/i386/kernel/ldt.c host-ptrace/arch/i386/kernel/ldt.c
14 --- host/arch/i386/kernel/ldt.c Fri Oct 26 00:01:41 2001
15 +++ host-ptrace/arch/i386/kernel/ldt.c Sun Nov 3 18:37:48 2002
17 * assured by user-space anyway. Writes are atomic, to protect
18 * the security checks done on new descriptors.
20 -static int read_ldt(void * ptr, unsigned long bytecount)
21 +static int read_ldt(struct task_struct *task, void * ptr,
22 + unsigned long bytecount)
26 - struct mm_struct * mm = current->mm;
27 + struct mm_struct * mm = task->mm;
30 if (!mm->context.segments)
35 -static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
36 +static int write_ldt(struct task_struct *task, void * ptr,
37 + unsigned long bytecount, int oldmode)
39 - struct mm_struct * mm = current->mm;
40 + struct mm_struct * mm = task->mm;
41 __u32 entry_1, entry_2, *lp;
43 struct modify_ldt_ldt_s ldt_info;
48 -asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
49 +int modify_ldt(struct task_struct *task, int func, void *ptr,
50 + unsigned long bytecount)
56 - ret = read_ldt(ptr, bytecount);
57 + ret = read_ldt(task, ptr, bytecount);
60 - ret = write_ldt(ptr, bytecount, 1);
61 + ret = write_ldt(task, ptr, bytecount, 1);
64 ret = read_default_ldt(ptr, bytecount);
67 - ret = write_ldt(ptr, bytecount, 0);
68 + ret = write_ldt(task, ptr, bytecount, 0);
74 +asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
76 + return(modify_ldt(current, func, ptr, bytecount));
78 diff -Naur host/arch/i386/kernel/process.c host-ptrace/arch/i386/kernel/process.c
79 --- host/arch/i386/kernel/process.c Fri Aug 9 15:57:14 2002
80 +++ host-ptrace/arch/i386/kernel/process.c Wed Nov 6 22:12:45 2002
82 * we do not have to muck with descriptors here, that is
83 * done in switch_mm() as needed.
85 -void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
86 +void mm_copy_segments(struct mm_struct *old_mm, struct mm_struct *new_mm)
88 - struct mm_struct * old_mm;
92 - old_mm = current->mm;
93 if (old_mm && (old_ldt = old_mm->context.segments) != NULL) {
95 * Completely new LDT, we initialize it from the parent:
98 new_mm->context.segments = ldt;
99 new_mm->context.cpuvalid = ~0UL; /* valid on all CPU's - they can't have stale data */
102 +void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
104 + mm_copy_segments(current->mm, new_mm);
107 +void copy_task_segments(struct task_struct *from, struct mm_struct *new_mm)
109 + mm_copy_segments(from->mm, new_mm);
113 diff -Naur host/arch/i386/kernel/ptrace.c host-ptrace/arch/i386/kernel/ptrace.c
114 --- host/arch/i386/kernel/ptrace.c Fri Aug 9 15:57:14 2002
115 +++ host-ptrace/arch/i386/kernel/ptrace.c Mon Nov 11 19:03:38 2002
117 put_stack_long(child, EFL_OFFSET, tmp);
120 +extern int modify_ldt(struct task_struct *task, int func, void *ptr,
121 + unsigned long bytecount);
123 +extern struct mm_struct *proc_mm_get_mm(int fd);
125 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
127 struct task_struct *child;
129 child->ptrace |= PT_TRACESYSGOOD;
131 child->ptrace &= ~PT_TRACESYSGOOD;
136 + case PTRACE_FAULTINFO: {
137 + struct ptrace_faultinfo fault;
139 + fault = ((struct ptrace_faultinfo)
140 + { .is_write = child->thread.error_code,
141 + .addr = child->thread.cr2 });
142 + ret = copy_to_user((unsigned long *) data, &fault,
148 + case PTRACE_SIGPENDING:
149 + ret = copy_to_user((unsigned long *) data,
150 + &child->pending.signal,
151 + sizeof(child->pending.signal));
155 + struct ptrace_ldt ldt;
157 + if(copy_from_user(&ldt, (unsigned long *) data,
162 + ret = modify_ldt(child, ldt.func, ldt.ptr, ldt.bytecount);
166 + case PTRACE_SWITCH_MM: {
167 + struct mm_struct *old = child->mm;
168 + struct mm_struct *new = proc_mm_get_mm(data);
171 + ret = PTR_ERR(new);
175 + atomic_inc(&new->mm_users);
177 + child->active_mm = new;
182 diff -Naur host/arch/i386/kernel/sys_i386.c host-ptrace/arch/i386/kernel/sys_i386.c
183 --- host/arch/i386/kernel/sys_i386.c Mon Mar 19 15:35:09 2001
184 +++ host-ptrace/arch/i386/kernel/sys_i386.c Mon Nov 11 17:23:25 2002
188 /* common code for old and new mmaps */
189 -static inline long do_mmap2(
190 +long do_mmap2(struct mm_struct *mm,
191 unsigned long addr, unsigned long len,
192 unsigned long prot, unsigned long flags,
193 unsigned long fd, unsigned long pgoff)
198 - down_write(¤t->mm->mmap_sem);
199 - error = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT);
200 - up_write(¤t->mm->mmap_sem);
201 + down_write(&mm->mmap_sem);
202 + error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff);
203 + up_write(&mm->mmap_sem);
208 unsigned long prot, unsigned long flags,
209 unsigned long fd, unsigned long pgoff)
211 - return do_mmap2(addr, len, prot, flags, fd, pgoff);
212 + return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
217 if (a.offset & ~PAGE_MASK)
220 - err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
221 + err = do_mmap2(current->mm, a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
225 diff -Naur host/include/asm-i386/processor.h host-ptrace/include/asm-i386/processor.h
226 --- host/include/asm-i386/processor.h Sun Nov 10 18:47:37 2002
227 +++ host-ptrace/include/asm-i386/processor.h Mon Nov 11 17:33:30 2002
229 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
231 /* Copy and release all segment info associated with a VM */
232 +extern void mm_copy_segments(struct mm_struct *old_mm,
233 + struct mm_struct *new_mm);
234 extern void copy_segments(struct task_struct *p, struct mm_struct * mm);
235 extern void release_segments(struct mm_struct * mm);
237 diff -Naur host/include/asm-i386/ptrace.h host-ptrace/include/asm-i386/ptrace.h
238 --- host/include/asm-i386/ptrace.h Sun Sep 23 19:20:51 2001
239 +++ host-ptrace/include/asm-i386/ptrace.h Sun Nov 10 18:36:22 2002
242 #define PTRACE_SETOPTIONS 21
244 +struct ptrace_faultinfo {
246 + unsigned long addr;
252 + unsigned long bytecount;
255 +#define PTRACE_FAULTINFO 52
256 +#define PTRACE_SIGPENDING 53
257 +#define PTRACE_LDT 54
258 +#define PTRACE_SWITCH_MM 55
260 /* options set using PTRACE_SETOPTIONS */
261 #define PTRACE_O_TRACESYSGOOD 0x00000001
263 diff -Naur host/include/linux/mm.h host-ptrace/include/linux/mm.h
264 --- host/include/linux/mm.h Fri Aug 30 15:03:44 2002
265 +++ host-ptrace/include/linux/mm.h Mon Nov 11 19:08:53 2002
267 int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
268 int len, int write, int force, struct page **pages, struct vm_area_struct **vmas);
270 +extern long do_mprotect(struct mm_struct *mm, unsigned long start,
271 + size_t len, unsigned long prot);
274 * On a two-level page table, this ends up being trivial. Thus the
275 * inlining and the symmetry break with pte_alloc() that does all
278 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
280 -extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
281 - unsigned long len, unsigned long prot,
282 - unsigned long flag, unsigned long pgoff);
283 +extern unsigned long do_mmap_pgoff(struct mm_struct *mm,
284 + struct file *file, unsigned long addr,
285 + unsigned long len, unsigned long prot,
286 + unsigned long flag, unsigned long pgoff);
288 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
289 unsigned long len, unsigned long prot,
291 if ((offset + PAGE_ALIGN(len)) < offset)
293 if (!(offset & ~PAGE_MASK))
294 - ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
295 + ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, offset >> PAGE_SHIFT);
297 #ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC
298 #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
299 diff -Naur host/include/linux/proc_mm.h host-ptrace/include/linux/proc_mm.h
300 --- host/include/linux/proc_mm.h Wed Dec 31 19:00:00 1969
301 +++ host-ptrace/include/linux/proc_mm.h Mon Nov 11 17:41:09 2002
304 + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
305 + * Licensed under the GPL
312 +#define MM_MUNMAP 55
313 +#define MM_MPROTECT 56
314 +#define MM_COPY_SEGMENTS 57
317 + unsigned long addr;
319 + unsigned long prot;
320 + unsigned long flags;
322 + unsigned long offset;
326 + unsigned long addr;
330 +struct mm_mprotect {
331 + unsigned long addr;
339 + struct mm_mmap mmap;
340 + struct mm_munmap munmap;
341 + struct mm_mprotect mprotect;
347 diff -Naur host/mm/Makefile host-ptrace/mm/Makefile
348 --- host/mm/Makefile Fri Aug 9 15:57:31 2002
349 +++ host-ptrace/mm/Makefile Sun Nov 10 18:37:33 2002
353 obj-$(CONFIG_HIGHMEM) += highmem.o
354 +obj-$(CONFIG_PROC_MM) += proc_mm.o
356 include $(TOPDIR)/Rules.make
357 diff -Naur host/mm/mmap.c host-ptrace/mm/mmap.c
358 --- host/mm/mmap.c Fri Aug 9 15:57:31 2002
359 +++ host-ptrace/mm/mmap.c Mon Nov 11 17:24:18 2002
360 @@ -390,10 +390,11 @@
364 -unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, unsigned long len,
365 - unsigned long prot, unsigned long flags, unsigned long pgoff)
366 +unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file,
367 + unsigned long addr, unsigned long len,
368 + unsigned long prot, unsigned long flags,
369 + unsigned long pgoff)
371 - struct mm_struct * mm = current->mm;
372 struct vm_area_struct * vma, * prev;
373 unsigned int vm_flags;
374 int correct_wcount = 0;
375 diff -Naur host/mm/mprotect.c host-ptrace/mm/mprotect.c
376 --- host/mm/mprotect.c Fri Aug 9 15:57:31 2002
377 +++ host-ptrace/mm/mprotect.c Mon Nov 11 17:47:58 2002
382 -asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
383 +long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
384 + unsigned long prot)
386 unsigned long nstart, end, tmp;
387 struct vm_area_struct * vma, * next, * prev;
392 - down_write(¤t->mm->mmap_sem);
393 + down_write(&mm->mmap_sem);
395 - vma = find_vma_prev(current->mm, start, &prev);
396 + vma = find_vma_prev(mm, start, &prev);
398 if (!vma || vma->vm_start > start)
404 - up_write(¤t->mm->mmap_sem);
405 + up_write(&mm->mmap_sem);
409 +asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
411 + return(do_mprotect(current->mm, start, len, prot));
413 diff -Naur host/mm/proc_mm.c host-ptrace/mm/proc_mm.c
414 --- host/mm/proc_mm.c Wed Dec 31 19:00:00 1969
415 +++ host-ptrace/mm/proc_mm.c Mon Nov 11 19:07:52 2002
418 + * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
419 + * Licensed under the GPL
422 +#include "linux/proc_fs.h"
423 +#include "linux/proc_mm.h"
424 +#include "linux/file.h"
425 +#include "asm/uaccess.h"
426 +#include "asm/mmu_context.h"
428 +static struct file_operations proc_mm_fops;
430 +struct mm_struct *proc_mm_get_mm(int fd)
432 + struct mm_struct *ret = ERR_PTR(-EBADF);
439 + ret = ERR_PTR(-EINVAL);
440 + if(file->f_op != &proc_mm_fops)
443 + ret = file->private_data;
451 +extern long do_mmap2(struct mm_struct *mm, unsigned long addr,
452 + unsigned long len, unsigned long prot,
453 + unsigned long flags, unsigned long fd,
454 + unsigned long pgoff);
456 +static ssize_t write_proc_mm(struct file *file, const char *buffer,
457 + size_t count, loff_t *ppos)
459 + struct mm_struct *mm = file->private_data;
460 + struct proc_mm_op req;
463 + if(count > sizeof(req))
466 + n = copy_from_user(&req, buffer, count);
473 + struct mm_mmap *map = &req.u.mmap;
475 + ret = do_mmap2(mm, map->addr, map->len, map->prot,
476 + map->flags, map->fd, map->offset >> PAGE_SHIFT);
477 + if((ret & ~PAGE_MASK) == 0)
483 + struct mm_munmap *unmap = &req.u.munmap;
485 + down_write(&mm->mmap_sem);
486 + ret = do_munmap(mm, unmap->addr, unmap->len);
487 + up_write(&mm->mmap_sem);
493 + case MM_MPROTECT: {
494 + struct mm_mprotect *protect = &req.u.mprotect;
496 + ret = do_mprotect(mm, protect->addr, protect->len,
503 + case MM_COPY_SEGMENTS: {
504 + struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments);
507 + ret = PTR_ERR(from);
511 + mm_copy_segments(from, mm);
522 +static int open_proc_mm(struct inode *inode, struct file *file)
524 + struct mm_struct *mm = mm_alloc();
531 + ret = init_new_context(current, mm);
535 + spin_lock(&mmlist_lock);
536 + list_add(&mm->mmlist, ¤t->mm->mmlist);
538 + spin_unlock(&mmlist_lock);
540 + file->private_data = mm;
550 +static int release_proc_mm(struct inode *inode, struct file *file)
552 + struct mm_struct *mm = file->private_data;
558 +static struct file_operations proc_mm_fops = {
559 + .open = open_proc_mm,
560 + .release = release_proc_mm,
561 + .write = write_proc_mm,
564 +static int make_proc_mm(void)
566 + struct proc_dir_entry *ent;
568 + ent = create_proc_entry("mm", 0222, &proc_root);
570 + printk("make_proc_mm : Failed to register /proc/mm\n");
573 + ent->proc_fops = &proc_mm_fops;
578 +__initcall(make_proc_mm);
581 + * Overrides for Emacs so that we follow Linus's tabbing style.
582 + * Emacs will notice this stuff at the end of the file and automatically
583 + * adjust the settings for this buffer only. This must remain at the end
585 + * ---------------------------------------------------------------------------
587 + * c-file-style: "linux"