Created
January 21, 2025 12:40
-
-
Save johnpmitsch/9d76eaad99338b4486c6889ef6e61771 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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