func main() { libPath := flag.String("lib", "./lib", "Directory containing hooks") rootFsPath := flag.String("root", "", "Directory that will become root in the new mount namespace") runPath := flag.String("run", "./run", "Directory where server socket is placed") userNsFlag := flag.String("userns", "enabled", "If specified, use user namespacing") title := flag.String("title", "", "") flag.Parse() if *rootFsPath == "" { missing("--root") } binPath, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { fmt.Fprintf(os.Stderr, "wshd: obtain absolute path: %s", err) os.Exit(6) } socketPath := path.Join(*runPath, "wshd.sock") privileged := false if *userNsFlag == "" || *userNsFlag == "disabled" { privileged = true } containerReader, hostWriter, err := os.Pipe() if err != nil { fmt.Fprintf(os.Stderr, "wshd: create pipe: %s", err) os.Exit(5) } hostReader, containerWriter, err := os.Pipe() if err != nil { fmt.Fprintf(os.Stderr, "wshd: create pipe: %s", err) os.Exit(4) } sync := &containerizer.PipeSynchronizer{ Reader: hostReader, Writer: hostWriter, } listener, err := unix_socket.NewListenerFromPath(socketPath) if err != nil { fmt.Fprintf(os.Stderr, "wshd: create listener: %s", err) os.Exit(8) } socketFile, err := listener.File() if err != nil { fmt.Fprintf(os.Stderr, "wshd: obtain listener file: %s", err) os.Exit(9) } beforeCloneInitializer := &system.Initializer{Steps: []system.StepRunner{ &containerizer.FuncStep{ (&container_daemon.RlimitsManager{}).Init, }, }} maxUID := sysinfo.Min(sysinfo.MustGetMaxValidUID(), sysinfo.MustGetMaxValidGID()) cz := containerizer.Containerizer{ BeforeCloneInitializer: beforeCloneInitializer, InitBinPath: path.Join(binPath, "initc"), InitArgs: []string{ "--root", *rootFsPath, "--config", path.Join(*libPath, "../etc/config"), "--title", *title, }, Execer: &system.NamespacingExecer{ CommandRunner: linux_command_runner.New(), ExtraFiles: []*os.File{containerReader, containerWriter, socketFile}, Privileged: privileged, MaxUID: maxUID, }, Signaller: sync, Waiter: sync, // Temporary until we merge the hook scripts functionality in Golang CommandRunner: linux_command_runner.New(), LibPath: *libPath, RootfsPath: *rootFsPath, } err = cz.Create() if err != nil { fmt.Fprintf(os.Stderr, "Failed to create container: %s", err) os.Exit(2) } }
"github.com/cloudfoundry-incubator/garden-linux/containerizer" "github.com/cloudfoundry-incubator/garden-linux/containerizer/fake_container_execer" "github.com/cloudfoundry-incubator/garden-linux/containerizer/fake_initializer" "github.com/cloudfoundry-incubator/garden-linux/containerizer/fake_signaller" "github.com/cloudfoundry-incubator/garden-linux/containerizer/fake_waiter" "github.com/cloudfoundry-incubator/garden-linux/hook" . "github.com/cloudfoundry/gunk/command_runner/fake_command_runner" . "github.com/cloudfoundry/gunk/command_runner/fake_command_runner/matchers" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Containerizer", func() { Describe("Create", func() { var cz *containerizer.Containerizer var containerExecer *fake_container_execer.FakeContainerExecer var signaller *fake_signaller.FakeSignaller var waiter *fake_waiter.FakeWaiter var hookCommandRunner *FakeCommandRunner var beforeCloneInitializer *fake_initializer.FakeInitializer BeforeEach(func() { containerExecer = &fake_container_execer.FakeContainerExecer{} signaller = &fake_signaller.FakeSignaller{} waiter = &fake_waiter.FakeWaiter{} hookCommandRunner = &FakeCommandRunner{} beforeCloneInitializer = &fake_initializer.FakeInitializer{} cz = &containerizer.Containerizer{ BeforeCloneInitializer: beforeCloneInitializer,
// initc initializes a newly created container and then execs to become // the init process func main() { if reexec.Init() { return } defer func() { if r := recover(); r != nil { fmt.Fprintf(os.Stderr, "initc: panicked: %s\n", r) os.Exit(4) } }() rootFsPath := flag.String("root", "", "Path for the root file system directory") configFilePath := flag.String("config", "./etc/config", "Path for the configuration file") title := flag.String("title", "", "") cf_lager.AddFlags(flag.CommandLine) flag.Parse() if *rootFsPath == "" { missing("--root") } syncReader := os.NewFile(uintptr(3), "/dev/a") defer syncReader.Close() syncWriter := os.NewFile(uintptr(4), "/dev/d") defer syncWriter.Close() sync := &containerizer.PipeSynchronizer{ Reader: syncReader, Writer: syncWriter, } if err := sync.Wait(2 * time.Minute); err != nil { fail(fmt.Sprintf("initc: wait for host: %s", err), 8) } env, err := process.EnvFromFile(*configFilePath) if err != nil { fmt.Fprintf(os.Stderr, "initc: failed to get env from config file: %s\n", err) os.Exit(3) } dropCapabilities := env["root_uid"] != "0" procMountFlags := syscall.MS_NOSUID | syscall.MS_NODEV | syscall.MS_NOEXEC sysMountFlags := syscall.MS_NOSUID | syscall.MS_NODEV | syscall.MS_NOEXEC | syscall.MS_RDONLY if dropCapabilities { procMountFlags = procMountFlags | syscall.MS_RDONLY } initializer := &system.Initializer{ Steps: []system.StepRunner{ &containerizer.FuncStep{system.Mount{ Type: system.Tmpfs, Flags: syscall.MS_NODEV, TargetPath: "/dev/shm", }.Mount}, &containerizer.FuncStep{system.Mount{ Type: system.Proc, Flags: procMountFlags, TargetPath: "/proc", }.Mount}, &containerizer.FuncStep{system.Mount{ Type: system.Sys, Flags: sysMountFlags, TargetPath: "/sys", }.Mount}, &containerizer.FuncStep{system.Mount{ Type: system.Devpts, TargetPath: "/dev/pts", Data: "newinstance,ptmxmode=0666", }.Mount}, &containerizer.FuncStep{system.Unmount{ Dir: "/tmp/garden-host", }.Unmount}, &containerizer.FuncStep{func() error { return setupNetwork(env) }}, &containerizer.CapabilitiesStep{ Drop: dropCapabilities, Capabilities: &sys.ProcessCapabilities{Pid: os.Getpid()}, }, }, } containerizer := containerizer.Containerizer{ RootfsPath: *rootFsPath, ContainerInitializer: initializer, Waiter: sync, Signaller: sync, } if err := containerizer.Init(); err != nil { fail(fmt.Sprintf("failed to init containerizer: %s", err), 2) } syscall.RawSyscall(syscall.SYS_FCNTL, uintptr(4), syscall.F_SETFD, 0) syscall.RawSyscall(syscall.SYS_FCNTL, uintptr(5), syscall.F_SETFD, 0) if err := syscall.Exec("/proc/self/exe", []string{"initd", fmt.Sprintf("-dropCapabilities=%t", dropCapabilities), fmt.Sprintf("-title=\"%s\"", *title)}, os.Environ()); err != nil { fail(fmt.Sprintf("failed to reexec: %s", err), 3) } }