Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rootless containers from scratch

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on. →
Liz Rice
October 27, 2020

Rootless containers from scratch

As seen at OS Summit EU 2020

Liz Rice

October 27, 2020

Transcript

16 slides
  1. © 2020 Aqua Security Software Ltd., All Rights Reserved Rootless

    containers from scratch Liz Rice VP Open Source Engineering, Aqua Security @lizrice
  2. @lizrice Limit what a process can see • Unix Timesharing

    System • Process IDs • Mounts • Network • InterProcess Comms • User IDs Namespaces
  3. @lizrice Limit what a process can see • Unix Timesharing

    System • Process IDs • Mounts • Network • InterProcess Comms • User IDs Namespaces
  4. @lizrice Starting in Linux 3.8, unprivileged processes can create user

    namespaces The child process created … with the CLONE_NEWUSER flag starts out with a complete set of capabilities in the new user namespace. man user_namespaces
  5. @lizrice Starting in Linux 3.8, unprivileged processes can create user

    namespaces The child process created … with the CLONE_NEWUSER flag starts out with a complete set of capabilities in the new user namespace. If CLONE_NEWUSER is specified along with other CLONE_NEW* flags … the user namespace is guaranteed to be created first, giving the child … privileges over the remaining namespaces created by the call. man user_namespaces
  6. @lizrice Host User IDs 0 1 2 … 1000 1001

    1002 1003 … Namespace User IDs 0 1 2 … size
  7. @lizrice func main() { switch os.Args[1] { case "run": run()

    case "child": child() default: panic("Missing argument 1") } } func run() { fmt.Printf("Running %v as user %d in process %d\n", os.Args[2:], os.Geteuid(), os.Getpid()) cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin cmd.SysProcAttr = &syscall.SysProcAttr{ Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWUSER|syscall.CLONE_NEWNS|syscall.CLONE_NEWPID, UidMappings: []syscall.SysProcIDMap{{ ContainerID: 0, HostID: 1000, Size: 1}}, } must(cmd.Run()) } func child() { fmt.Printf("Running %v as user %d in process %d\n", os.Args[2:], os.Geteuid(), os.Getpid()) fmt.Printf("Capabilities: %s\n", showCaps())
  8. @lizrice func child() { fmt.Printf("Running %v as user %d in

    process %d\n", os.Args[2:], os.Geteuid(), os.Getpid()) must(syscall.Chroot("/home/vagrant/alpinefs")) must(os.Chdir("/")) must(syscall.Mount("proc", "proc", "proc", 0, "")) cmd := exec.Command(os.Args[2], os.Args[3:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Stdin = os.Stdin must(cmd.Run()) must(syscall.Unmount("proc", 0)) } func must(err error) { if err != nil { panic(err) } }
  9. © 2020 Aqua Security Software Ltd., All Rights Reserved Thank

    you github.com/rootless-containers/rootlesskit github.com/lizrice/containers-from-scratch

More Decks by Liz Rice

Other Decks in Technology