Пример #1
0
// New returns the docker default configuration for libcontainer
func New() *libcontainer.Container {
	return &libcontainer.Container{
		CapabilitiesMask: libcontainer.Capabilities{
			libcontainer.GetCapability("SETPCAP"),
			libcontainer.GetCapability("SYS_MODULE"),
			libcontainer.GetCapability("SYS_RAWIO"),
			libcontainer.GetCapability("SYS_PACCT"),
			libcontainer.GetCapability("SYS_ADMIN"),
			libcontainer.GetCapability("SYS_NICE"),
			libcontainer.GetCapability("SYS_RESOURCE"),
			libcontainer.GetCapability("SYS_TIME"),
			libcontainer.GetCapability("SYS_TTY_CONFIG"),
			libcontainer.GetCapability("MKNOD"),
			libcontainer.GetCapability("AUDIT_WRITE"),
			libcontainer.GetCapability("AUDIT_CONTROL"),
			libcontainer.GetCapability("MAC_OVERRIDE"),
			libcontainer.GetCapability("MAC_ADMIN"),
			libcontainer.GetCapability("NET_ADMIN"),
		},
		Namespaces: libcontainer.Namespaces{
			libcontainer.GetNamespace("NEWNS"),
			libcontainer.GetNamespace("NEWUTS"),
			libcontainer.GetNamespace("NEWIPC"),
			libcontainer.GetNamespace("NEWPID"),
			libcontainer.GetNamespace("NEWNET"),
		},
		Cgroups: &cgroups.Cgroup{
			Parent:       "docker",
			DeviceAccess: false,
		},
		Context: libcontainer.Context{
			"apparmor_profile": "docker-default",
		},
	}
}
Пример #2
0
// GetNamespaceFlags parses the container's Namespaces options to set the correct
// flags on clone, unshare, and setns
func GetNamespaceFlags(namespaces map[string]bool) (flag int) {
	for key, enabled := range namespaces {
		if enabled {
			if ns := libcontainer.GetNamespace(key); ns != nil {
				flag |= ns.Value
			}
		}
	}
	return flag
}
Пример #3
0
func getNsFds(pid int, container *libcontainer.Container) ([]uintptr, error) {
	fds := []uintptr{}

	for key, enabled := range container.Namespaces {
		if enabled {
			if ns := libcontainer.GetNamespace(key); ns != nil {
				f, err := os.OpenFile(filepath.Join("/proc/", strconv.Itoa(pid), "ns", ns.File), os.O_RDONLY, 0)
				if err != nil {
					return fds, err
				}
				fds = append(fds, f.Fd())
			}
		}
	}
	return fds, nil
}
Пример #4
0
// ExecIn uses an existing pid and joins the pid's namespaces with the new command.
func ExecIn(container *libcontainer.Container, nspid int, args []string) (int, error) {
	// clear the current processes env and replace it with the environment
	// defined on the container
	if err := LoadContainerEnvironment(container); err != nil {
		return -1, err
	}

	for key, enabled := range container.Namespaces {
		// skip the PID namespace on unshare because it it not supported
		if enabled && key != "NEWPID" {
			if ns := libcontainer.GetNamespace(key); ns != nil {
				if err := system.Unshare(ns.Value); err != nil {
					return -1, err
				}
			}
		}
	}
	fds, err := getNsFds(nspid, container)
	closeFds := func() {
		for _, f := range fds {
			system.Closefd(f)
		}
	}
	if err != nil {
		closeFds()
		return -1, err
	}
	processLabel, err := label.GetPidCon(nspid)
	if err != nil {
		closeFds()
		return -1, err
	}
	// foreach namespace fd, use setns to join an existing container's namespaces
	for _, fd := range fds {
		if fd > 0 {
			if err := system.Setns(fd, 0); err != nil {
				closeFds()
				return -1, fmt.Errorf("setns %s", err)
			}
		}
		system.Closefd(fd)
	}

	// if the container has a new pid and mount namespace we need to
	// remount proc and sys to pick up the changes
	if container.Namespaces["NEWNS"] && container.Namespaces["NEWPID"] {
		pid, err := system.Fork()
		if err != nil {
			return -1, err
		}
		if pid == 0 {
			// TODO: make all raw syscalls to be fork safe
			if err := system.Unshare(syscall.CLONE_NEWNS); err != nil {
				return -1, err
			}
			if err := mount.RemountProc(); err != nil {
				return -1, fmt.Errorf("remount proc %s", err)
			}
			if err := mount.RemountSys(); err != nil {
				return -1, fmt.Errorf("remount sys %s", err)
			}
			goto dropAndExec
		}
		proc, err := os.FindProcess(pid)
		if err != nil {
			return -1, err
		}
		state, err := proc.Wait()
		if err != nil {
			return -1, err
		}
		os.Exit(state.Sys().(syscall.WaitStatus).ExitStatus())
	}
dropAndExec:
	if err := FinalizeNamespace(container); err != nil {
		return -1, err
	}
	err = label.SetProcessLabel(processLabel)
	if err != nil {
		return -1, err
	}
	if err := system.Execv(args[0], args[0:], container.Env); err != nil {
		return -1, err
	}
	panic("unreachable")
}