It is known that most remote exploits use the fact that stacks are
executable (in i386, at least).

On Linux, they use INT 80 system calls to execute functions in the kernel
as root, when the stack is smashed as a result of a buffer overflow bug in
various server software.

This preliminary, small patch prevents execution of system calls which
were executed from a writable segment. It was tested and seems to work,
without breaking anything. It also reports of such calls by using printk.


--- linux/arch/i386/kernel/entry.S      Tue Dec 12 20:04:08 2000
+++ linux/arch/i386/kernel/entry.S      Wed Jan  3 22:46:24 2001
@@ -78,8 +78,16 @@
 exec_domain    = 16
 need_resched   = 20
 tsk_ptrace     = 24
+tsk_mm         = 44
 processor      = 52
 
+/*
+ * these are offsets into vm_area_struct
+ */
+
+vmas_flags     = 20
+
+
 ENOSYS = 38
 
 
@@ -196,6 +204,26 @@
        pushl %eax                      # save orig_eax
        SAVE_ALL
        GET_CURRENT(%ebx)
+
+       /* only execute code from non-writable segments */
+       pushl %ebx
+       pushl %eax
+       movl tsk_mm(%ebx),%eax          # get current->mm
+       movl (EIP+8)(%esp),%ebx         # get caller EIP
+       pushl %ebx
+       pushl %eax
+       call find_vma
+       addl $8,%esp
+       testl %eax,%eax
+       je no_vm_area
+       movl vmas_flags(%eax), %ebx
+       andl $0x02, %ebx
+       cmpl $0x02, %ebx
+       je sys_from_wrong_mem
+no_vm_area:
+       popl %eax
+       popl %ebx
+       
        cmpl $(NR_syscalls),%eax
        jae badsys
        testb $0x02,tsk_ptrace(%ebx)    # PT_TRACESYS
@@ -252,6 +280,15 @@
 tracesys_exit:
        call SYMBOL_NAME(syscall_trace)
        jmp ret_from_sys_call
+
+sys_from_wrong_mem:
+       GET_CURRENT(%ebx)
+       push %ebx
+       call print_bad_syscall
+       addl $4,%esp    
+       
+       popl %eax
+       popl %ebx
 badsys:
        movl $-ENOSYS,EAX(%esp)
        jmp ret_from_sys_call
--- linux/arch/i386/kernel/process.c    Wed Jan  3 22:57:42 2001
+++ linux/arch/i386/kernel/process.c    Wed Jan  3 22:57:55 2001
@@ -765,3 +765,8 @@
 }
 #undef last_sched
 #undef first_sched
+
+void print_bad_syscall(struct task_struct *task)
+{
+       printk("process %s (%d) tried to syscall from an executable segment!\n", 
+task->comm, task->pid);
+}


-- 
Dan Aloni 
[EMAIL PROTECTED]

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to