Support PID NamespaceMode_TARGET
This commit adds support for the PID namespace mode TARGET when generating a container spec. The container that is created will be sharing its PID namespace with the target container that was specified by ID in the namespace options. Signed-off-by: Thomas Hartland <thomas.george.hartland@cern.ch>
This commit is contained in:
		| @@ -593,16 +593,16 @@ func WithSupplementalGroups(groups []int64) oci.SpecOpts { | ||||
| } | ||||
|  | ||||
| // WithPodNamespaces sets the pod namespaces for the container | ||||
| func WithPodNamespaces(config *runtime.LinuxContainerSecurityContext, pid uint32) oci.SpecOpts { | ||||
| func WithPodNamespaces(config *runtime.LinuxContainerSecurityContext, sandboxPid uint32, targetPid uint32) oci.SpecOpts { | ||||
| 	namespaces := config.GetNamespaceOptions() | ||||
|  | ||||
| 	opts := []oci.SpecOpts{ | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.NetworkNamespace, Path: GetNetworkNamespace(pid)}), | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.IPCNamespace, Path: GetIPCNamespace(pid)}), | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.UTSNamespace, Path: GetUTSNamespace(pid)}), | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.NetworkNamespace, Path: GetNetworkNamespace(sandboxPid)}), | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.IPCNamespace, Path: GetIPCNamespace(sandboxPid)}), | ||||
| 		oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.UTSNamespace, Path: GetUTSNamespace(sandboxPid)}), | ||||
| 	} | ||||
| 	if namespaces.GetPid() != runtime.NamespaceMode_CONTAINER { | ||||
| 		opts = append(opts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.PIDNamespace, Path: GetPIDNamespace(pid)})) | ||||
| 		opts = append(opts, oci.WithLinuxNamespace(runtimespec.LinuxNamespace{Type: runtimespec.PIDNamespace, Path: GetPIDNamespace(targetPid)})) | ||||
| 	} | ||||
| 	return oci.Compose(opts...) | ||||
| } | ||||
|   | ||||
| @@ -270,9 +270,24 @@ func (c *criService) containerSpec( | ||||
| 		specOpts = append(specOpts, customopts.WithAnnotation(pKey, pValue)) | ||||
| 	} | ||||
|  | ||||
| 	// Default target PID namespace is the sandbox PID. | ||||
| 	targetPid := sandboxPid | ||||
| 	// If the container targets another container's PID namespace, | ||||
| 	// set targetPid to the PID of that container. | ||||
| 	nsOpts := securityContext.GetNamespaceOptions() | ||||
| 	if nsOpts.GetPid() == runtime.NamespaceMode_TARGET { | ||||
| 		targetContainer, err := c.validateTargetContainer(sandboxID, nsOpts.TargetId) | ||||
| 		if err != nil { | ||||
| 			return nil, errors.Wrapf(err, "invalid target container") | ||||
| 		} | ||||
|  | ||||
| 		status := targetContainer.Status.Get() | ||||
| 		targetPid = status.Pid | ||||
| 	} | ||||
|  | ||||
| 	specOpts = append(specOpts, | ||||
| 		customopts.WithOOMScoreAdj(config, c.config.RestrictOOMScoreAdj), | ||||
| 		customopts.WithPodNamespaces(securityContext, sandboxPid), | ||||
| 		customopts.WithPodNamespaces(securityContext, sandboxPid, targetPid), | ||||
| 		customopts.WithSupplementalGroups(supplementalGroups), | ||||
| 		customopts.WithAnnotation(annotations.ContainerType, annotations.ContainerTypeContainer), | ||||
| 		customopts.WithAnnotation(annotations.SandboxID, sandboxID), | ||||
|   | ||||
| @@ -84,6 +84,17 @@ func (c *criService) StartContainer(ctx context.Context, r *runtime.StartContain | ||||
| 		return nil, errors.Errorf("sandbox container %q is not running", sandboxID) | ||||
| 	} | ||||
|  | ||||
| 	// Recheck target container validity in Linux namespace options. | ||||
| 	if linux := config.GetLinux(); linux != nil { | ||||
| 		nsOpts := linux.GetSecurityContext().GetNamespaceOptions() | ||||
| 		if nsOpts.GetPid() == runtime.NamespaceMode_TARGET { | ||||
| 			_, err := c.validateTargetContainer(sandboxID, nsOpts.TargetId) | ||||
| 			if err != nil { | ||||
| 				return nil, errors.Wrap(err, "invalid target container") | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ioCreation := func(id string) (_ containerdio.IO, err error) { | ||||
| 		stdoutWC, stderrWC, err := c.createContainerLoggers(meta.LogPath, config.GetTty()) | ||||
| 		if err != nil { | ||||
|   | ||||
| @@ -242,6 +242,30 @@ func (c *criService) ensureImageExists(ctx context.Context, ref string, config * | ||||
| 	return &newImage, nil | ||||
| } | ||||
|  | ||||
| // validateTargetContainer checks that a container is a valid | ||||
| // target for a container using PID NamespaceMode_TARGET. | ||||
| // The target container must be in the same sandbox and must be running. | ||||
| // Returns the target container for convenience. | ||||
| func (c *criService) validateTargetContainer(sandboxID, targetContainerID string) (containerstore.Container, error) { | ||||
| 	targetContainer, err := c.containerStore.Get(targetContainerID) | ||||
| 	if err != nil { | ||||
| 		return containerstore.Container{}, errors.Wrapf(err, "container %q does not exist", targetContainerID) | ||||
| 	} | ||||
|  | ||||
| 	targetSandboxID := targetContainer.Metadata.SandboxID | ||||
| 	if targetSandboxID != sandboxID { | ||||
| 		return containerstore.Container{}, | ||||
| 			errors.Errorf("container %q (sandbox %s) does not belong to sandbox %s", targetContainerID, targetSandboxID, sandboxID) | ||||
| 	} | ||||
|  | ||||
| 	status := targetContainer.Status.Get() | ||||
| 	if state := status.State(); state != runtime.ContainerState_CONTAINER_RUNNING { | ||||
| 		return containerstore.Container{}, errors.Errorf("container %q is not running - in state %s", targetContainerID, state) | ||||
| 	} | ||||
|  | ||||
| 	return targetContainer, nil | ||||
| } | ||||
|  | ||||
| // isInCRIMounts checks whether a destination is in CRI mount list. | ||||
| func isInCRIMounts(dst string, mounts []*runtime.Mount) bool { | ||||
| 	for _, m := range mounts { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Thomas Hartland
					Thomas Hartland