diff --git a/pkg/securitypolicy/securitypolicyenforcer.go b/pkg/securitypolicy/securitypolicyenforcer.go index 75d7460a5d..10b8c3ee8d 100644 --- a/pkg/securitypolicy/securitypolicyenforcer.go +++ b/pkg/securitypolicy/securitypolicyenforcer.go @@ -502,6 +502,13 @@ func possibleIndicesForID(containerID string, mapping map[int]map[string]struct{ // hooks.CreateRuntime hook into container spec and the hook ensures that // the expected mounts appear prior container start. At the moment enforcement // is expected to take place inside LCOW UVM. +// +// Supported scenarios: +// 1. expected mount is provided as a path inside the sandbox and it should resolve inside UVM +// e.g, "sandbox://path/on/the/host, which will correspond to "/run/gcs/c/sandboxMounts/path/on/the/host" +// 2. expected mount is provided as a path under a sandbox mount path inside container, e.g., +// sandbox mount is at path "/sandbox/mount" and wait path is "/sandbox/mount/wait/path", which +// corresponds to "/run/gcs/c/sandboxMounts/path/on/the/host/wait/path" func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerID string, spec *oci.Spec) error { pe.mutex.Lock() defer pe.mutex.Unlock() @@ -521,6 +528,9 @@ func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerI return errors.New("no valid container indices found") } + // Unlike environment variable and command line enforcement, there isn't anything + // to validate here, since we're essentially just injecting hooks when necessary + // for all containers. matchFound := false for _, index := range pIndices { if !matchFound { @@ -539,10 +549,22 @@ func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerI for _, mount := range wMounts { wp := "" if strings.HasPrefix(mount, guestpath.SandboxMountPrefix) { + // This covers case #1, and we replace sandbox mount prefix with the sandbox + // mounts path inside UVM sandboxPath := strings.TrimPrefix(mount, guestpath.SandboxMountPrefix) wp = filepath.Join(guestpath.LCOWRootPrefixInUVM, "sandboxMounts", sandboxPath) } else { - // Find the corresponding sandbox mount and resolve the path inside UVM. + // This covers case #2. Iterate through container mounts to identify the + // correct sandbox mount where the wait path is nested under. The mount + // spec will be something like: + // { + // "source": "/run/gcs/c/sandboxMounts/path/on/host", + // "destination": "/sandbox/mount" + // } + // The wait path will be "/sandbox/mount/wait/path". To find the corresponding + // sandbox mount do a prefix match on wait path against all container mounts Destination + // and resolve the full path inside UVM. For example above it becomes + // "/run/gcs/c/sandboxMounts/path/on/host/wait/path" for _, m := range spec.Mounts { if strings.HasPrefix(mount, m.Destination) { wp = filepath.Join(m.Source, strings.TrimPrefix(mount, m.Destination)) diff --git a/test/vendor/github.com/Microsoft/hcsshim/pkg/securitypolicy/securitypolicyenforcer.go b/test/vendor/github.com/Microsoft/hcsshim/pkg/securitypolicy/securitypolicyenforcer.go index 75d7460a5d..10b8c3ee8d 100644 --- a/test/vendor/github.com/Microsoft/hcsshim/pkg/securitypolicy/securitypolicyenforcer.go +++ b/test/vendor/github.com/Microsoft/hcsshim/pkg/securitypolicy/securitypolicyenforcer.go @@ -502,6 +502,13 @@ func possibleIndicesForID(containerID string, mapping map[int]map[string]struct{ // hooks.CreateRuntime hook into container spec and the hook ensures that // the expected mounts appear prior container start. At the moment enforcement // is expected to take place inside LCOW UVM. +// +// Supported scenarios: +// 1. expected mount is provided as a path inside the sandbox and it should resolve inside UVM +// e.g, "sandbox://path/on/the/host, which will correspond to "/run/gcs/c/sandboxMounts/path/on/the/host" +// 2. expected mount is provided as a path under a sandbox mount path inside container, e.g., +// sandbox mount is at path "/sandbox/mount" and wait path is "/sandbox/mount/wait/path", which +// corresponds to "/run/gcs/c/sandboxMounts/path/on/the/host/wait/path" func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerID string, spec *oci.Spec) error { pe.mutex.Lock() defer pe.mutex.Unlock() @@ -521,6 +528,9 @@ func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerI return errors.New("no valid container indices found") } + // Unlike environment variable and command line enforcement, there isn't anything + // to validate here, since we're essentially just injecting hooks when necessary + // for all containers. matchFound := false for _, index := range pIndices { if !matchFound { @@ -539,10 +549,22 @@ func (pe *StandardSecurityPolicyEnforcer) EnforceExpectedMountsPolicy(containerI for _, mount := range wMounts { wp := "" if strings.HasPrefix(mount, guestpath.SandboxMountPrefix) { + // This covers case #1, and we replace sandbox mount prefix with the sandbox + // mounts path inside UVM sandboxPath := strings.TrimPrefix(mount, guestpath.SandboxMountPrefix) wp = filepath.Join(guestpath.LCOWRootPrefixInUVM, "sandboxMounts", sandboxPath) } else { - // Find the corresponding sandbox mount and resolve the path inside UVM. + // This covers case #2. Iterate through container mounts to identify the + // correct sandbox mount where the wait path is nested under. The mount + // spec will be something like: + // { + // "source": "/run/gcs/c/sandboxMounts/path/on/host", + // "destination": "/sandbox/mount" + // } + // The wait path will be "/sandbox/mount/wait/path". To find the corresponding + // sandbox mount do a prefix match on wait path against all container mounts Destination + // and resolve the full path inside UVM. For example above it becomes + // "/run/gcs/c/sandboxMounts/path/on/host/wait/path" for _, m := range spec.Mounts { if strings.HasPrefix(mount, m.Destination) { wp = filepath.Join(m.Source, strings.TrimPrefix(mount, m.Destination))