summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2018-04-20 18:59:19 +0200
committerAtomic Bot <atomic-devel@projectatomic.io>2018-05-04 17:15:55 +0000
commit73078fabcfd2420c47e41843da71dd993f9a0a3e (patch)
tree1c98d8ae433c5f148c7af5184777d2348b5b2540
parentb51d7379987581da82902027fe91cdf298047bc0 (diff)
downloadpodman-73078fabcfd2420c47e41843da71dd993f9a0a3e.tar.gz
podman-73078fabcfd2420c47e41843da71dd993f9a0a3e.tar.bz2
podman-73078fabcfd2420c47e41843da71dd993f9a0a3e.zip
networking, userNS: configure the network namespace after create
so that the OCI runtime creates the network namespace from the correct userNS. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com> Closes: #690 Approved by: mheon
-rw-r--r--cmd/podman/spec.go31
-rw-r--r--libpod/container.go2
-rw-r--r--libpod/container_internal.go24
-rw-r--r--libpod/networking.go73
-rw-r--r--libpod/options.go3
5 files changed, 106 insertions, 27 deletions
diff --git a/cmd/podman/spec.go b/cmd/podman/spec.go
index 15dab6c4d..747d76359 100644
--- a/cmd/podman/spec.go
+++ b/cmd/podman/spec.go
@@ -167,6 +167,7 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
cgroupPerm := "ro"
g := generate.New()
g.HostSpecific = true
+ addCgroup := true
if config.Privileged {
cgroupPerm = "rw"
g.RemoveMount("/sys")
@@ -177,14 +178,27 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
Options: []string{"nosuid", "noexec", "nodev", "rw"},
}
g.AddMount(sysMnt)
+ } else if !config.UsernsMode.IsHost() && config.NetMode.IsHost() {
+ addCgroup = false
+ g.RemoveMount("/sys")
+ sysMnt := spec.Mount{
+ Destination: "/sys",
+ Type: "bind",
+ Source: "/sys",
+ Options: []string{"nosuid", "noexec", "nodev", "ro", "rbind"},
+ }
+ g.AddMount(sysMnt)
}
- cgroupMnt := spec.Mount{
- Destination: "/sys/fs/cgroup",
- Type: "cgroup",
- Source: "cgroup",
- Options: []string{"nosuid", "noexec", "nodev", "relatime", cgroupPerm},
+
+ if addCgroup {
+ cgroupMnt := spec.Mount{
+ Destination: "/sys/fs/cgroup",
+ Type: "cgroup",
+ Source: "cgroup",
+ Options: []string{"nosuid", "noexec", "nodev", "relatime", cgroupPerm},
+ }
+ g.AddMount(cgroupMnt)
}
- g.AddMount(cgroupMnt)
g.SetProcessCwd(config.WorkDir)
g.SetProcessArgs(config.Command)
g.SetProcessTerminal(config.Tty)
@@ -697,8 +711,9 @@ func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, er
}
options = append(options, libpod.WithNetNSFrom(connectedCtr))
} else if !c.NetMode.IsHost() && !c.NetMode.IsNone() {
- options = append(options, libpod.WithNetNS([]ocicni.PortMapping{}))
- options = append(options, libpod.WithNetNS(portBindings))
+ postConfigureNetNS := (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost()
+ options = append(options, libpod.WithNetNS([]ocicni.PortMapping{}, postConfigureNetNS))
+ options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS))
}
if c.PidMode.IsContainer() {
diff --git a/libpod/container.go b/libpod/container.go
index fb1f83c29..5fa27af58 100644
--- a/libpod/container.go
+++ b/libpod/container.go
@@ -285,6 +285,8 @@ type ContainerConfig struct {
// File containing the conmon PID
ConmonPidFile string `json:"conmonPidFile,omitempty"`
// TODO log options for log drivers
+
+ PostConfigureNetNS bool `json:"postConfigureNetNS"`
}
// ContainerStatus returns a string representation for users
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 73095316e..18b56e23c 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -416,6 +416,16 @@ func (c *Container) checkDependenciesRunningLocked(depCtrs map[string]*Container
return notRunning, nil
}
+func (c *Container) completeNetworkSetup() error {
+ if !c.config.PostConfigureNetNS {
+ return nil
+ }
+ if err := c.syncContainer(); err != nil {
+ return err
+ }
+ return c.runtime.setupNetNS(c)
+}
+
// Initialize a container, creating it in the runtime
func (c *Container) init(ctx context.Context) error {
if err := c.makeBindMounts(); err != nil {
@@ -442,7 +452,11 @@ func (c *Container) init(ctx context.Context) error {
c.state.State = ContainerStateCreated
- return c.save()
+ if err := c.save(); err != nil {
+ return err
+ }
+
+ return c.completeNetworkSetup()
}
// Reinitialize a container
@@ -626,7 +640,7 @@ func (c *Container) prepare() (err error) {
}
// Set up network namespace if not already set up
- if c.config.CreateNetNS && c.state.NetNS == nil {
+ if c.config.CreateNetNS && c.state.NetNS == nil && !c.config.PostConfigureNetNS {
if err := c.runtime.createNetNS(c); err != nil {
// Tear down storage before exiting to make sure we
// don't leak mounts
@@ -913,7 +927,11 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
// If network namespace was requested, add it now
if c.config.CreateNetNS {
- g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
+ if c.config.PostConfigureNetNS {
+ g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, "")
+ } else {
+ g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
+ }
}
// Remove the default /dev/shm mount to ensure we overwrite it
diff --git a/libpod/networking.go b/libpod/networking.go
index cceeb18d6..54a1c78de 100644
--- a/libpod/networking.go
+++ b/libpod/networking.go
@@ -1,7 +1,12 @@
package libpod
import (
+ "crypto/rand"
+ "fmt"
"net"
+ "os"
+ "path/filepath"
+ "strings"
cnitypes "github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/plugins/pkg/ns"
@@ -9,7 +14,7 @@ import (
"github.com/pkg/errors"
"github.com/projectatomic/libpod/utils"
"github.com/sirupsen/logrus"
- "strings"
+ "golang.org/x/sys/unix"
)
// Get an OCICNI network config
@@ -24,20 +29,7 @@ func getPodNetwork(id, name, nsPath string, ports []ocicni.PortMapping) ocicni.P
}
// Create and configure a new network namespace for a container
-func (r *Runtime) createNetNS(ctr *Container) (err error) {
- ctrNS, err := ns.NewNS()
- if err != nil {
- return errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
- }
- defer func() {
- if err != nil {
- if err2 := ctrNS.Close(); err2 != nil {
- logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err2)
- }
- }
- }()
-
- logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())
+func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (err error) {
podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.PortMappings)
result, err := r.netPlugin.SetUpPod(podNetwork)
@@ -74,6 +66,57 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) {
return nil
}
+// Create and configure a new network namespace for a container
+func (r *Runtime) createNetNS(ctr *Container) (err error) {
+ ctrNS, err := ns.NewNS()
+ if err != nil {
+ return errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
+ }
+ defer func() {
+ if err != nil {
+ if err2 := ctrNS.Close(); err2 != nil {
+ logrus.Errorf("Error closing partially created network namespace for container %s: %v", ctr.ID(), err2)
+ }
+ }
+ }()
+
+ logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())
+ return r.configureNetNS(ctr, ctrNS)
+}
+
+// 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)
+
+ b := make([]byte, 16)
+
+ if _, err := rand.Reader.Read(b); err != nil {
+ return errors.Wrapf(err, "failed to generate random netns name")
+ }
+
+ nsPath := fmt.Sprintf("/var/run/netns/cni-%x-%x-%x-%x-%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
+
+ if err := os.MkdirAll(filepath.Dir(nsPath), 0711); err != nil {
+ return errors.Wrapf(err, "cannot create %s", filepath.Dir(nsPath))
+ }
+
+ mountPointFd, err := os.Create(nsPath)
+ if err != nil {
+ return errors.Wrapf(err, "cannot open %s", nsPath)
+ }
+ mountPointFd.Close()
+
+ if err := unix.Mount(nsProcess, nsPath, "none", unix.MS_BIND, ""); err != nil {
+ return errors.Wrapf(err, "cannot mount %s", nsPath)
+ }
+
+ netNS, err := ns.GetNS(nsPath)
+ if err != nil {
+ return err
+ }
+ return r.configureNetNS(ctr, netNS)
+}
+
// iptablesDNS accepts an arg (-I|-D) and IP address of the container and then
// generates an iptables command to either add or subtract the needed rule
func iptablesDNS(arg, ip string) error {
diff --git a/libpod/options.go b/libpod/options.go
index eaca70afc..2b3ad2eb4 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -707,7 +707,7 @@ func WithDependencyCtrs(ctrs []*Container) CtrCreateOption {
// namespace with a minimal configuration.
// An optional array of port mappings can be provided.
// Conflicts with WithNetNSFrom().
-func WithNetNS(portMappings []ocicni.PortMapping) CtrCreateOption {
+func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool) CtrCreateOption {
return func(ctr *Container) error {
if ctr.valid {
return ErrCtrFinalized
@@ -717,6 +717,7 @@ func WithNetNS(portMappings []ocicni.PortMapping) CtrCreateOption {
return errors.Wrapf(ErrInvalidArg, "container is already set to join another container's net ns, cannot create a new net ns")
}
+ ctr.config.PostConfigureNetNS = postConfigureNetNS
ctr.config.CreateNetNS = true
ctr.config.PortMappings = portMappings