Goals
Get root privilege
- payload:
| 1 | commit_creds(prepare_kernel_cred(0)) |
Escape SECCOMP
- payload:
| 1 | current->thread_info.flags &= ~(1 << TIF_SECCOMP) |
Run single command
- payload:
| 1 | run_cmd("/path/to/command") |
Background
Kernel Space & User Space
- Linux memory divides into 2 separated areas: Kernel Space and User Space
- User needs to ask the kernel for help by sending requests which is called System Calls
- On x86-64 arch, after calling
syscall, the CPU enters kernel mode and calls theentry_SYSCALL_64()function. It will then search and execute requested system call fromsys_call_table
Task
Linux kernel doesn't distinguish between Processes and Threads, it defines them all as Tasks by calling
copy_process()functionWhen tasks are created, they are allocated a
task_structstructure, one for each task
| 1 | struct task_struct { |
| 2 | |
| 3 | /* |
| 4 | * For reasons of header soup (see current_thread_info()), this |
| 5 | * must be the first element of task_struct. |
| 6 | */ |
| 7 | struct thread_info thread_info; |
| 8 | |
| 9 | unsigned int __state; |
| 10 | /* saved state for "spinlock sleepers" */ |
| 11 | unsigned int saved_state; |
| 12 | /* |
| 13 | * This begins the randomizable portion of task_struct. Only |
| 14 | * scheduling-critical items should be added above here. |
| 15 | */ |
| 16 | randomized_struct_fields_start |
| 17 | void *stack; |
| 18 | refcount_t usage; |
| 19 | /* Per task flags (PF_*), defined further below: */ |
| 20 | unsigned int flags; |
| 21 | unsigned int ptrace; |
| 22 | |
| 23 | int on_cpu; |
| 24 | struct __call_single_node wake_entry; |
| 25 | unsigned int wakee_flips; |
| 26 | unsigned long wakee_flip_decay_ts; |
| 27 | struct task_struct *last_wakee; |
| 28 | ... |
| 29 | } |
task_structstores most essential metadata and state information for a taskpid_t pidis the process IDpid_t tgidis the thread group ID. All threads generated within a same parent process share identical TGID values.char comm[TASK_COMM_LEN]: An array of characters that stores the executable binary of the task. Used to identify the task.struct list_head tasks: A doubly linked-list of active tasks in the kernel.struct task_struct __rcu *parent: Points to the task's parent task.struct list_head children: A linked-list of all child tasks.struct mm_struct *mm: Pointer to a struct mm_struct for the task's memory management.struct files_struct *files: Pointer to files_struct, a struct that manages the files that the taskopen()has opened. This member manages the list of files that the task is opening and the state of each file.struct signal_struct *signal: A pointer to a signal_struct, a struct containing information for handling signals. This handles the incomming signals.
The
currentmacro is a pointer to thetask_structstruct of the task currently running on CPU.
Memory Architecture
- Looking at the structure of
mm_struct, it looks like this:
| 1 | struct mm_struct { |
| 2 | struct { |
| 3 | ... |
| 4 | unsigned long start_code, end_code, start_data, end_data; |
| 5 | unsigned long start_brk, brk, start_stack; |
| 6 | unsigned long arg_start, arg_end, env_start, env_end; |
| 7 | ... |
| 8 | } __randomize_layout; |
| 9 | /* |
| 10 | * The mm_cpumask needs to be at the end of mm_struct, because it |
| 11 | * is dynamically sized based on nr_cpu_ids. |
| 12 | */ |
| 13 | unsigned long cpu_bitmap[]; |
| 14 | }; |
start_codeandend_codeare about code segmentstart_dataandend_dataare about data segmentstart_brkandbrkare about heap segment.brkcan be incrementedstart_stackis the start address of the stack segmentAll above are belongs to user space. The main memory structures in the kernel are summarized below:
0x0000000000000000 ~ 0x00007fffffffffff: The virtual address of user space. Each process has its own independent area0xffff888000000000 ~ 0xffffc87fffffffff: Direct mapping of all physical memory region0xffffc90000000000 ~ 0xffffe8ffffffffff:vmallocarea. It is virtually contiguous (physicaly non-contiguous) allocations0xffffffff80000000 ~ 0xffffffff9fffffff: The area where the kernel code is located.0xffffffffa0000000 ~ 0xfffffffffeffffff: The area where the kernel modules are located.
Other areas are Vmemmap Region and KASAN Shadow Region
The above memory map corresponds to 4-level Page Tables on x86-64 arch, and its structure may vary depending on whenther or not the kernel has the
CONFIG_X86_5LEVEL(5-level page tables)