]> git.pld-linux.org Git - packages/kernel.git/blame - host-skas3.patch
- added description of djurban's branch
[packages/kernel.git] / host-skas3.patch
CommitLineData
decd1569 1diff -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
4@@ -291,6 +291,8 @@
5 bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF
6 fi
7
8+bool '/proc/mm' CONFIG_PROC_MM
9+
10 endmenu
11
12 source drivers/mtd/Config.in
13diff -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
16@@ -24,11 +24,12 @@
17 * assured by user-space anyway. Writes are atomic, to protect
18 * the security checks done on new descriptors.
19 */
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)
23 {
24 int err;
25 unsigned long size;
26- struct mm_struct * mm = current->mm;
27+ struct mm_struct * mm = task->mm;
28
29 err = 0;
30 if (!mm->context.segments)
31@@ -64,9 +65,10 @@
32 return err;
33 }
34
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)
38 {
39- struct mm_struct * mm = current->mm;
40+ struct mm_struct * mm = task->mm;
41 __u32 entry_1, entry_2, *lp;
42 int error;
43 struct modify_ldt_ldt_s ldt_info;
44@@ -148,23 +150,29 @@
45 return error;
46 }
47
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)
51 {
52 int ret = -ENOSYS;
53
54 switch (func) {
55 case 0:
56- ret = read_ldt(ptr, bytecount);
57+ ret = read_ldt(task, ptr, bytecount);
58 break;
59 case 1:
60- ret = write_ldt(ptr, bytecount, 1);
61+ ret = write_ldt(task, ptr, bytecount, 1);
62 break;
63 case 2:
64 ret = read_default_ldt(ptr, bytecount);
65 break;
66 case 0x11:
67- ret = write_ldt(ptr, bytecount, 0);
68+ ret = write_ldt(task, ptr, bytecount, 0);
69 break;
70 }
71 return ret;
72+}
73+
74+asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
75+{
76+ return(modify_ldt(current, func, ptr, bytecount));
77 }
78diff -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
81@@ -551,13 +551,11 @@
82 * we do not have to muck with descriptors here, that is
83 * done in switch_mm() as needed.
84 */
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)
87 {
88- struct mm_struct * old_mm;
89 void *old_ldt, *ldt;
90
91 ldt = NULL;
92- old_mm = current->mm;
93 if (old_mm && (old_ldt = old_mm->context.segments) != NULL) {
94 /*
95 * Completely new LDT, we initialize it from the parent:
96@@ -570,6 +568,16 @@
97 }
98 new_mm->context.segments = ldt;
99 new_mm->context.cpuvalid = ~0UL; /* valid on all CPU's - they can't have stale data */
100+}
101+
102+void copy_segments(struct task_struct *p, struct mm_struct *new_mm)
103+{
104+ mm_copy_segments(current->mm, new_mm);
105+}
106+
107+void copy_task_segments(struct task_struct *from, struct mm_struct *new_mm)
108+{
109+ mm_copy_segments(from->mm, new_mm);
110 }
111
112 /*
113diff -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
116@@ -147,6 +147,11 @@
117 put_stack_long(child, EFL_OFFSET, tmp);
118 }
119
120+extern int modify_ldt(struct task_struct *task, int func, void *ptr,
121+ unsigned long bytecount);
122+
123+extern struct mm_struct *proc_mm_get_mm(int fd);
124+
125 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
126 {
127 struct task_struct *child;
128@@ -415,6 +420,53 @@
129 child->ptrace |= PT_TRACESYSGOOD;
130 else
131 child->ptrace &= ~PT_TRACESYSGOOD;
132+ ret = 0;
133+ break;
134+ }
135+
136+ case PTRACE_FAULTINFO: {
137+ struct ptrace_faultinfo fault;
138+
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,
143+ sizeof(fault));
144+ if(ret)
145+ break;
146+ break;
147+ }
148+ case PTRACE_SIGPENDING:
149+ ret = copy_to_user((unsigned long *) data,
150+ &child->pending.signal,
151+ sizeof(child->pending.signal));
152+ break;
153+
154+ case PTRACE_LDT: {
155+ struct ptrace_ldt ldt;
156+
157+ if(copy_from_user(&ldt, (unsigned long *) data,
158+ sizeof(ldt))){
159+ ret = -EIO;
160+ break;
161+ }
162+ ret = modify_ldt(child, ldt.func, ldt.ptr, ldt.bytecount);
163+ break;
164+ }
165+
166+ case PTRACE_SWITCH_MM: {
167+ struct mm_struct *old = child->mm;
168+ struct mm_struct *new = proc_mm_get_mm(data);
169+
170+ if(IS_ERR(new)){
171+ ret = PTR_ERR(new);
172+ break;
173+ }
174+
175+ atomic_inc(&new->mm_users);
176+ child->mm = new;
177+ child->active_mm = new;
178+ mmput(old);
179 ret = 0;
180 break;
181 }
182diff -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
185@@ -40,7 +40,7 @@
186 }
187
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)
194@@ -55,9 +55,9 @@
195 goto out;
196 }
197
198- down_write(&current->mm->mmap_sem);
199- error = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT);
200- up_write(&current->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);
204
205 if (file)
206 fput(file);
207@@ -69,7 +69,7 @@
208 unsigned long prot, unsigned long flags,
209 unsigned long fd, unsigned long pgoff)
210 {
211- return do_mmap2(addr, len, prot, flags, fd, pgoff);
212+ return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff);
213 }
214
215 /*
216@@ -100,7 +100,7 @@
217 if (a.offset & ~PAGE_MASK)
218 goto out;
219
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);
222 out:
223 return err;
224 }
225diff -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
228@@ -436,6 +436,8 @@
229 extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
230
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);
236
237diff -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
240@@ -51,6 +51,22 @@
241
242 #define PTRACE_SETOPTIONS 21
243
244+struct ptrace_faultinfo {
245+ int is_write;
246+ unsigned long addr;
247+};
248+
249+struct ptrace_ldt {
250+ int func;
251+ void *ptr;
252+ unsigned long bytecount;
253+};
254+
255+#define PTRACE_FAULTINFO 52
256+#define PTRACE_SIGPENDING 53
257+#define PTRACE_LDT 54
258+#define PTRACE_SWITCH_MM 55
259+
260 /* options set using PTRACE_SETOPTIONS */
261 #define PTRACE_O_TRACESYSGOOD 0x00000001
262
263diff -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
266@@ -492,6 +492,9 @@
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);
269
270+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
271+ size_t len, unsigned long prot);
272+
273 /*
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
276@@ -539,9 +542,10 @@
277
278 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
279
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);
287
288 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
289 unsigned long len, unsigned long prot,
290@@ -551,7 +555,7 @@
291 if ((offset + PAGE_ALIGN(len)) < offset)
292 goto out;
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);
296
297 #ifdef CONFIG_GRKERNSEC_PAX_SEGMEXEC
298 #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE)
299diff -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
302@@ -0,0 +1,44 @@
303+/*
304+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
305+ * Licensed under the GPL
306+ */
307+
308+#ifndef __PROC_MM_H
309+#define __PROC_MM_H
310+
311+#define MM_MMAP 54
312+#define MM_MUNMAP 55
313+#define MM_MPROTECT 56
314+#define MM_COPY_SEGMENTS 57
315+
316+struct mm_mmap {
317+ unsigned long addr;
318+ unsigned long len;
319+ unsigned long prot;
320+ unsigned long flags;
321+ unsigned long fd;
322+ unsigned long offset;
323+};
324+
325+struct mm_munmap {
326+ unsigned long addr;
327+ unsigned long len;
328+};
329+
330+struct mm_mprotect {
331+ unsigned long addr;
332+ unsigned long len;
333+ unsigned int prot;
334+};
335+
336+struct proc_mm_op {
337+ int op;
338+ union {
339+ struct mm_mmap mmap;
340+ struct mm_munmap munmap;
341+ struct mm_mprotect mprotect;
342+ int copy_segments;
343+ } u;
344+};
345+
346+#endif
347diff -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
350@@ -17,5 +17,6 @@
351 shmem.o
352
353 obj-$(CONFIG_HIGHMEM) += highmem.o
354+obj-$(CONFIG_PROC_MM) += proc_mm.o
355
356 include $(TOPDIR)/Rules.make
357diff -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 @@
361 return 0;
362 }
363
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)
370 {
371- struct mm_struct * mm = current->mm;
372 struct vm_area_struct * vma, * prev;
373 unsigned int vm_flags;
374 int correct_wcount = 0;
375diff -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
378@@ -264,7 +264,8 @@
379 return 0;
380 }
381
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)
385 {
386 unsigned long nstart, end, tmp;
387 struct vm_area_struct * vma, * next, * prev;
388@@ -281,9 +282,9 @@
389 if (end == start)
390 return 0;
391
392- down_write(&current->mm->mmap_sem);
393+ down_write(&mm->mmap_sem);
394
395- vma = find_vma_prev(current->mm, start, &prev);
396+ vma = find_vma_prev(mm, start, &prev);
397 error = -ENOMEM;
398 if (!vma || vma->vm_start > start)
399 goto out;
400@@ -332,6 +333,11 @@
401 }
402 out:
403
404- up_write(&current->mm->mmap_sem);
405+ up_write(&mm->mmap_sem);
406 return error;
407+}
408+
409+asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
410+{
411+ return(do_mprotect(current->mm, start, len, prot));
412 }
413diff -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
416@@ -0,0 +1,173 @@
417+/*
418+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
419+ * Licensed under the GPL
420+ */
421+
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"
427+
428+static struct file_operations proc_mm_fops;
429+
430+struct mm_struct *proc_mm_get_mm(int fd)
431+{
432+ struct mm_struct *ret = ERR_PTR(-EBADF);
433+ struct file *file;
434+
435+ file = fget(fd);
436+ if (!file)
437+ goto out;
438+
439+ ret = ERR_PTR(-EINVAL);
440+ if(file->f_op != &proc_mm_fops)
441+ goto out_fput;
442+
443+ ret = file->private_data;
444+
445+ out_fput:
446+ fput(file);
447+ out:
448+ return(ret);
449+}
450+
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);
455+
456+static ssize_t write_proc_mm(struct file *file, const char *buffer,
457+ size_t count, loff_t *ppos)
458+{
459+ struct mm_struct *mm = file->private_data;
460+ struct proc_mm_op req;
461+ int n, ret;
462+
463+ if(count > sizeof(req))
464+ return(-EINVAL);
465+
466+ n = copy_from_user(&req, buffer, count);
467+ if(n != 0)
468+ return(-EFAULT);
469+
470+ ret = count;
471+ switch(req.op){
472+ case MM_MMAP: {
473+ struct mm_mmap *map = &req.u.mmap;
474+
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)
478+ ret = count;
479+
480+ break;
481+ }
482+ case MM_MUNMAP: {
483+ struct mm_munmap *unmap = &req.u.munmap;
484+
485+ down_write(&mm->mmap_sem);
486+ ret = do_munmap(mm, unmap->addr, unmap->len);
487+ up_write(&mm->mmap_sem);
488+
489+ if(ret == 0)
490+ ret = count;
491+ break;
492+ }
493+ case MM_MPROTECT: {
494+ struct mm_mprotect *protect = &req.u.mprotect;
495+
496+ ret = do_mprotect(mm, protect->addr, protect->len,
497+ protect->prot);
498+ if(ret == 0)
499+ ret = count;
500+ break;
501+ }
502+
503+ case MM_COPY_SEGMENTS: {
504+ struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments);
505+
506+ if(IS_ERR(from)){
507+ ret = PTR_ERR(from);
508+ break;
509+ }
510+
511+ mm_copy_segments(from, mm);
512+ break;
513+ }
514+ default:
515+ ret = -EINVAL;
516+ break;
517+ }
518+
519+ return(ret);
520+}
521+
522+static int open_proc_mm(struct inode *inode, struct file *file)
523+{
524+ struct mm_struct *mm = mm_alloc();
525+ int ret;
526+
527+ ret = -ENOMEM;
528+ if(mm == NULL)
529+ goto out_mem;
530+
531+ ret = init_new_context(current, mm);
532+ if(ret)
533+ goto out_free;
534+
535+ spin_lock(&mmlist_lock);
536+ list_add(&mm->mmlist, &current->mm->mmlist);
537+ mmlist_nr++;
538+ spin_unlock(&mmlist_lock);
539+
540+ file->private_data = mm;
541+
542+ return(0);
543+
544+ out_free:
545+ mmput(mm);
546+ out_mem:
547+ return(ret);
548+}
549+
550+static int release_proc_mm(struct inode *inode, struct file *file)
551+{
552+ struct mm_struct *mm = file->private_data;
553+
554+ mmput(mm);
555+ return(0);
556+}
557+
558+static struct file_operations proc_mm_fops = {
559+ .open = open_proc_mm,
560+ .release = release_proc_mm,
561+ .write = write_proc_mm,
562+};
563+
564+static int make_proc_mm(void)
565+{
566+ struct proc_dir_entry *ent;
567+
568+ ent = create_proc_entry("mm", 0222, &proc_root);
569+ if(ent == NULL){
570+ printk("make_proc_mm : Failed to register /proc/mm\n");
571+ return(0);
572+ }
573+ ent->proc_fops = &proc_mm_fops;
574+
575+ return(0);
576+}
577+
578+__initcall(make_proc_mm);
579+
580+/*
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
584+ * of the file.
585+ * ---------------------------------------------------------------------------
586+ * Local variables:
587+ * c-file-style: "linux"
588+ * End:
589+ */
This page took 0.148597 seconds and 4 git commands to generate.