Skip to content

Instantly share code, notes, and snippets.

@julz
Created November 20, 2015 12:39

Revisions

  1. julz created this gist Nov 20, 2015.
    57 changes: 57 additions & 0 deletions main.go
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,57 @@
    package main

    import (
    "fmt"
    "os"
    "os/exec"
    "syscall"
    )

    func main() {
    switch os.Args[1] {
    case "run":
    parent()
    case "child":
    child()
    default:
    panic("wat should I do")
    }
    }

    func parent() {
    cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
    cmd.SysProcAttr = &syscall.SysProcAttr{
    Cloneflags: syscall.CLONE_NEWUTS | syscall.CLONE_NEWPID | syscall.CLONE_NEWNS,
    }
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err := cmd.Run(); err != nil {
    fmt.Println("ERROR", err)
    os.Exit(1)
    }
    }

    func child() {
    must(syscall.Mount("rootfs", "rootfs", "", syscall.MS_BIND, ""))
    must(os.MkdirAll("rootfs/oldrootfs", 0700))
    must(syscall.PivotRoot("rootfs", "rootfs/oldrootfs"))
    must(os.Chdir("/"))

    cmd := exec.Command(os.Args[2], os.Args[3:]...)
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr

    if err := cmd.Run(); err != nil {
    fmt.Println("ERROR", err)
    os.Exit(1)
    }
    }

    func must(err error) {
    if err != nil {
    panic(err)
    }
    }