Skip to content

Commit 7c4f900

Browse files
author
Shreyansh Sancheti
committed
guest: use OCIBundlePath as sandbox root source of truth
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>
1 parent 5a0252a commit 7c4f900

File tree

7 files changed

+580
-191
lines changed

7 files changed

+580
-191
lines changed

internal/guest/runtime/hcsv2/container.go

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import (
3030
"github.com/Microsoft/hcsshim/internal/oc"
3131
"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
3232
"github.com/Microsoft/hcsshim/internal/protocol/guestresource"
33-
"github.com/Microsoft/hcsshim/pkg/annotations"
3433
)
3534

3635
// containerStatus has been introduced to enable parallel container creation
@@ -77,6 +76,10 @@ type Container struct {
7776
// of this container is located. Usually, this is either `/run/gcs/c/<containerID>` or
7877
// `/run/gcs/c/<UVMID>/container_<containerID>` if scratch is shared with UVM scratch.
7978
scratchDirPath string
79+
80+
// sandboxRoot is the root directory of the pod within the guest.
81+
// Used during cleanup to unmount sandbox-specific paths.
82+
sandboxRoot string
8083
}
8184

8285
func (c *Container) Start(ctx context.Context, conSettings stdio.ConnectionSettings) (_ int, err error) {
@@ -229,25 +232,19 @@ func (c *Container) Kill(ctx context.Context, signal syscall.Signal) error {
229232
func (c *Container) Delete(ctx context.Context) error {
230233
entity := log.G(ctx).WithField(logfields.ContainerID, c.id)
231234
entity.Info("opengcs::Container::Delete")
232-
if c.isSandbox {
233-
// Check if this is a virtual pod
234-
virtualSandboxID := ""
235-
if c.spec != nil && c.spec.Annotations != nil {
236-
virtualSandboxID = c.spec.Annotations[annotations.VirtualPodID]
237-
}
238-
239-
// remove user mounts in sandbox container - use virtual pod aware paths
240-
if err := storage.UnmountAllInPath(ctx, specGuest.VirtualPodAwareSandboxMountsDir(c.id, virtualSandboxID), true); err != nil {
235+
if c.isSandbox && c.sandboxRoot != "" {
236+
// remove user mounts in sandbox container
237+
if err := storage.UnmountAllInPath(ctx, specGuest.SandboxMountsDirFromRoot(c.sandboxRoot), true); err != nil {
241238
entity.WithError(err).Error("failed to unmount sandbox mounts")
242239
}
243240

244-
// remove user mounts in tmpfs sandbox container - use virtual pod aware paths
245-
if err := storage.UnmountAllInPath(ctx, specGuest.VirtualPodAwareSandboxTmpfsMountsDir(c.id, virtualSandboxID), true); err != nil {
241+
// remove tmpfs mounts in sandbox container
242+
if err := storage.UnmountAllInPath(ctx, specGuest.SandboxTmpfsMountsDirFromRoot(c.sandboxRoot), true); err != nil {
246243
entity.WithError(err).Error("failed to unmount tmpfs sandbox mounts")
247244
}
248245

249-
// remove hugepages mounts in sandbox container - use virtual pod aware paths
250-
if err := storage.UnmountAllInPath(ctx, specGuest.VirtualPodAwareHugePagesMountsDir(c.id, virtualSandboxID), true); err != nil {
246+
// remove hugepages mounts in sandbox container
247+
if err := storage.UnmountAllInPath(ctx, specGuest.SandboxHugePagesMountsDirFromRoot(c.sandboxRoot), true); err != nil {
251248
entity.WithError(err).Error("failed to unmount hugepages mounts")
252249
}
253250
}

internal/guest/runtime/hcsv2/sandbox_container.go

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,30 @@ import (
2020
"github.com/Microsoft/hcsshim/pkg/annotations"
2121
)
2222

23-
func getSandboxHostnamePath(id, virtualSandboxID string) string {
24-
return filepath.Join(specGuest.VirtualPodAwareSandboxRootDir(id, virtualSandboxID), "hostname")
23+
func getSandboxHostnamePath(sandboxRoot string) string {
24+
return filepath.Join(sandboxRoot, "hostname")
2525
}
2626

27-
func getSandboxHostsPath(id, virtualSandboxID string) string {
28-
return filepath.Join(specGuest.VirtualPodAwareSandboxRootDir(id, virtualSandboxID), "hosts")
27+
func getSandboxHostsPath(sandboxRoot string) string {
28+
return filepath.Join(sandboxRoot, "hosts")
2929
}
3030

31-
func getSandboxResolvPath(id, virtualSandboxID string) string {
32-
return filepath.Join(specGuest.VirtualPodAwareSandboxRootDir(id, virtualSandboxID), "resolv.conf")
31+
func getSandboxResolvPath(sandboxRoot string) string {
32+
return filepath.Join(sandboxRoot, "resolv.conf")
3333
}
3434

35-
func setupSandboxContainerSpec(ctx context.Context, id string, spec *oci.Spec) (err error) {
35+
func setupSandboxContainerSpec(ctx context.Context, id, sandboxRoot string, spec *oci.Spec) (err error) {
3636
ctx, span := oc.StartSpan(ctx, "hcsv2::setupSandboxContainerSpec")
3737
defer span.End()
3838
defer func() { oc.SetSpanStatus(span, err) }()
3939
span.AddAttributes(trace.StringAttribute("cid", id))
4040

41-
// Check if this is a virtual pod to use appropriate root directory
42-
virtualSandboxID := spec.Annotations[annotations.VirtualPodID]
43-
44-
// Generate the sandbox root dir - virtual pod aware
45-
rootDir := specGuest.VirtualPodAwareSandboxRootDir(id, virtualSandboxID)
46-
if err := os.MkdirAll(rootDir, 0755); err != nil {
47-
return errors.Wrapf(err, "failed to create sandbox root directory %q", rootDir)
41+
if err := os.MkdirAll(sandboxRoot, 0755); err != nil {
42+
return errors.Wrapf(err, "failed to create sandbox root directory %q", sandboxRoot)
4843
}
4944
defer func() {
5045
if err != nil {
51-
_ = os.RemoveAll(rootDir)
46+
_ = os.RemoveAll(sandboxRoot)
5247
}
5348
}()
5449

@@ -62,19 +57,20 @@ func setupSandboxContainerSpec(ctx context.Context, id string, spec *oci.Spec) (
6257
}
6358
}
6459

65-
sandboxHostnamePath := getSandboxHostnamePath(id, virtualSandboxID)
60+
sandboxHostnamePath := getSandboxHostnamePath(sandboxRoot)
6661
if err := os.WriteFile(sandboxHostnamePath, []byte(hostname+"\n"), 0644); err != nil {
6762
return errors.Wrapf(err, "failed to write hostname to %q", sandboxHostnamePath)
6863
}
6964

7065
// Write the hosts
7166
sandboxHostsContent := network.GenerateEtcHostsContent(ctx, hostname)
72-
sandboxHostsPath := getSandboxHostsPath(id, virtualSandboxID)
67+
sandboxHostsPath := getSandboxHostsPath(sandboxRoot)
7368
if err := os.WriteFile(sandboxHostsPath, []byte(sandboxHostsContent), 0644); err != nil {
7469
return errors.Wrapf(err, "failed to write sandbox hosts to %q", sandboxHostsPath)
7570
}
7671

7772
// Check if this is a virtual pod sandbox container by comparing container ID with virtual pod ID
73+
virtualSandboxID := spec.Annotations[annotations.VirtualPodID]
7874
isVirtualPodSandbox := virtualSandboxID != "" && id == virtualSandboxID
7975
if strings.EqualFold(spec.Annotations[annotations.SkipPodNetworking], "true") || isVirtualPodSandbox {
8076
ns := GetOrAddNetworkNamespace(specGuest.GetNetworkNamespaceID(spec))
@@ -97,7 +93,7 @@ func setupSandboxContainerSpec(ctx context.Context, id string, spec *oci.Spec) (
9793
if err != nil {
9894
return errors.Wrap(err, "failed to generate sandbox resolv.conf content")
9995
}
100-
sandboxResolvPath := getSandboxResolvPath(id, virtualSandboxID)
96+
sandboxResolvPath := getSandboxResolvPath(sandboxRoot)
10197
if err := os.WriteFile(sandboxResolvPath, []byte(resolvContent), 0644); err != nil {
10298
return errors.Wrap(err, "failed to write sandbox resolv.conf")
10399
}
@@ -125,10 +121,8 @@ func setupSandboxContainerSpec(ctx context.Context, id string, spec *oci.Spec) (
125121

126122
// Set cgroup path - check if this is a virtual pod
127123
if virtualSandboxID != "" {
128-
// Virtual pod sandbox gets its own cgroup under /containers/virtual-pods using the virtual pod ID
129124
spec.Linux.CgroupsPath = "/containers/virtual-pods/" + virtualSandboxID
130125
} else {
131-
// Traditional sandbox goes under /containers
132126
spec.Linux.CgroupsPath = "/containers/" + id
133127
}
134128

0 commit comments

Comments
 (0)