200 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			200 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// +build !windows
 | 
						|
 | 
						|
package containerd
 | 
						|
 | 
						|
import (
 | 
						|
	"io/ioutil"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"syscall"
 | 
						|
 | 
						|
	"golang.org/x/sys/unix"
 | 
						|
 | 
						|
	"github.com/containerd/containerd/mount"
 | 
						|
	specs "github.com/opencontainers/runtime-spec/specs-go"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	rwm               = "rwm"
 | 
						|
	defaultRootfsPath = "rootfs"
 | 
						|
)
 | 
						|
 | 
						|
var (
 | 
						|
	defaultEnv = []string{
 | 
						|
		"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
 | 
						|
	}
 | 
						|
)
 | 
						|
 | 
						|
func defaultCaps() []string {
 | 
						|
	return []string{
 | 
						|
		"CAP_CHOWN",
 | 
						|
		"CAP_DAC_OVERRIDE",
 | 
						|
		"CAP_FSETID",
 | 
						|
		"CAP_FOWNER",
 | 
						|
		"CAP_MKNOD",
 | 
						|
		"CAP_NET_RAW",
 | 
						|
		"CAP_SETGID",
 | 
						|
		"CAP_SETUID",
 | 
						|
		"CAP_SETFCAP",
 | 
						|
		"CAP_SETPCAP",
 | 
						|
		"CAP_NET_BIND_SERVICE",
 | 
						|
		"CAP_SYS_CHROOT",
 | 
						|
		"CAP_KILL",
 | 
						|
		"CAP_AUDIT_WRITE",
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func defaultNamespaces() []specs.LinuxNamespace {
 | 
						|
	return []specs.LinuxNamespace{
 | 
						|
		{
 | 
						|
			Type: specs.PIDNamespace,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Type: specs.IPCNamespace,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Type: specs.UTSNamespace,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Type: specs.MountNamespace,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			Type: specs.NetworkNamespace,
 | 
						|
		},
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func createDefaultSpec() (*specs.Spec, error) {
 | 
						|
	s := &specs.Spec{
 | 
						|
		Version: specs.Version,
 | 
						|
		Root: &specs.Root{
 | 
						|
			Path: defaultRootfsPath,
 | 
						|
		},
 | 
						|
		Process: &specs.Process{
 | 
						|
			Env:             defaultEnv,
 | 
						|
			Cwd:             "/",
 | 
						|
			NoNewPrivileges: true,
 | 
						|
			User: specs.User{
 | 
						|
				UID: 0,
 | 
						|
				GID: 0,
 | 
						|
			},
 | 
						|
			Capabilities: &specs.LinuxCapabilities{
 | 
						|
				Bounding:    defaultCaps(),
 | 
						|
				Permitted:   defaultCaps(),
 | 
						|
				Inheritable: defaultCaps(),
 | 
						|
				Effective:   defaultCaps(),
 | 
						|
			},
 | 
						|
			Rlimits: []specs.POSIXRlimit{
 | 
						|
				{
 | 
						|
					Type: "RLIMIT_NOFILE",
 | 
						|
					Hard: uint64(1024),
 | 
						|
					Soft: uint64(1024),
 | 
						|
				},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		Mounts: []specs.Mount{
 | 
						|
			{
 | 
						|
				Destination: "/proc",
 | 
						|
				Type:        "proc",
 | 
						|
				Source:      "proc",
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/dev",
 | 
						|
				Type:        "tmpfs",
 | 
						|
				Source:      "tmpfs",
 | 
						|
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/dev/pts",
 | 
						|
				Type:        "devpts",
 | 
						|
				Source:      "devpts",
 | 
						|
				Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/dev/shm",
 | 
						|
				Type:        "tmpfs",
 | 
						|
				Source:      "shm",
 | 
						|
				Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/dev/mqueue",
 | 
						|
				Type:        "mqueue",
 | 
						|
				Source:      "mqueue",
 | 
						|
				Options:     []string{"nosuid", "noexec", "nodev"},
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/sys",
 | 
						|
				Type:        "sysfs",
 | 
						|
				Source:      "sysfs",
 | 
						|
				Options:     []string{"nosuid", "noexec", "nodev", "ro"},
 | 
						|
			},
 | 
						|
			{
 | 
						|
				Destination: "/run",
 | 
						|
				Type:        "tmpfs",
 | 
						|
				Source:      "tmpfs",
 | 
						|
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
 | 
						|
			},
 | 
						|
		},
 | 
						|
		Linux: &specs.Linux{
 | 
						|
			// TODO (AkihiroSuda): unmask /sys/firmware on Windows daemon for LCOW support?
 | 
						|
			// https://github.com/moby/moby/pull/33241/files#diff-a1f5051ce84e711a2ee688ab9ded5e74R215
 | 
						|
			MaskedPaths: []string{
 | 
						|
				"/proc/kcore",
 | 
						|
				"/proc/latency_stats",
 | 
						|
				"/proc/timer_list",
 | 
						|
				"/proc/timer_stats",
 | 
						|
				"/proc/sched_debug",
 | 
						|
				"/sys/firmware",
 | 
						|
			},
 | 
						|
			ReadonlyPaths: []string{
 | 
						|
				"/proc/asound",
 | 
						|
				"/proc/bus",
 | 
						|
				"/proc/fs",
 | 
						|
				"/proc/irq",
 | 
						|
				"/proc/sys",
 | 
						|
				"/proc/sysrq-trigger",
 | 
						|
			},
 | 
						|
			// TODO (@crosbymichael) make sure we don't have have two containers in the same cgroup
 | 
						|
			Resources: &specs.LinuxResources{
 | 
						|
				Devices: []specs.LinuxDeviceCgroup{
 | 
						|
					{
 | 
						|
						Allow:  false,
 | 
						|
						Access: rwm,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			},
 | 
						|
			Namespaces: defaultNamespaces(),
 | 
						|
		},
 | 
						|
	}
 | 
						|
	return s, nil
 | 
						|
}
 | 
						|
 | 
						|
func remapRootFS(mounts []mount.Mount, uid, gid uint32) error {
 | 
						|
	root, err := ioutil.TempDir("", "ctd-remap")
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	defer os.RemoveAll(root)
 | 
						|
	for _, m := range mounts {
 | 
						|
		if err := m.Mount(root); err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	defer unix.Unmount(root, 0)
 | 
						|
	return filepath.Walk(root, incrementFS(root, uid, gid))
 | 
						|
}
 | 
						|
 | 
						|
func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc {
 | 
						|
	return func(path string, info os.FileInfo, err error) error {
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		var (
 | 
						|
			stat = info.Sys().(*syscall.Stat_t)
 | 
						|
			u, g = int(stat.Uid + uidInc), int(stat.Gid + gidInc)
 | 
						|
		)
 | 
						|
		// be sure the lchown the path as to not de-reference the symlink to a host file
 | 
						|
		return os.Lchown(path, u, g)
 | 
						|
	}
 | 
						|
}
 |