static void modify_cs(struct mm_struct *mm, unsigned long limit) { mm->context.exec_limit = limit; set_user_cs(&mm->context.user_cs, limit); if (mm == current->mm) { int cpu; cpu = get_cpu(); load_user_cs_desc(cpu, mm); put_cpu(); } }
/* * lazy-check for CS validity on exec-shield binaries: * * the original non-exec stack patch was written by * Solar Designer <solar at openwall.com>. Thanks! */ static int check_lazy_exec_limit(int cpu, struct pt_regs *regs, long error_code) { struct desc_struct *desc1, *desc2; struct vm_area_struct *vma; unsigned long limit; if (current->mm == NULL) return 0; limit = -1UL; if (current->mm->context.exec_limit != -1UL) { limit = PAGE_SIZE; spin_lock(¤t->mm->page_table_lock); for (vma = current->mm->mmap; vma; vma = vma->vm_next) if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) limit = vma->vm_end; vma = get_gate_vma(current->mm); if (vma && (vma->vm_flags & VM_EXEC) && (vma->vm_end > limit)) limit = vma->vm_end; spin_unlock(¤t->mm->page_table_lock); if (limit >= TASK_SIZE) limit = -1UL; current->mm->context.exec_limit = limit; } set_user_cs(¤t->mm->context.user_cs, limit); desc1 = ¤t->mm->context.user_cs; desc2 = get_cpu_gdt_table(cpu) + GDT_ENTRY_DEFAULT_USER_CS; if (__compare_user_cs_desc(desc1, desc2)) { /* * The CS was not in sync - reload it and retry the * instruction. If the instruction still faults then * we won't hit this branch next time around. */ if (print_fatal_signals >= 2) { printk(KERN_ERR "#GPF fixup (%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->ip, smp_processor_id()); printk(KERN_ERR "exec_limit: %08lx, user_cs: %08x/%08x, CPU_cs: %08x/%08x.\n", current->mm->context.exec_limit, desc1->a, desc1->b, desc2->a, desc2->b); } load_user_cs_desc(cpu, current->mm); return 1; } return 0; }
void arch_flush_exec_range(struct mm_struct *mm) { mm->context.exec_limit = 0; set_user_cs(&mm->context.user_cs, 0); }