Skip to contentSkip to conversation

host-skas3 for 2.6.9-rc2

PATCH In review Gerd Knorr 2 participants 3 messages Sep 16, 2004 – Sep 20, 2004 6 messages not in the archive

Subsystems (7)
lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 20040913144250.GA17259@bytesex

A message that is not in the archive (sent off-list or not yet received): [email protected]

A message that is not in the archive (sent off-list or not yet received): 20040915144213.GA32509@bytesex

A message that is not in the archive (sent off-list or not yet received): 20040916110323.GB12785@bytesex

Gerd Knorr

author
#5 lore raw

PATCH 1/1 host-skas3 for 2.6.9-rc2

Quoted 2 lines · Gerd Knorr

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

arch/i386/Kconfig +4 -0
Index: host-2.6.9-rc2/arch/i386/Kconfig
===================================================================
@@ -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"
arch/i386/kernel/entry.S +5 -2
Index: host-2.6.9-rc2/arch/i386/kernel/entry.S
===================================================================
@@ -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
arch/i386/kernel/ldt.c +23 -15
Index: host-2.6.9-rc2/arch/i386/kernel/ldt.c
===================================================================
@@ -18,6 +18,7 @@
 #include <asm/system.h>
 #include <asm/ldt.h>
 #include <asm/desc.h>
+#include <asm/mmu_context.h>
 
 #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 && (&current->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(&current->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);
+}
arch/i386/kernel/ptrace.c +65 -3

116 lines not on this page · raw message

arch/i386/kernel/sys_i386.c +6 -6
Index: host-2.6.9-rc2/arch/i386/kernel/sys_i386.c
===================================================================
@@ -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(&current->mm->mmap_sem);
-	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
-	up_write(&current->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;
 }
include/asm-i386/desc.h +3 -0
Index: host-2.6.9-rc2/include/asm-i386/desc.h
===================================================================
@@ -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
include/asm-i386/mmu_context.h +18 -2
Index: host-2.6.9-rc2/include/asm-i386/mmu_context.h
===================================================================
@@ -6,13 +6,26 @@
 #include <asm/atomic.h>
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
+#include <asm/semaphore.h>
 
 /*
- * 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 
include/asm-i386/ptrace.h +22 -0
Index: host-2.6.9-rc2/include/asm-i386/ptrace.h
===================================================================
@@ -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
include/asm-i386/thread_info.h +3 -1
Index: host-2.6.9-rc2/include/asm-i386/thread_info.h
===================================================================
@@ -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<<TIF_NEED_RESCHED)
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
+#define _TIF_SYSCALL_EMU	(1<<TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
+  (0x0000FFFF & ~(_TIF_SYSCALL_EMU|_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
 #define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
 
 /*
include/linux/mm.h +11 -2
Index: host-2.6.9-rc2/include/linux/mm.h
===================================================================
@@ -623,6 +623,9 @@ struct shrinker;
 extern struct shrinker *set_shrinker(int, shrinker_t);
 extern void remove_shrinker(struct shrinker *shrinker);
 
+extern long do_mprotect(struct mm_struct *mm, unsigned long start,
+			size_t len, unsigned long prot);
+
 /*
  * On a two-level page table, this ends up being trivial. Thus the
  * inlining and the symmetry break with pte_alloc_map() that does all
@@ -682,9 +685,15 @@ extern void exit_mmap(struct mm_struct *
 
 extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
-extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
+extern unsigned long __do_mmap_pgoff(struct mm_struct *mm, struct file *file,
+				   unsigned long addr, unsigned long len,
+				   unsigned long prot, unsigned long flag,
+				   unsigned long pgoff);
+static inline unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
-	unsigned long flag, unsigned long pgoff);
+	unsigned long flag, unsigned long pgoff) {
+	return __do_mmap_pgoff(current->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,
include/linux/proc_mm.h +48 -0

48 lines not on this page · raw message

include/linux/ptrace.h +1 -0
Index: host-2.6.9-rc2/include/linux/ptrace.h
===================================================================
@@ -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
kernel/fork.c +1 -0
Index: host-2.6.9-rc2/kernel/fork.c
===================================================================
@@ -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 */
mm/Makefile +1 -1
Index: host-2.6.9-rc2/mm/Makefile
===================================================================
@@ -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
mm/mmap.c +5 -5
Index: host-2.6.9-rc2/mm/mmap.c
===================================================================
@@ -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.
mm/mprotect.c +15 -8
Index: host-2.6.9-rc2/mm/mprotect.c
===================================================================
@@ -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(&current->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(&current->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(&current->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(&current->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));
+}
mm/proc_mm.c +181 -0

181 lines not on this page · raw message

-------------------------------------------------------
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 [email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

#6 lore raw
Quoted 7 lines · Gerd Knorr
Quoted 2 lines · Gerd Knorr

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.

Well, please cleanup it, because you are affecting the behaviour on fork() (the change should be harmless, however, just repeating arch_pick_mmap_layout()).

Without the SKAS patch, init_new_context does not call arch_pick_mmap_layout(), so it should not after ( and init_new_context calls, actually, init_new_empty_context()). I think that the proper place to add the call is open_proc_mm(). Do you agree on this?

Bye

Signature · 13 lines
Paolo Giarrusso, aka Blaisorblade
Linux registered user n. 292729


-------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

A message that is not in the archive (sent off-list or not yet received): 20040920153737.GA9823@bytesex

#8 lore raw
Quoted 6 lines · Gerd Knorr
Quoted 4 lines

Without the SKAS patch, init_new_context does not call arch_pick_mmap_layout(), so it should not after ( and init_new_context calls, actually, init_new_empty_context()). I think that the proper place to add the call is open_proc_mm(). Do you agree on this?

Sounds ok, changed that, tested, works, new version below.

Yes, agreed.

Quoted 2 lines

There is
also another fix in enter_lazy_tlb()

In switch_mm, actually.

Quoted 2 lines

: use the per_cpu() macro (also
new in 2.6.9-rc I think).

Ah, yes, that is the only change which I had made when porting the SKAS patch to 2.6.9, while fixing the reject below. Basically, what we do is to make sure that the BUG_ON check that we remove cannot be triggered; that check is done if prev == next, so we must make sure to give to "prev" the value that "next" is supposed to have.

The reason is that with PTRACE_SWITCH_MM a thread can be scheduled away while having one MM and rescheduled while having a new MM; and if when it's scheduled away, a kernel thread goes executing, the kernel thread (using a lazy TLB) will keep using the old MM, the one switched away with PTRACE_SWITCH_MM, and the one you get with per_cpu(...). The "prev" and "next" args, instead, come from current->mm, so prev is wrong (the kernel code didn't notice that current->mm has changed). However, this can only be triggered on SMP, when the ptracing thread (the UML kernel thread) executes on a different CPU than the userspace thread.

Bye

Signature · 13 lines
Paolo Giarrusso, aka Blaisorblade
Linux registered user n. 292729


-------------------------------------------------------
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
[email protected]
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel