...

Source file src/github.com/opencontainers/runc/libcontainer/specconv/example.go

Documentation: github.com/opencontainers/runc/libcontainer/specconv

     1  package specconv
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"strings"
     7  
     8  	"github.com/opencontainers/runc/libcontainer/cgroups"
     9  	"github.com/opencontainers/runtime-spec/specs-go"
    10  )
    11  
    12  // Example returns an example spec file, with many options set so a user can
    13  // see what a standard spec file looks like.
    14  func Example() *specs.Spec {
    15  	spec := &specs.Spec{
    16  		Version: specs.Version,
    17  		Root: &specs.Root{
    18  			Path:     "rootfs",
    19  			Readonly: true,
    20  		},
    21  		Process: &specs.Process{
    22  			Terminal: true,
    23  			User:     specs.User{},
    24  			Args: []string{
    25  				"sh",
    26  			},
    27  			Env: []string{
    28  				"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    29  				"TERM=xterm",
    30  			},
    31  			Cwd:             "/",
    32  			NoNewPrivileges: true,
    33  			Capabilities: &specs.LinuxCapabilities{
    34  				Bounding: []string{
    35  					"CAP_AUDIT_WRITE",
    36  					"CAP_KILL",
    37  					"CAP_NET_BIND_SERVICE",
    38  				},
    39  				Permitted: []string{
    40  					"CAP_AUDIT_WRITE",
    41  					"CAP_KILL",
    42  					"CAP_NET_BIND_SERVICE",
    43  				},
    44  				Ambient: []string{
    45  					"CAP_AUDIT_WRITE",
    46  					"CAP_KILL",
    47  					"CAP_NET_BIND_SERVICE",
    48  				},
    49  				Effective: []string{
    50  					"CAP_AUDIT_WRITE",
    51  					"CAP_KILL",
    52  					"CAP_NET_BIND_SERVICE",
    53  				},
    54  			},
    55  			Rlimits: []specs.POSIXRlimit{
    56  				{
    57  					Type: "RLIMIT_NOFILE",
    58  					Hard: uint64(1024),
    59  					Soft: uint64(1024),
    60  				},
    61  			},
    62  		},
    63  		Hostname: "runc",
    64  		Mounts: []specs.Mount{
    65  			{
    66  				Destination: "/proc",
    67  				Type:        "proc",
    68  				Source:      "proc",
    69  				Options:     nil,
    70  			},
    71  			{
    72  				Destination: "/dev",
    73  				Type:        "tmpfs",
    74  				Source:      "tmpfs",
    75  				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
    76  			},
    77  			{
    78  				Destination: "/dev/pts",
    79  				Type:        "devpts",
    80  				Source:      "devpts",
    81  				Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
    82  			},
    83  			{
    84  				Destination: "/dev/shm",
    85  				Type:        "tmpfs",
    86  				Source:      "shm",
    87  				Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
    88  			},
    89  			{
    90  				Destination: "/dev/mqueue",
    91  				Type:        "mqueue",
    92  				Source:      "mqueue",
    93  				Options:     []string{"nosuid", "noexec", "nodev"},
    94  			},
    95  			{
    96  				Destination: "/sys",
    97  				Type:        "sysfs",
    98  				Source:      "sysfs",
    99  				Options:     []string{"nosuid", "noexec", "nodev", "ro"},
   100  			},
   101  			{
   102  				Destination: "/sys/fs/cgroup",
   103  				Type:        "cgroup",
   104  				Source:      "cgroup",
   105  				Options:     []string{"nosuid", "noexec", "nodev", "relatime", "ro"},
   106  			},
   107  		},
   108  		Linux: &specs.Linux{
   109  			MaskedPaths: []string{
   110  				"/proc/acpi",
   111  				"/proc/asound",
   112  				"/proc/kcore",
   113  				"/proc/keys",
   114  				"/proc/latency_stats",
   115  				"/proc/timer_list",
   116  				"/proc/timer_stats",
   117  				"/proc/sched_debug",
   118  				"/sys/firmware",
   119  				"/proc/scsi",
   120  			},
   121  			ReadonlyPaths: []string{
   122  				"/proc/bus",
   123  				"/proc/fs",
   124  				"/proc/irq",
   125  				"/proc/sys",
   126  				"/proc/sysrq-trigger",
   127  			},
   128  			Resources: &specs.LinuxResources{
   129  				Devices: []specs.LinuxDeviceCgroup{
   130  					{
   131  						Allow:  false,
   132  						Access: "rwm",
   133  					},
   134  				},
   135  			},
   136  			Namespaces: []specs.LinuxNamespace{
   137  				{
   138  					Type: specs.PIDNamespace,
   139  				},
   140  				{
   141  					Type: specs.NetworkNamespace,
   142  				},
   143  				{
   144  					Type: specs.IPCNamespace,
   145  				},
   146  				{
   147  					Type: specs.UTSNamespace,
   148  				},
   149  				{
   150  					Type: specs.MountNamespace,
   151  				},
   152  			},
   153  		},
   154  	}
   155  	if cgroups.IsCgroup2UnifiedMode() {
   156  		spec.Linux.Namespaces = append(spec.Linux.Namespaces, specs.LinuxNamespace{
   157  			Type: specs.CgroupNamespace,
   158  		})
   159  	}
   160  	return spec
   161  }
   162  
   163  // ToRootless converts the given spec file into one that should work with
   164  // rootless containers (euid != 0), by removing incompatible options and adding others that
   165  // are needed.
   166  func ToRootless(spec *specs.Spec) {
   167  	var namespaces []specs.LinuxNamespace
   168  
   169  	// Remove networkns from the spec.
   170  	for _, ns := range spec.Linux.Namespaces {
   171  		switch ns.Type {
   172  		case specs.NetworkNamespace, specs.UserNamespace:
   173  			// Do nothing.
   174  		default:
   175  			namespaces = append(namespaces, ns)
   176  		}
   177  	}
   178  	// Add userns to the spec.
   179  	namespaces = append(namespaces, specs.LinuxNamespace{
   180  		Type: specs.UserNamespace,
   181  	})
   182  	spec.Linux.Namespaces = namespaces
   183  
   184  	// Add mappings for the current user.
   185  	spec.Linux.UIDMappings = []specs.LinuxIDMapping{{
   186  		HostID:      uint32(os.Geteuid()),
   187  		ContainerID: 0,
   188  		Size:        1,
   189  	}}
   190  	spec.Linux.GIDMappings = []specs.LinuxIDMapping{{
   191  		HostID:      uint32(os.Getegid()),
   192  		ContainerID: 0,
   193  		Size:        1,
   194  	}}
   195  
   196  	// Fix up mounts.
   197  	var mounts []specs.Mount
   198  	for _, mount := range spec.Mounts {
   199  		// Replace the /sys mount with an rbind.
   200  		if filepath.Clean(mount.Destination) == "/sys" {
   201  			mounts = append(mounts, specs.Mount{
   202  				Source:      "/sys",
   203  				Destination: "/sys",
   204  				Type:        "none",
   205  				Options:     []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
   206  			})
   207  			continue
   208  		}
   209  
   210  		// Remove all gid= and uid= mappings.
   211  		var options []string
   212  		for _, option := range mount.Options {
   213  			if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") {
   214  				options = append(options, option)
   215  			}
   216  		}
   217  
   218  		mount.Options = options
   219  		mounts = append(mounts, mount)
   220  	}
   221  	spec.Mounts = mounts
   222  
   223  	// Remove cgroup settings.
   224  	spec.Linux.Resources = nil
   225  }
   226  

View as plain text