Thursday, October 16, 2014

Is this a good security design in Linux kernel? -- connections between thread_info and kernel stack

In Linux kernel, thread_info is a small CPU-specific data structure that stores some low-level task data for corresponding process, it also has a pointer to task_struct, which is a processor-independent process control block data structure, e.g. scheduling, virtual memory structures.


/* x86 * 64 */
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                  saved_preempt_count;
 mm_segment_t         addr_limit;
 struct restart_block restart_block;
 void __user          *sysenter_return;
 unsigned int         sig_on_uaccess_error:1;
 unsigned int         uaccess_err:1; /* uaccess failed */
};

Every user process has its unique two stacks, one is for code running in user mode, and the other is kernel stack for code execution running in kernel mode. 

The current design is like below picture, the kernel stack space of process and its thread_info structure are located together (at two ends because stack grows down). This is because it offers a key benefit in terms of efficiency: the kernel can easily obtain the address of the thread_info structure of the process currently running on a CPU from the value of its kernel ESP register

For example as below, %eax eventually holds the pointer to thread_info structure.

movl $0xFFFFE000, %eax
andl %esp,        %eax (mask out last 13 bits)


Connections between task_struct and kernel stack

How to find thread_info from kernel stack?

* Note that these pictures above are from Junfeng's operating system course slides.
http://www.cs.columbia.edu/~junfeng/10sp-w4118/syllabus.html (or link).


From security's point of view, this means that whenever the address of kernel stack is leaked for some reasons (e.g. a bug, vulnerability), the address of corresponding thread_info structure will also be leaked. And as you can see that we can also get the address of task_struct as long as the address of thread_info is gotten. 

The task_struct is a one of very critical kernel data structures in Linux system, for example, it contains the credentials (uid, gid, suid, sgid...). Provided that there is a kernel vulnerability that can cause arbitrary kernel memory overwrite, then those credential fields could be clear by an exploit to get root privilege even without executing any code in kernel mode. 

So, the question: is this a bad security design? Could we do something to improve it? 

See my previous post for monitoring Windows thread scheduling, it seems that Windows operating system uses FS (or GS) to retrieve thread-related structure for current running thread. However, as far as I know, in Linux system, fs/gs are used for LTS (Local Thread Storage) purpose. 

UPDATE:

  1. Fortunately I got an idea (not too bad idea:-) to mitigate this issue, I will talk about it later in a new post.
  2. Add references for "stack overflow" attack against this bad design.


Exploiting Stack Overflows in the Linux Kernel
https://jon.oberheide.org/blog/2010/11/29/exploiting-stack-overflows-in-the-linux-kernel/

Exploiting stack overflows
https://jon.oberheide.org/files/infiltrate12-thestackisback.pdf

Exploiting the Futex Bug and uncovering Towelroot
http://tinyhack.com/2014/07/07/exploiting-the-futex-bug-and-uncovering-towelroot/

SMEP: What is It, and How to Beat It on Linux
http://vulnfactory.org/blog/2011/06/05/smep-what-is-it-and-how-to-beat-it-on-linux/


No comments:

Post a Comment