Skip to content

Instantly share code, notes, and snippets.

@johnpmitsch
Created January 21, 2025 12:40
Show Gist options
  • Save johnpmitsch/9d76eaad99338b4486c6889ef6e61771 to your computer and use it in GitHub Desktop.
Save johnpmitsch/9d76eaad99338b4486c6889ef6e61771 to your computer and use it in GitHub Desktop.
package main
import (
"os"
"os/exec"
"syscall"
)
func main() {
switch os.Args[1] {
case "run":
run()
case "child":
child()
default:
panic("Error")
}
}
func run() {
cmd := exec.Command("/proc/self/exe", append([]string{"child"}, os.Args[2:]...)...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.SysProcAttr = &syscall.SysProcAttr{
Cloneflags: syscall.CLONE_NEWUTS |
// CLONE_NEWUTS: Unix Timesharing System namespace
// Isolates hostname and NIS domain name
// Test: hostname command inside vs outside container
// Demo: hostname inside shows "im_a_container"
syscall.CLONE_NEWNET |
// CLONE_NEWNET: Network namespace
// Isolates network interfaces, ports, routing tables, etc.
// Test: ip addr show inside vs outside container
// Demo: Only loopback interface visible inside container
syscall.CLONE_NEWPID |
// CLONE_NEWPID: Process ID namespace
// Isolates process IDs - processes inside see different PIDs
// Test: ps aux inside vs outside container
// Demo: Inside container, init process shows as PID 1
syscall.CLONE_NEWNS |
// CLONE_NEWNS: Mount namespace
// Isolates filesystem mount points
// Test: mount command inside vs outside container
// Demo: /proc mount inside container is isolated
syscall.CLONE_NEWIPC |
// CLONE_NEWIPC: IPC namespace
// Isolates System V IPC objects and POSIX message queues
// Test: ipcs command inside vs outside container
// Demo: IPC resources created outside not visible inside
syscall.CLONE_NEWUSER,
// CLONE_NEWUSER: User namespace
// Isolates user and group ID number spaces
// Test: id command inside vs outside container
// Demo: Root (uid 0) inside maps to unprivileged user outside
UidMappings: []syscall.SysProcIDMap{
{
ContainerID: 0, // Maps to root inside container
HostID: os.Getuid(), // Actual user ID outside
Size: 1,
},
},
GidMappings: []syscall.SysProcIDMap{
{
ContainerID: 0, // Maps to root group inside container
HostID: os.Getgid(), // Actual group ID outside
Size: 1,
},
},
}
must(cmd.Run())
}
func child() {
syscall.Sethostname([]byte("im_a_container"))
must(syscall.Chdir("/rootfs/rootfs"))
must(syscall.Mount("proc", "proc", "proc", 0, ""))
cmd := exec.Command(os.Args[2], os.Args[3:]...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), "PS1=🐳 this is a container # ")
must(cmd.Run())
}
func must(err error) {
if err != nil {
panic(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment