110 likes | 273 Views
Sandboxing Project. By Team Sandbox Asaf Cohen, Yaron Rozen. What we need to do?. Create a sandbox mechanism inside the kernel. A sandbox is a security mechanism for separating processes from the rest of the system.
E N D
Sandboxing Project By Team Sandbox Asaf Cohen, Yaron Rozen
What we need to do? • Create a sandbox mechanism inside the kernel. • A sandbox is a security mechanism for separating processes from the rest of the system. • Purpose: run untested programs, even with root privileges with no worry.
How are we going to do it? • We are implementing the sandbox mechanism with the following additions to the kernel: • Adding new system call for sandbox creation, and fork into sandbox. • Adding a struct sandbox member to task_struct. • Will hold an id and a bitmask. • The default id value will be 0 (means: no sandbox). • Changing copy_process to close unauthorized resources (according to sandbox.id). • Adding sandbox_wrapper to Entry(system_call)
Adding new system calls • intsys_sb_create(bitmap, chroot_dir) • intsys_sb_destroy(sand_id) • int sys_sb_fork_into(sand_id)
sandbox member in task_struct • Each sand_id will identify a single sandbox_struct in the kernel. • This structure will hold a syscall_bitmap(in future iterations: permission_bitmap) • sand_id will be given to copy_process() by sys_sb_fork()
Copy_process • Inside copy_process() we add handlers to prevent copy of resources during fork, so we limit the task struct of the sandboxed process. • copy_files(clone_flags, p); • copy_fs(clone_flags, p); • copy_mm(clone_flags, p); • ....
Sandbox wrapper • ENTRY(system_call) • …. • call sandbox_wrapper • Jnz failure • call *sys_call_table(,%rax,8) • intsandbox_wrapper() • Task_struct t = current()->task; • If (t.sandbox.id != 0): // sandboxed • return t.sandbox.bitmask[eax] // bitmask treatment
How the sandbox is enforced? 2) Requires a service from the kernel using a system call Sandboxed Process User Mode Kernel Mode System call Kernel Entry here we add sandbox_wrapper() • Task Struct: • state • pid • … • struct sandbox = { • id (zero indicates no sandbox) • bitmap (controls syscall execution) • } 1) Each task structure has a new sandbox member, if the id is different than zero the process is sandboxed. 3) Allows/Denies the system call according to the bitmap
Timeline from process perspective (1) The (pseudo)code of the parent process: intsand_id = SYSCALL(sys_sb_create, bitmap, chroot_dir) intpid = SYSCALL(sys_sb_fork_into, sand_id) if (pid = 0) { // child code runs in sandbox SYSCALL(sys_exec_once, [exec_params … ]) } else { // parent code wait(pid); // monitors child } SYSCALL(sys_sb_destroy, sand_id)
Timeline from process perspective (2) • Parent task (pid = 70) is not sandboxed(sandbox.id = 0) • Calls sys_sb_create(bitmap, chroot_dir) • In the kernel a new sandbox with id 2 and the given bitmap is initalized. • Task recieves new sandbox id 2 in user mode. • Calls sys_sb_fork_into(2) • The kernel forks a new task struct with parameters: • pid = 80 • ppid = 70 • sandbox.id = 2 • sandbox.bitmap = bitmap
Timeline from process perspective (3) • The child loads its code into memory using a new syscall: sys_exec_once() • sys_exec_once() performs exactly what sys_execve() does except that sys_exec_once also clears the allow bit of sys_exec_once from the bitmap. • We assume here that the the parent denies the child from using exec() in the sandbox permissions bitmap. • This is a simple solution to a “chicken and egg” problem. • The code of the child runs in sandbox number 2, that is, every syscall is analyzed in the kernel before execution according to bitmap.