diff options
-rw-r--r-- | libpod/container.go | 4 | ||||
-rw-r--r-- | libpod/container_internal.go | 6 | ||||
-rw-r--r-- | libpod/networking_linux.go | 38 | ||||
-rw-r--r-- | libpod/networking_unsupported.go | 4 | ||||
-rw-r--r-- | libpod/oci.go | 10 | ||||
-rw-r--r-- | pkg/spec/createconfig.go | 8 |
6 files changed, 65 insertions, 5 deletions
diff --git a/libpod/container.go b/libpod/container.go index 456fc412d..77c94c7df 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -3,6 +3,7 @@ package libpod import ( "fmt" "net" + "os" "path/filepath" "time" @@ -106,6 +107,9 @@ type Container struct { valid bool lock storage.Locker runtime *Runtime + + rootlessSlirpSyncR *os.File + rootlessSlirpSyncW *os.File } // containerState contains the current state of the container diff --git a/libpod/container_internal.go b/libpod/container_internal.go index 8a96af0ab..2f258d007 100644 --- a/libpod/container_internal.go +++ b/libpod/container_internal.go @@ -524,12 +524,12 @@ func (c *Container) completeNetworkSetup() error { if !c.config.PostConfigureNetNS { return nil } - if rootless.IsRootless() { - return nil - } if err := c.syncContainer(); err != nil { return err } + if rootless.IsRootless() { + return c.runtime.setupRootlessNetNS(c) + } return c.runtime.setupNetNS(c) } diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index dbc68e04b..2186b4ac9 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -6,9 +6,11 @@ import ( "crypto/rand" "fmt" "os" + "os/exec" "path/filepath" "strconv" "strings" + "syscall" cnitypes "github.com/containernetworking/cni/pkg/types/current" "github.com/containernetworking/plugins/pkg/ns" @@ -93,6 +95,42 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) { return r.configureNetNS(ctr, ctrNS) } +// Configure the network namespace for a rootless container +func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { + defer ctr.rootlessSlirpSyncR.Close() + defer ctr.rootlessSlirpSyncW.Close() + + path, err := exec.LookPath("slirp4netns") + if err != nil { + logrus.Errorf("could not find slirp4netns, the network namespace won't be configured: %v", err) + return nil + } + + syncR, syncW, err := os.Pipe() + if err != nil { + return errors.Wrapf(err, "failed to open pipe") + } + defer syncR.Close() + defer syncW.Close() + + cmd := exec.Command(path, "-c", "-e", "3", "-r", "4", fmt.Sprintf("%d", ctr.state.PID), "tap0") + + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setpgid: true, + } + cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncR, syncW) + + if err := cmd.Start(); err != nil { + return errors.Wrapf(err, "failed to start process") + } + + b := make([]byte, 16) + if _, err := syncR.Read(b); err != nil { + return errors.Wrapf(err, "failed to read from sync pipe") + } + return nil +} + // Configure the network namespace using the container process func (r *Runtime) setupNetNS(ctr *Container) (err error) { nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID) diff --git a/libpod/networking_unsupported.go b/libpod/networking_unsupported.go index e4c668f88..070985c47 100644 --- a/libpod/networking_unsupported.go +++ b/libpod/networking_unsupported.go @@ -6,6 +6,10 @@ import ( "github.com/projectatomic/libpod/pkg/inspect" ) +func (r *Runtime) setupRootlessNetNS(ctr *Container) (err error) { + return ErrNotImplemented +} + func (r *Runtime) setupNetNS(ctr *Container) (err error) { return ErrNotImplemented } diff --git a/libpod/oci.go b/libpod/oci.go index 0483c0d53..5ae3406ac 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -22,6 +22,7 @@ import ( "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" "github.com/projectatomic/libpod/pkg/ctime" + "github.com/projectatomic/libpod/pkg/rootless" "github.com/sirupsen/logrus" "golang.org/x/sys/unix" kwait "k8s.io/apimachinery/pkg/util/wait" @@ -317,6 +318,15 @@ func (r *OCIRuntime) createOCIContainer(ctr *Container, cgroupParent string) (er // process cannot use them. cmd.ExtraFiles = append(cmd.ExtraFiles, ports...) + if rootless.IsRootless() { + ctr.rootlessSlirpSyncR, ctr.rootlessSlirpSyncW, err = os.Pipe() + if err != nil { + return errors.Wrapf(err, "failed to create rootless network sync pipe") + } + // Leak one end in conmon, the other one will be leaked into slirp4netns + cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessSlirpSyncW) + } + if notify, ok := os.LookupEnv("NOTIFY_SOCKET"); ok { cmd.Env = append(cmd.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", notify)) } diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 0bd6c6d1c..fb45f042b 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -381,8 +381,12 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib return nil, errors.Wrapf(err, "container %q not found", c.NetMode.ConnectedContainer()) } options = append(options, libpod.WithNetNSFrom(connectedCtr)) - } else if !rootless.IsRootless() && !c.NetMode.IsHost() && !c.NetMode.IsNone() { - postConfigureNetNS := (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() + } else if !c.NetMode.IsHost() && !c.NetMode.IsNone() { + isRootless := rootless.IsRootless() + postConfigureNetNS := isRootless || (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost() + if isRootless && len(portBindings) > 0 { + return nil, errors.New("port bindings are not yet supported by rootless containers") + } options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS, networks)) } |