<commit_before>// +build linux

package hcsv2

import (
	"context"
	"os"
	"path/filepath"
	"strings"

	"github.com/Microsoft/hcsshim/internal/log"
	"github.com/Microsoft/hcsshim/internal/oc"
	"github.com/Microsoft/hcsshim/pkg/annotations"
	"github.com/opencontainers/runc/libcontainer/devices"
	oci "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
	"go.opencensus.io/trace"
	"golang.org/x/sys/unix"
)

func getWorkloadRootDir(id string) string {
	return filepath.Join("/run/gcs/c", id)
}

func updateSandboxMounts(sbid string, spec *oci.Spec) error {
	sandboxMountPrefix := "sandbox://"
	for i, m := range spec.Mounts {
		if strings.HasPrefix(m.Source, sandboxMountPrefix) {
			mountsDir := getSandboxMountsDir(sbid)
			subPath := strings.TrimPrefix(m.Source, sandboxMountPrefix)
			sandboxSource := filepath.Join(mountsDir, subPath)

			// filepath.Join cleans the resulting path before returning so it would resolve the relative path if one was given.
			// Hence, we need to ensure that the resolved path is still under the correct directory
			if !strings.HasPrefix(sandboxSource, mountsDir) {
				return errors.Errorf("mount path %v for mount %v is not within sandbox's mounts dir", sandboxSource, m.Source)
			}

			spec.Mounts[i].Source = sandboxSource

			_, err := os.Stat(sandboxSource)
			if os.IsNotExist(err) {
				if err := os.MkdirAll(sandboxSource, 0755); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func updateHugePageMounts(sbid string, spec *oci.Spec) error {
	mountPrefix := "hugepages://"
	for i, m := range spec.Mounts {
		if strings.HasPrefix(m.Source, mountPrefix) {
			mountsDir := getSandboxHugePageMountsDir(sbid)
			subPath := strings.TrimPrefix(m.Source, mountPrefix)
			pageSize := strings.Split(subPath, string(os.PathSeparator))[0]
			hugePageMountSource := filepath.Join(mountsDir, subPath)

			// filepath.Join cleans the resulting path before returning so it would resolve the relative path if one was given.
			// Hence, we need to ensure that the resolved path is still under the correct directory
			if !strings.HasPrefix(hugePageMountSource, mountsDir) {
				return errors.Errorf("mount path %v for mount %v is not within hugepages's mounts dir", hugePageMountSource, m.Source)
			}

			spec.Mounts[i].Source = hugePageMountSource

			_, err := os.Stat(hugePageMountSource)
			if os.IsNotExist(err) {
				if err := os.MkdirAll(hugePageMountSource, 0755); err != nil {
					return err
				}

				if err := unix.Mount("none", hugePageMountSource, "hugetlbfs", 0, "pagesize="+pageSize); err != nil {
					return errors.Errorf("mount operation failed for %v failed with error %v", hugePageMountSource, err)
				}
			}
		}
	}
	return nil
}

func specHasGPUDevice(spec *oci.Spec) bool {
	for _, d := range spec.Windows.Devices {
		if d.IDType == "gpu" {
			return true
		}
	}
	return false
}

func setupWorkloadContainerSpec(ctx context.Context, sbid, id string, spec *oci.Spec) (err error) {
	ctx, span := trace.StartSpan(ctx, "hcsv2::setupWorkloadContainerSpec")
	defer span.End()<commit_msg>Fix permissions issues with sandbox mounts<commit_after>// +build linux

package hcsv2

import (
	"context"
	"os"
	"path/filepath"
	"strings"

	"github.com/Microsoft/hcsshim/internal/log"
	"github.com/Microsoft/hcsshim/internal/oc"
	"github.com/Microsoft/hcsshim/pkg/annotations"
	"github.com/opencontainers/runc/libcontainer/devices"
	oci "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/pkg/errors"
	"go.opencensus.io/trace"
	"golang.org/x/sys/unix"
)

func getWorkloadRootDir(id string) string {
	return filepath.Join("/run/gcs/c", id)
}

func updateSandboxMounts(sbid string, spec *oci.Spec) error {
	sandboxMountPrefix := "sandbox://"
	for i, m := range spec.Mounts {
		if strings.HasPrefix(m.Source, sandboxMountPrefix) {
			mountsDir := getSandboxMountsDir(sbid)
			subPath := strings.TrimPrefix(m.Source, sandboxMountPrefix)
			sandboxSource := filepath.Join(mountsDir, subPath)

			// filepath.Join cleans the resulting path before returning so it would resolve the relative path if one was given.
			// Hence, we need to ensure that the resolved path is still under the correct directory
			if !strings.HasPrefix(sandboxSource, mountsDir) {
				return errors.Errorf("mount path %v for mount %v is not within sandbox's mounts dir", sandboxSource, m.Source)
			}

			spec.Mounts[i].Source = sandboxSource

			_, err := os.Stat(sandboxSource)
			if os.IsNotExist(err) {
				// os.MkdirAll combines the given permissions with the running process's
				// umask. By default this causes 0777 to become 0755.
				// Temporarily set the umask of this process to 0 so that we can actually
				// make all dirs with os.ModePerm permissions.
				savedUmask := unix.Umask(0)
				defer unix.Umask(savedUmask)
				if err := os.MkdirAll(sandboxSource, os.ModePerm); err != nil {
					return err
				}
			}
		}
	}
	return nil
}

func updateHugePageMounts(sbid string, spec *oci.Spec) error {
	mountPrefix := "hugepages://"
	for i, m := range spec.Mounts {
		if strings.HasPrefix(m.Source, mountPrefix) {
			mountsDir := getSandboxHugePageMountsDir(sbid)
			subPath := strings.TrimPrefix(m.Source, mountPrefix)
			pageSize := strings.Split(subPath, string(os.PathSeparator))[0]
			hugePageMountSource := filepath.Join(mountsDir, subPath)

			// filepath.Join cleans the resulting path before returning so it would resolve the relative path if one was given.
			// Hence, we need to ensure that the resolved path is still under the correct directory
			if !strings.HasPrefix(hugePageMountSource, mountsDir) {
				return errors.Errorf("mount path %v for mount %v is not within hugepages's mounts dir", hugePageMountSource, m.Source)
			}

			spec.Mounts[i].Source = hugePageMountSource

			_, err := os.Stat(hugePageMountSource)
			if os.IsNotExist(err) {
				// os.MkdirAll combines the given permissions with the running process's
				// umask. By default this causes 0777 to become 0755.
				// Temporarily set the umask of this process to 0 so that we can actually
				// make all dirs with os.ModePerm permissions.
				savedUmask := unix.Umask(0)
				defer unix.Umask(savedUmask)
				if err := os.MkdirAll(hugePageMountSource, os.ModePerm); err != nil {
					return err
				}

				if err := unix.Mount("none", hugePageMountSource, "hugetlbfs", 0, "pagesize="+pageSize); err != nil {
					return errors.Errorf("mount operation failed for %v failed with error %v", hugePageMountSource, err)
				}
			}
		}
	}
	return nil
}

func specHasGPUDevice(spec *oci.Spec) bool {
	for _, d := range spec.Windows.Devices {
		if d.IDType == "gpu" {
			return true
		}
	}
	return false
}

func setupWorkloadContainerSpec(ctx context.Context, sbid, id string, spec *oci.Spec) (err error) {
	ctx, span := trace.StartSpan(ctx, "hcsv2::setupWorkloadContainerSpec")
	defer span.End()
{'fraction_non_alphanumeric': 0.11223147742218326, 'fraction_numerical': 0.00526085050416484, 'mean_word_length': 3.937950937950938, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2007065', 'n_tokens_mistral': 2556, 'n_tokens_neox': 2254, 'n_words': 614}