예제 #1
0
func (d *driver) createNetwork(container *libcontainer.Config, c *execdriver.Command) error {
	if c.Network.HostNetworking {
		container.Namespaces["NEWNET"] = false
		return nil
	}

	container.Networks = []*libcontainer.Network{
		{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
			Gateway: "localhost",
			Type:    "loopback",
		},
	}

	if c.Network.Interface != nil {
		vethNetwork := libcontainer.Network{
			Mtu:        c.Network.Mtu,
			Address:    fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
			MacAddress: c.Network.Interface.MacAddress,
			Gateway:    c.Network.Interface.Gateway,
			Type:       "veth",
			Bridge:     c.Network.Interface.Bridge,
			VethPrefix: "veth",
		}
		container.Networks = append(container.Networks, &vethNetwork)
	}

	if c.Network.ContainerID != "" {
		if d.driverType == execdriver.NativeBuiltin {
			d.Lock()
			active := d.activeContainers[c.Network.ContainerID]
			d.Unlock()

			if active == nil || active.cmd.Process == nil {
				return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
			}
			cmd := active.cmd

			nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
			container.Networks = append(container.Networks, &libcontainer.Network{
				Type:   "netns",
				NsPath: nspath,
			})
		} else { // external container
			state, err := libcontainer.GetState(filepath.Join(d.root, c.Network.ContainerID))
			if err != nil {
				return fmt.Errorf("Read container state error: %v", err)
			}
			nspath := filepath.Join("/proc", fmt.Sprint(state.InitPid), "ns", "net")
			container.Networks = append(container.Networks, &libcontainer.Network{
				Type:   "netns",
				NsPath: nspath,
			})
		}

	}

	return nil
}
예제 #2
0
파일: create.go 프로젝트: viirya/docker
func (d *driver) createNetwork(container *libcontainer.Config, c *execdriver.Command) error {
	if c.Network.HostNetworking {
		container.Namespaces.Remove(libcontainer.NEWNET)
		return nil
	}

	container.Networks = []*libcontainer.Network{
		{
			Mtu:     c.Network.Mtu,
			Address: fmt.Sprintf("%s/%d", "127.0.0.1", 0),
			Gateway: "localhost",
			Type:    "loopback",
		},
	}

	if c.Network.Interface != nil {
		vethNetwork := libcontainer.Network{
			Mtu:        c.Network.Mtu,
			Address:    fmt.Sprintf("%s/%d", c.Network.Interface.IPAddress, c.Network.Interface.IPPrefixLen),
			MacAddress: c.Network.Interface.MacAddress,
			Gateway:    c.Network.Interface.Gateway,
			Type:       "veth",
			Bridge:     c.Network.Interface.Bridge,
			VethPrefix: "veth",
		}
		if c.Network.Interface.GlobalIPv6Address != "" {
			vethNetwork.IPv6Address = fmt.Sprintf("%s/%d", c.Network.Interface.GlobalIPv6Address, c.Network.Interface.GlobalIPv6PrefixLen)
			vethNetwork.IPv6Gateway = c.Network.Interface.IPv6Gateway
		}
		container.Networks = append(container.Networks, &vethNetwork)
	}

	if c.Network.ContainerID != "" {
		d.Lock()
		active := d.activeContainers[c.Network.ContainerID]
		d.Unlock()

		if active == nil || active.cmd.Process == nil {
			return fmt.Errorf("%s is not a valid running container to join", c.Network.ContainerID)
		}
		cmd := active.cmd

		nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
		container.Namespaces.Add(libcontainer.NEWNET, nspath)
	}

	return nil
}
예제 #3
0
파일: create.go 프로젝트: 98pm/docker
func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
	container.Capabilities = capabilities.GetAllCapabilities()
	container.Cgroups.AllowAllDevices = true

	hostDeviceNodes, err := devices.GetHostDeviceNodes()
	if err != nil {
		return err
	}
	container.MountConfig.DeviceNodes = hostDeviceNodes

	container.RestrictSys = false

	if apparmor.IsEnabled() {
		container.AppArmorProfile = "unconfined"
	}

	return nil
}
예제 #4
0
파일: create.go 프로젝트: viirya/docker
func (d *driver) setupRlimits(container *libcontainer.Config, c *execdriver.Command) {
	if c.Resources == nil {
		return
	}

	for _, rlimit := range c.Resources.Rlimits {
		container.Rlimits = append(container.Rlimits, libcontainer.Rlimit((*rlimit)))
	}
}
예제 #5
0
파일: parse.go 프로젝트: 98pm/docker
func dropCap(container *libcontainer.Config, context interface{}, value string) error {
	// If the capability is specified multiple times, remove all instances.
	for i, capability := range container.Capabilities {
		if capability == value {
			container.Capabilities = append(container.Capabilities[:i], container.Capabilities[i+1:]...)
		}
	}

	// The capability wasn't found so we will drop it anyways.
	return nil
}
예제 #6
0
// TODO(vmarmol): Switch to getting this from libcontainer once we have a solid API.
func (self *dockerContainerHandler) readLibcontainerConfig() (*libcontainer.Config, error) {
	out, err := ioutil.ReadFile(self.libcontainerConfigPath)
	if err != nil {
		return nil, fmt.Errorf("failed to read libcontainer config from %q: %v", self.libcontainerConfigPath, err)
	}
	var config libcontainer.Config
	err = json.Unmarshal(out, &config)
	if err != nil {
		// TODO(vmarmol): Remove this once it becomes the standard.
		// Try to parse the old config. The main difference is that namespaces used to be a map, now it is a slice of structs.
		// The JSON marshaler will use the non-nested field before the nested one.
		type oldLibcontainerConfig struct {
			libcontainer.Config
			OldNamespaces map[string]bool `json:"namespaces,omitempty"`
		}
		var oldConfig oldLibcontainerConfig
		err2 := json.Unmarshal(out, &oldConfig)
		if err2 != nil {
			// Use original error.
			return nil, fmt.Errorf("failed to parse libcontainer config at %q: %v", self.libcontainerConfigPath, err)
		}

		// Translate the old config into the new config.
		config = oldConfig.Config
		for ns := range oldConfig.OldNamespaces {
			config.Namespaces = append(config.Namespaces, libcontainer.Namespace{
				Type: libcontainer.NamespaceType(ns),
			})
		}
	}

	// Replace cgroup parent and name with our own since we may be running in a different context.
	config.Cgroups.Name = self.cgroup.Name
	config.Cgroups.Parent = self.cgroup.Parent

	return &config, nil
}
예제 #7
0
파일: create.go 프로젝트: kieslee/docker
func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
	container.Capabilities = capabilities.GetAllCapabilities()
	container.Cgroups.AllowAllDevices = true

	hostDeviceNodes, err := devices.GetHostDeviceNodes()
	if err != nil {
		return err
	}
	container.MountConfig.DeviceNodes = hostDeviceNodes

	delete(container.Context, "restrictions")

	if apparmor.IsEnabled() {
		container.Context["apparmor_profile"] = "unconfined"
	}

	return nil
}
예제 #8
0
파일: parse.go 프로젝트: 98pm/docker
func joinNetNamespace(container *libcontainer.Config, context interface{}, value string) error {
	var (
		running = context.(map[string]*exec.Cmd)
		cmd     = running[value]
	)

	if cmd == nil || cmd.Process == nil {
		return fmt.Errorf("%s is not a valid running container to join", value)
	}

	nspath := filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "net")
	container.Networks = append(container.Networks, &libcontainer.Network{
		Type:   "netns",
		NsPath: nspath,
	})

	return nil
}
예제 #9
0
파일: create.go 프로젝트: NERSC/docker
func (d *driver) createIpc(container *libcontainer.Config, c *execdriver.Command) error {
	if c.Ipc.HostIpc {
		container.Namespaces["NEWIPC"] = false
		return nil
	}

	if c.Ipc.ContainerID != "" {
		d.Lock()
		active := d.activeContainers[c.Ipc.ContainerID]
		d.Unlock()

		if active == nil || active.cmd.Process == nil {
			return fmt.Errorf("%s is not a valid running container to join", c.Ipc.ContainerID)
		}
		cmd := active.cmd

		container.IpcNsPath = filepath.Join("/proc", fmt.Sprint(cmd.Process.Pid), "ns", "ipc")
	}

	return nil
}
예제 #10
0
파일: create.go 프로젝트: 98pm/docker
func (d *driver) setupLabels(container *libcontainer.Config, c *execdriver.Command) error {
	container.ProcessLabel = c.Config["process_label"][0]
	container.MountConfig.MountLabel = c.Config["mount_label"][0]

	return nil
}
예제 #11
0
파일: create.go 프로젝트: NERSC/docker
func (d *driver) setupLabels(container *libcontainer.Config, c *execdriver.Command) error {
	container.ProcessLabel = c.ProcessLabel
	container.MountConfig.MountLabel = c.MountLabel

	return nil
}
예제 #12
0
파일: parse.go 프로젝트: 98pm/docker
func apparmorProfile(container *libcontainer.Config, context interface{}, value string) error {
	container.AppArmorProfile = value
	return nil
}
예제 #13
0
파일: parse.go 프로젝트: 98pm/docker
func addCap(container *libcontainer.Config, context interface{}, value string) error {
	container.Capabilities = append(container.Capabilities, value)
	return nil
}
예제 #14
0
func initUserNs(container *libcontainer.Config, uncleanRootfs, consolePath string, pipe *os.File, args []string) (err error) {
	// clear the current processes env and replace it with the environment
	// defined on the container
	if err := LoadContainerEnvironment(container); err != nil {
		return err
	}

	// We always read this as it is a way to sync with the parent as well
	var networkState *network.NetworkState
	if err := json.NewDecoder(pipe).Decode(&networkState); err != nil {
		return err
	}
	// join any namespaces via a path to the namespace fd if provided
	if err := joinExistingNamespaces(container.Namespaces); err != nil {
		return err
	}
	if consolePath != "" {
		if err := console.OpenAndDup("/dev/console"); err != nil {
			return err
		}
	}
	if _, err := syscall.Setsid(); err != nil {
		return fmt.Errorf("setsid %s", err)
	}
	if consolePath != "" {
		if err := system.Setctty(); err != nil {
			return fmt.Errorf("setctty %s", err)
		}
	}

	if container.WorkingDir == "" {
		container.WorkingDir = "/"
	}

	if err := setupRlimits(container); err != nil {
		return fmt.Errorf("setup rlimits %s", err)
	}

	cloneFlags := GetNamespaceFlags(container.Namespaces)

	if container.Hostname != "" {
		if (cloneFlags & syscall.CLONE_NEWUTS) == 0 {
			return fmt.Errorf("unable to set the hostname without UTS namespace")
		}
		if err := syscall.Sethostname([]byte(container.Hostname)); err != nil {
			return fmt.Errorf("unable to sethostname %q: %s", container.Hostname, err)
		}
	}

	if err := apparmor.ApplyProfile(container.AppArmorProfile); err != nil {
		return fmt.Errorf("set apparmor profile %s: %s", container.AppArmorProfile, err)
	}

	if err := label.SetProcessLabel(container.ProcessLabel); err != nil {
		return fmt.Errorf("set process label %s", err)
	}

	if container.RestrictSys {
		if (cloneFlags & syscall.CLONE_NEWNS) == 0 {
			return fmt.Errorf("unable to restrict access to kernel files without mount namespace")
		}
		if err := restrict.Restrict("proc/sys", "proc/sysrq-trigger", "proc/irq", "proc/bus"); err != nil {
			return err
		}
	}

	pdeathSignal, err := system.GetParentDeathSignal()
	if err != nil {
		return fmt.Errorf("get parent death signal %s", err)
	}

	if err := FinalizeNamespace(container); err != nil {
		return fmt.Errorf("finalize namespace %s", err)
	}

	// FinalizeNamespace can change user/group which clears the parent death
	// signal, so we restore it here.
	if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
		return fmt.Errorf("restore parent death signal %s", err)
	}

	return system.Execv(args[0], args[0:], os.Environ())
}