Beispiel #1
0
// ListenProcessNamespace creates a net.Listener in the namespace of the given pid.
// The arguments are identical to net.Listen.
func ListenProcessNamespace(pid uintptr, net, laddr string) (gnet.Listener, error) {
	fd, err := namespace.OpenProcess(int(pid), namespace.CLONE_NEWNET)
	defer namespace.Close(fd)
	if err != nil {
		return nil, err
	}

	return socketat(int(fd), net, laddr)
}
Beispiel #2
0
func socketat(fd int, net, laddr string) (gnet.Listener, error) {
	origNs, _ := namespace.OpenProcess(os.Getpid(), namespace.CLONE_NEWNET)
	defer syscall.Close(int(origNs))
	defer namespace.Setns(origNs, namespace.CLONE_NEWNET)

	// Join the container namespace
	err := namespace.Setns(uintptr(fd), namespace.CLONE_NEWNET)
	if err != 0 {
		return nil, err
	}

	// Create our socket
	return gnet.Listen(net, laddr)
}
func nsenterexec(containerName string, uid int, gid int, groups []int, wd string, shell string) (err error) {
	containerpid, err := dockerpid(containerName)
	if err != nil {
		panic(fmt.Sprintf("Could not get PID for container: %s", containerName))
	}
	containerSha, err := dockersha(containerName)
	if err != nil {
		panic(fmt.Sprintf("Could not get SHA for container: %s %s", err.Error(), containerName))
	}
	containerConfigLocation := fmt.Sprintf("/var/lib/docker/execdriver/native/%s/container.json", containerSha)
	container, err := loadContainer(containerConfigLocation)
	if err != nil {
		panic(fmt.Sprintf("Could not load container configuration: %v", err))
	}

	rootfd, err := openNamespaceFd(containerpid, "")
	if err != nil {
		panic(fmt.Sprintf("Could not open fd to root: %s", err))
	}
	rootfd.Close()

	cwdfd, err := openNamespaceFd(containerpid, wd)
	if err != nil {
		panic(fmt.Sprintf("Could not open fs to working directory (%s): %s", wd, err))
	}
	cwdfd.Close()

	if strings.HasPrefix(shell, "/") != true {
		return fmt.Errorf("Shell '%s' does not start with /, need an absolute path", shell)
	}
	shell = path.Clean(shell)
	shellfd, err := openNamespaceFd(containerpid, shell)
	shellfd.Close()
	if err != nil {
		return fmt.Errorf("Cannot find your shell %s inside your container", shell)
	}

	var nslist = []uintptr{namespace.CLONE_NEWIPC, namespace.CLONE_NEWUTS, namespace.CLONE_NEWNET, namespace.CLONE_NEWPID, namespace.CLONE_NEWNS} // namespace.CLONE_NEWUSER
	for _, ns := range nslist {
		nsfd, err := namespace.OpenProcess(containerpid, ns)
		if nsfd == 0 || err != nil {
			panic("namespace.OpenProcess(containerpid, xxx)")
		}
		namespace.Setns(nsfd, ns)
		namespace.Close(nsfd)
	}

	pid, err := ForkExec(shell, []string{"sh"}, &ProcAttr{
		//Env:
		Dir: wd,
		//sys.Setsid
		//sys.Setpgid
		//sys.Setctty && sys.Ctty
		Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()},
		Sys: &SysProcAttr{
			Chroot:     fmt.Sprintf("/proc/%s/root", strconv.Itoa(containerpid)),
			Credential: &Credential{Uid: uint32(uid), Gid: uint32(gid)}, //, Groups: []uint32(groups)},
		},
	})
	if err != nil {
		panic(err)
	}
	proc, err := os.FindProcess(pid)
	if err != nil {
		panic(fmt.Sprintf("Could not get proc for pid %s", strconv.Itoa(pid)))
	}
	// FIXME Race condition
	cleaner, err := namespaces.SetupCgroups(container, pid)
	if err != nil {
		proc.Kill()
		proc.Wait()
		panic(fmt.Sprintf("SetupCgroups failed: %s", err.Error()))
	}
	if cleaner != nil {
		defer cleaner.Cleanup()
	}

	var wstatus WaitStatus
	_, err1 := Wait4(pid, &wstatus, 0, nil)
	if err != nil {
		panic(err1)
	}

	return nil
}