Linux Kernel Security Research-Stack Overflow
By wzt <wzt.wzt@gmail.com>
I. background:
Stack overflow is different from the Stack buffer overflow I have previously published. They all occur in the kernel stack overflow.
Jon Oberheide mentioned a new method of stack overflow attack in his blog. He roughly talked about the overflow principle and didn't provide the poc. I tried to study it,
Summarize the debugging methods in the past few days.
2. Understand the kernel stack:
When the user space program enters the kernel space through int 0x80, the CPU automatically completes a stack switch, switching from the user space stack to the kernel space stack.
All system calls that occur before the exit of this process use the same kernel stack. The size of the kernel stack is generally 4096/8192. I drew a kernel stack to help you understand:
Memory low-address memory high-address
| <----------------------------- Esp |
+ ------------------------------------- 4096 ------------------------------- +
| 72 | 4 | x <4016 | 4 |
+ ------------------ + ----------------- + --------------------------------- +
| Thread_info | STACK_END_MAGIC | var/call chain | stack_canary |
+ ------------------ + ----------------- + --------------------------------- +
| 28 | 44 |
V |
Restart_block V
Esp + 0x0 + 0x40
+ --------------------------------------------------------------------------- +
| Ebx | ecx | edx | esi | edi | ebp | eax | ds | es | fs | gs | orig_eax | eip | cs | eflags | oldesp | oldss |
+ --------------------------------------------------------------------------- +
| Kernel completed | cpu automatically completed |
In the old kernel, struct task_struct is used to describe a process structure. In the new kernel, The task_struct structure is encapsulated in struct thread_info:
Struct thread_info {
Struct task_struct * task;/* main task structure */
Struct exec_domain * exec_domain;/* execution domain */
_ U32 flags;/* low level flags */
_ U32 status;/* thread synchronous flags */
_ U32 cpu;/* current CPU */
Int preempt_count;/* 0 => preemptable,
<0 => BUG */
Mm_segment_t addr_limit;
Struct restart_block;
Void _ user * sysenter_return;
# Ifdef CONFIG_X86_32
Unsigned long previus_esp;/* ESP of the previous stack in
Case of nested (IRQ) stacks
*/
_ U8 supervisor_stack [0];
# Endif
Int uaccess_err;
};
Its first field points to the task_stuct pointer of the current process. Note that it is a pointer rather than a struct. The size of task_struct in my 2.6.36.2 kernel is 1196 bytes, while thread_info
The size is 72 bytes, so saving a pointer will greatly save the Kernel Heap.