From: Bodo Stroesser The SKAS3 host patch isn't smp-safe. The wrong part is the implementation of PTRACE_LDT. If the ptraced child runs on an other processor than its parent, and the child's mm still is the active_mm, the changed LDT isn't flushed out. The problem occurs in alloc_ldt, but to fix this, I had to change the params of copy_ldt, too. Signed-off-by: Paolo 'Blaisorblade' Giarrusso --- clean-linux-2.6.11-paolo/arch/i386/kernel/ldt.c | 23 +++++++++++++---------- 1 files changed, 13 insertions(+), 10 deletions(-) diff -puN arch/i386/kernel/ldt.c~ptrace_ldt-reload-smp-fix arch/i386/kernel/ldt.c --- clean-linux-2.6.11/arch/i386/kernel/ldt.c~ptrace_ldt-reload-smp-fix 2005-07-10 16:55:35.000000000 +0200 +++ clean-linux-2.6.11-paolo/arch/i386/kernel/ldt.c 2005-07-10 16:55:35.000000000 +0200 @@ -28,11 +28,12 @@ static void flush_ldt(void *null) } #endif -static int alloc_ldt(mm_context_t *pc, int mincount, int reload) +static int alloc_ldt(struct mm_struct *mm, int mincount, int reload) { void *oldldt; void *newldt; int oldsize; + mm_context_t * pc = &mm->context; if (mincount <= pc->size) return 0; @@ -55,17 +56,19 @@ static int alloc_ldt(mm_context_t *pc, i pc->size = mincount; wmb(); - if (reload && (¤t->active_mm->context == pc)) { + if (reload) { #ifdef CONFIG_SMP cpumask_t mask; preempt_disable(); - load_LDT(pc); + if (¤t->active_mm->context == pc) + load_LDT(pc); mask = cpumask_of_cpu(smp_processor_id()); - if (!cpus_equal(current->mm->cpu_vm_mask, mask)) + if (!cpus_equal(mm->cpu_vm_mask, mask)) smp_call_function(flush_ldt, NULL, 1, 1); preempt_enable(); #else - load_LDT(pc); + if (¤t->active_mm->context == pc) + load_LDT(pc); #endif } if (oldsize) { @@ -77,12 +80,12 @@ static int alloc_ldt(mm_context_t *pc, i return 0; } -static inline int copy_ldt(mm_context_t *new, mm_context_t *old) +static inline int copy_ldt(struct mm_struct *new, struct mm_struct *old) { - int err = alloc_ldt(new, old->size, 0); + int err = alloc_ldt(new, old->context.size, 0); if (err < 0) return err; - memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE); + memcpy(new->context.ldt, old->context.ldt, old->context.size*LDT_ENTRY_SIZE); return 0; } @@ -96,7 +99,7 @@ int copy_context(struct mm_struct *mm, s if (old_mm && old_mm->context.size > 0) { down(&old_mm->context.sem); - retval = copy_ldt(&mm->context, &old_mm->context); + retval = copy_ldt(mm, old_mm); up(&old_mm->context.sem); } return retval; @@ -202,7 +205,7 @@ static int write_ldt(struct mm_struct * down(&mm->context.sem); if (ldt_info.entry_number >= mm->context.size) { - error = alloc_ldt(&mm->context, ldt_info.entry_number+1, 1); + error = alloc_ldt(mm, ldt_info.entry_number+1, 1); if (error < 0) goto out_unlock; } _