204 lines
5.4 KiB
Diff
204 lines
5.4 KiB
Diff
|
|
From bdc84a618b475cc21a39dfa2fe57eae68b6110b6 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Aleksa Sarai <asarai@suse.de>
|
||
|
|
Date: Mon, 9 May 2016 21:26:11 +1000
|
||
|
|
Subject: [PATCH 09/94] rootless: add autogenerated rootless config
|
||
|
|
from `runc spec`
|
||
|
|
|
||
|
|
Since this is a runC-specific feature, this belongs here over in
|
||
|
|
opencontainers/ocitools (which is for generic OCI runtimes).
|
||
|
|
|
||
|
|
In addition, we don't create a new network namespace. This is because
|
||
|
|
currently if you want to set up a veth bridge you need CAP_NET_ADMIN in
|
||
|
|
both network namespaces' pinned user namespace to create the necessary
|
||
|
|
interfaces in each network namespace.
|
||
|
|
|
||
|
|
Change-Id: I682b9c82f75c04b58d523ddb084b6adbb543e3d1
|
||
|
|
Signed-off-by: Aleksa Sarai <asarai@suse.de>
|
||
|
|
---
|
||
|
|
libcontainer/specconv/example.go | 73 ++++++++++++++++++++++++++++++--
|
||
|
|
libcontainer/specconv/spec_linux_test.go | 30 +++----------
|
||
|
|
spec.go | 11 ++++-
|
||
|
|
3 files changed, 85 insertions(+), 29 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/libcontainer/specconv/example.go b/libcontainer/specconv/example.go
|
||
|
|
index 44fad97..9a4460c 100644
|
||
|
|
--- a/libcontainer/specconv/example.go
|
||
|
|
+++ b/libcontainer/specconv/example.go
|
||
|
|
@@ -1,16 +1,18 @@
|
||
|
|
package specconv
|
||
|
|
|
||
|
|
import (
|
||
|
|
+ "os"
|
||
|
|
"runtime"
|
||
|
|
+ "strings"
|
||
|
|
|
||
|
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||
|
|
)
|
||
|
|
|
||
|
|
func sPtr(s string) *string { return &s }
|
||
|
|
|
||
|
|
-// ExampleSpec returns an example spec file, with many options set so a user
|
||
|
|
-// can see what a standard spec file looks like.
|
||
|
|
-func ExampleSpec() *specs.Spec {
|
||
|
|
+// Example returns an example spec file, with many options set so a user can
|
||
|
|
+// see what a standard spec file looks like.
|
||
|
|
+func Example() *specs.Spec {
|
||
|
|
return &specs.Spec{
|
||
|
|
Version: specs.Version,
|
||
|
|
Platform: specs.Platform{
|
||
|
|
@@ -158,3 +160,68 @@ func ExampleSpec() *specs.Spec {
|
||
|
|
},
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+// ExampleRootless returns an example spec file that works with rootless
|
||
|
|
+// containers. It's essentially a modified version of the specfile from
|
||
|
|
+// Example().
|
||
|
|
+func ToRootless(spec *specs.Spec) {
|
||
|
|
+ var namespaces []specs.LinuxNamespace
|
||
|
|
+
|
||
|
|
+ // Remove networkns from the spec.
|
||
|
|
+ for _, ns := range spec.Linux.Namespaces {
|
||
|
|
+ switch ns.Type {
|
||
|
|
+ case specs.NetworkNamespace, specs.UserNamespace:
|
||
|
|
+ // Do nothing.
|
||
|
|
+ default:
|
||
|
|
+ namespaces = append(namespaces, ns)
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ // Add userns to the spec.
|
||
|
|
+ namespaces = append(namespaces, specs.LinuxNamespace{
|
||
|
|
+ Type: specs.UserNamespace,
|
||
|
|
+ })
|
||
|
|
+ spec.Linux.Namespaces = namespaces
|
||
|
|
+
|
||
|
|
+ // Add mappings for the current user.
|
||
|
|
+ spec.Linux.UIDMappings = []specs.LinuxIDMapping{{
|
||
|
|
+ HostID: uint32(os.Geteuid()),
|
||
|
|
+ ContainerID: 0,
|
||
|
|
+ Size: 1,
|
||
|
|
+ }}
|
||
|
|
+ spec.Linux.GIDMappings = []specs.LinuxIDMapping{{
|
||
|
|
+ HostID: uint32(os.Getegid()),
|
||
|
|
+ ContainerID: 0,
|
||
|
|
+ Size: 1,
|
||
|
|
+ }}
|
||
|
|
+
|
||
|
|
+ // Fix up mounts.
|
||
|
|
+ var mounts []specs.Mount
|
||
|
|
+ for _, mount := range spec.Mounts {
|
||
|
|
+ // Ignore all mounts that are under /sys.
|
||
|
|
+ if strings.HasPrefix(mount.Destination, "/sys") {
|
||
|
|
+ continue
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ // Remove all gid= and uid= mappings.
|
||
|
|
+ var options []string
|
||
|
|
+ for _, option := range mount.Options {
|
||
|
|
+ if !strings.HasPrefix(option, "gid=") && !strings.HasPrefix(option, "uid=") {
|
||
|
|
+ options = append(options, option)
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ mount.Options = options
|
||
|
|
+ mounts = append(mounts, mount)
|
||
|
|
+ }
|
||
|
|
+ // Add the sysfs mount as an rbind.
|
||
|
|
+ mounts = append(mounts, specs.Mount{
|
||
|
|
+ Source: "/sys",
|
||
|
|
+ Destination: "/sys",
|
||
|
|
+ Type: "none",
|
||
|
|
+ Options: []string{"rbind", "nosuid", "noexec", "nodev", "ro"},
|
||
|
|
+ })
|
||
|
|
+ spec.Mounts = mounts
|
||
|
|
+
|
||
|
|
+ // Remove cgroup settings.
|
||
|
|
+ spec.Linux.Resources = nil
|
||
|
|
+}
|
||
|
|
diff --git a/libcontainer/specconv/spec_linux_test.go b/libcontainer/specconv/spec_linux_test.go
|
||
|
|
index 741fae6..f7292f3 100644
|
||
|
|
--- a/libcontainer/specconv/spec_linux_test.go
|
||
|
|
+++ b/libcontainer/specconv/spec_linux_test.go
|
||
|
|
@@ -3,7 +3,6 @@
|
||
|
|
package specconv
|
||
|
|
|
||
|
|
import (
|
||
|
|
- "os"
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"github.com/opencontainers/runc/libcontainer/configs/validate"
|
||
|
|
@@ -53,8 +52,9 @@ func TestLinuxCgroupsPathNotSpecified(t *testing.T) {
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSpecconvExampleValidate(t *testing.T) {
|
||
|
|
- spec := ExampleSpec()
|
||
|
|
+ spec := Example()
|
||
|
|
spec.Root.Path = "/"
|
||
|
|
+
|
||
|
|
opts := &CreateOpts{
|
||
|
|
CgroupName: "ContainerID",
|
||
|
|
UseSystemdCgroup: false,
|
||
|
|
@@ -97,29 +97,9 @@ func TestDupNamespaces(t *testing.T) {
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestRootlessSpecconvValidate(t *testing.T) {
|
||
|
|
- spec := &specs.Spec{
|
||
|
|
- Linux: specs.Linux{
|
||
|
|
- Namespaces: []specs.Namespace{
|
||
|
|
- {
|
||
|
|
- Type: specs.UserNamespace,
|
||
|
|
- },
|
||
|
|
- },
|
||
|
|
- UIDMappings: []specs.IDMapping{
|
||
|
|
- {
|
||
|
|
- HostID: uint32(os.Geteuid()),
|
||
|
|
- ContainerID: 0,
|
||
|
|
- Size: 1,
|
||
|
|
- },
|
||
|
|
- },
|
||
|
|
- GIDMappings: []specs.IDMapping{
|
||
|
|
- {
|
||
|
|
- HostID: uint32(os.Getegid()),
|
||
|
|
- ContainerID: 0,
|
||
|
|
- Size: 1,
|
||
|
|
- },
|
||
|
|
- },
|
||
|
|
- },
|
||
|
|
- }
|
||
|
|
+ spec := Example()
|
||
|
|
+ spec.Root.Path = "/"
|
||
|
|
+ ToRootless(spec)
|
||
|
|
|
||
|
|
opts := &CreateOpts{
|
||
|
|
CgroupName: "ContainerID",
|
||
|
|
diff --git a/spec.go b/spec.go
|
||
|
|
index d7df312..9024ad4 100644
|
||
|
|
--- a/spec.go
|
||
|
|
+++ b/spec.go
|
||
|
|
@@ -64,12 +64,21 @@ container on your host.`,
|
||
|
|
Value: "",
|
||
|
|
Usage: "path to the root of the bundle directory",
|
||
|
|
},
|
||
|
|
+ cli.BoolFlag{
|
||
|
|
+ Name: "rootless",
|
||
|
|
+ Usage: "generate a configuration for a rootless container",
|
||
|
|
+ },
|
||
|
|
},
|
||
|
|
Action: func(context *cli.Context) error {
|
||
|
|
if err := checkArgs(context, 0, exactArgs); err != nil {
|
||
|
|
return err
|
||
|
|
}
|
||
|
|
- spec := specconv.ExampleSpec()
|
||
|
|
+ spec := specconv.Example()
|
||
|
|
+
|
||
|
|
+ rootless := context.Bool("rootless")
|
||
|
|
+ if rootless {
|
||
|
|
+ specconv.ToRootless(spec)
|
||
|
|
+ }
|
||
|
|
|
||
|
|
checkNoFile := func(name string) error {
|
||
|
|
_, err := os.Stat(name)
|
||
|
|
--
|
||
|
|
2.7.4.3
|
||
|
|
|