Skip to content

guest: use OCIBundlePath as sandbox root source of truth#2653

Open
shreyanshjain7174 wants to merge 1 commit intomicrosoft:mainfrom
shreyanshjain7174:sandbox-path-refactor
Open

guest: use OCIBundlePath as sandbox root source of truth#2653
shreyanshjain7174 wants to merge 1 commit intomicrosoft:mainfrom
shreyanshjain7174:sandbox-path-refactor

Conversation

@shreyanshjain7174
Copy link
Copy Markdown
Contributor

@shreyanshjain7174 shreyanshjain7174 commented Mar 31, 2026

Guest-side GCS currently derives sandbox paths by combining a hard-coded prefix (/run/gcs/c) with the sandbox ID, ignoring the OCIBundlePath the host already sends. This breaks with Shim v2 path layouts and multi-pod UVMs.

This PR stores settings.OCIBundlePath as the canonical sandbox root on the Host struct (sandboxRoots map), and threads the resolved root through all setup and cleanup functions instead of re-deriving it.

For virtual pods, the sandbox root is derived from OCIBundlePath's parent directory (preserving the virtual-pods/ layout). For workload containers, it's looked up from the mapping. A legacy fallback ensures backwards compatibility with shim v1.

When the old shim sends OCIBundlePath in the legacy format, all paths are identical to before — verified by parity tests and a full CRI lifecycle (crictl runp/create/start/stop/rm) on a Hyper-V UVM.

Depends on: #2655 (bug fix for leaked LCOW resources) — both PRs modify uvm.go cleanup paths. Will rebase after #2655 merges.

@shreyanshjain7174 shreyanshjain7174 requested a review from a team as a code owner March 31, 2026 12:55
@shreyanshjain7174 shreyanshjain7174 force-pushed the sandbox-path-refactor branch 2 times, most recently from bbc4d4d to 7deb168 Compare March 31, 2026 13:05
@rawahars rawahars requested a review from helsaawy March 31, 2026 20:28
Copy link
Copy Markdown
Contributor

@rawahars rawahars left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall love the simplification of the virtual pod vs normal pod differentiation.

Major comments are regarding keeping existing utility methods, while removing virtual pod specific ones and then changing these methods to return paths/values which you are creating on the fly. That would make it easier to review too.

@rawahars
Copy link
Copy Markdown
Contributor

@anmaxvl Can you please take a look too to see if any invariant of Security Policy gets impacted with this change. As I see it that should not change but please do confirm that.

@anmaxvl
Copy link
Copy Markdown
Contributor

anmaxvl commented Apr 1, 2026

@micromaomao as well.

@micromaomao
Copy link
Copy Markdown
Member

@anmaxvl:

@micromaomao as well.

I will have a closer look tomorrow, but I think this is probably good because #2581 added validation to settings.OCIBundlePath (not in this PR's branch yet but in main) to force it to be the expected value.

@shreyanshjain7174 shreyanshjain7174 force-pushed the sandbox-path-refactor branch 2 times, most recently from c7fcebd to e1f8a6f Compare April 1, 2026 06:41
@shreyanshjain7174
Copy link
Copy Markdown
Contributor Author

@rawahars Addressed all 8 review comments. Also added scripts/validate-sandbox-paths.ps1 — a portable E2E validation script that exercises real CRI pod lifecycles via crictl and validates that /etc/hostname, /etc/hosts, and /etc/resolv.conf are correctly mounted from the sandbox root. It tests single-pod, sandbox+workload, and sequential multi-pod scenarios. All 13 checks pass locally.

Do you think this script is worth keeping in the repo for manual validation, or should it go in a separate PR / be dropped from this one?

Copy link
Copy Markdown
Contributor

@rawahars rawahars left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Major driving comment are that for the current change, try to align as close to original code structure as possible.

@shreyanshjain7174
Copy link
Copy Markdown
Contributor Author

Thanks for the detailed round 2 review. Pushed an update addressing all the comments:

  • Restored section comments in Container.Delete (remove user mounts, tmpfs mounts, hugepages)
  • Added utility methods back: getSandboxHostnamePath/HostsPath/ResolvPath in sandbox_container.go, getStandaloneHostnamePath/HostsPath/ResolvPath in standalone_container.go
  • Restored original setup function names: setupSandboxMountsPath, setupSandboxTmpfsMountsPath, etc.
  • Moved the root-based path helpers (SandboxMountsDirFromRoot, SandboxTmpfsMountsDirFromRoot, etc.) into spec.go alongside the existing ID-based methods
  • Moved GenerateWorkloadContainerNetworkMountsFromRoot into spec.go as well, removed the local inline version
  • Added whitespace and comments in registerSandboxRoot for readability
  • Kept the VirtualPod* methods in spec.go for now since GenerateWorkloadContainerNetworkMounts (used by securitypolicy) still depends on VirtualPodAwareSandboxRootDir. Happy to remove them in a follow-up once we wire that caller through the root-based path too.

All tests pass locally (unit + E2E via crictl).

@shreyanshjain7174 shreyanshjain7174 force-pushed the sandbox-path-refactor branch 2 times, most recently from 08c0b9e to 7c4f900 Compare April 1, 2026 16:49
@shreyanshjain7174
Copy link
Copy Markdown
Contributor Author

Note: this PR has a merge conflict with #2655 (bug fix for leaked LCOW resources) in uvm.go — specifically around RemoveContainer and the virtual pod cleanup paths. Once #2655 merges, I'll rebase on top of it.

Copy link
Copy Markdown
Contributor

@helsaawy helsaawy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we switch entirely to the *FromRoot functions and delete the [VirtualPodAware]*MountsDir/Source functions in internal/guest/spec?

func updateSandboxMounts(sandboxRoot string, spec *oci.Spec) error {
mountsDir := specGuest.SandboxMountsDirFromRoot(sandboxRoot)
tmpfsMountsDir := specGuest.SandboxTmpfsMountsDirFromRoot(sandboxRoot)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worthwhile to add Sandbox[Tmpfs]MountsSourceFromRoot or something similar.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added SandboxMountSourceFromRoot, SandboxTmpfsMountSourceFromRoot, and HugePagesMountSourceFromRoot to spec.go. The updateSandboxMounts and updateHugePageMounts functions in workload_container.go now use these instead of inline filepath.Join + TrimPrefix.

Replace heuristic sandbox path derivation (hard-coded /run/gcs/c prefix + ID)
with host-provided OCIBundlePath as the canonical sandbox root directory.

This change prepares the guest-side GCS for Shim v2 and multi-pod UVM support,
where the host may use a different path layout than the legacy /run/gcs/c/<id>.

Key changes:
- Add sandboxRoots mapping on Host to store resolved sandbox root per sandbox ID
- Sandbox containers: register OCIBundlePath as sandbox root
- Virtual pods: derive sandbox root from OCIBundlePath parent + /virtual-pods/<id>
- Workload containers: resolve sandbox root from Host mapping (fallback to legacy)
- Standalone containers: use OCIBundlePath directly as root
- Container.Delete: use stored sandboxRoot for cleanup paths
- Remove duplicate setup functions (setupVirtualPod* merged into unified setup*)

The refactor produces identical paths when the old shim sends OCIBundlePath in
the legacy format, ensuring zero behavior change for existing deployments.

Security: virtualPodID is validated against path traversal before use.
Signed-off-by: Shreyansh Sancheti <shsancheti@microsoft.com>
}

// remove user mounts in sandbox container - use virtual pod aware paths
if err := storage.UnmountAllInPath(ctx, specGuest.VirtualPodAwareSandboxMountsDir(c.id, virtualSandboxID), true); err != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we planning on removing VirtualPodAwareSandboxMountsDir and other utility methods in next PR?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the follow-up PR (guest-pod-unification branch) removes VirtualPodAwareSandboxMountsDir and the other VirtualPod* methods as part of the unified pod model.

// Set cgroup path
virtualSandboxID := spec.Annotations[annotations.VirtualPodID]
if virtualSandboxID != "" {
// Standalone container in virtual pod goes under /containers/virtual-pods/{virtualSandboxID}/{containerID}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Consider adding this comment in next PR when you do the refactoring.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will add in the follow-up.

// sandboxRoots maps sandboxID to the resolved sandbox root directory.
// Populated via RegisterSandboxRoot during sandbox creation using
// the host-provided OCIBundlePath as source of truth.
sandboxRootsMutex sync.RWMutex
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Why not just use the containersMutex? If sandboxRoots is always used under containersMutex then you can skip sandboxRootsMutex.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point — sandboxRoots is only accessed within CreateContainer and RemoveContainer which both hold containersMutex. I'll consolidate to use containersMutex only in the follow-up to keep this PR minimal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants