runc/patch/0009-rootless-add-autogenerated-rootless-config-.patch

204 lines
5.4 KiB
Diff
Raw Normal View History

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