mirror of
https://github.com/containers/podman.git
synced 2025-06-25 03:52:15 +08:00
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
This commit is contained in:

committed by
Atomic Bot

parent
b51d737998
commit
73078fabcf
@ -167,6 +167,7 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
cgroupPerm := "ro"
|
cgroupPerm := "ro"
|
||||||
g := generate.New()
|
g := generate.New()
|
||||||
g.HostSpecific = true
|
g.HostSpecific = true
|
||||||
|
addCgroup := true
|
||||||
if config.Privileged {
|
if config.Privileged {
|
||||||
cgroupPerm = "rw"
|
cgroupPerm = "rw"
|
||||||
g.RemoveMount("/sys")
|
g.RemoveMount("/sys")
|
||||||
@ -177,7 +178,19 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
Options: []string{"nosuid", "noexec", "nodev", "rw"},
|
Options: []string{"nosuid", "noexec", "nodev", "rw"},
|
||||||
}
|
}
|
||||||
g.AddMount(sysMnt)
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
if addCgroup {
|
||||||
cgroupMnt := spec.Mount{
|
cgroupMnt := spec.Mount{
|
||||||
Destination: "/sys/fs/cgroup",
|
Destination: "/sys/fs/cgroup",
|
||||||
Type: "cgroup",
|
Type: "cgroup",
|
||||||
@ -185,6 +198,7 @@ func createConfigToOCISpec(config *createConfig) (*spec.Spec, error) {
|
|||||||
Options: []string{"nosuid", "noexec", "nodev", "relatime", cgroupPerm},
|
Options: []string{"nosuid", "noexec", "nodev", "relatime", cgroupPerm},
|
||||||
}
|
}
|
||||||
g.AddMount(cgroupMnt)
|
g.AddMount(cgroupMnt)
|
||||||
|
}
|
||||||
g.SetProcessCwd(config.WorkDir)
|
g.SetProcessCwd(config.WorkDir)
|
||||||
g.SetProcessArgs(config.Command)
|
g.SetProcessArgs(config.Command)
|
||||||
g.SetProcessTerminal(config.Tty)
|
g.SetProcessTerminal(config.Tty)
|
||||||
@ -697,8 +711,9 @@ func (c *createConfig) GetContainerCreateOptions() ([]libpod.CtrCreateOption, er
|
|||||||
}
|
}
|
||||||
options = append(options, libpod.WithNetNSFrom(connectedCtr))
|
options = append(options, libpod.WithNetNSFrom(connectedCtr))
|
||||||
} else if !c.NetMode.IsHost() && !c.NetMode.IsNone() {
|
} else if !c.NetMode.IsHost() && !c.NetMode.IsNone() {
|
||||||
options = append(options, libpod.WithNetNS([]ocicni.PortMapping{}))
|
postConfigureNetNS := (len(c.IDMappings.UIDMap) > 0 || len(c.IDMappings.GIDMap) > 0) && !c.UsernsMode.IsHost()
|
||||||
options = append(options, libpod.WithNetNS(portBindings))
|
options = append(options, libpod.WithNetNS([]ocicni.PortMapping{}, postConfigureNetNS))
|
||||||
|
options = append(options, libpod.WithNetNS(portBindings, postConfigureNetNS))
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.PidMode.IsContainer() {
|
if c.PidMode.IsContainer() {
|
||||||
|
@ -285,6 +285,8 @@ type ContainerConfig struct {
|
|||||||
// File containing the conmon PID
|
// File containing the conmon PID
|
||||||
ConmonPidFile string `json:"conmonPidFile,omitempty"`
|
ConmonPidFile string `json:"conmonPidFile,omitempty"`
|
||||||
// TODO log options for log drivers
|
// TODO log options for log drivers
|
||||||
|
|
||||||
|
PostConfigureNetNS bool `json:"postConfigureNetNS"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContainerStatus returns a string representation for users
|
// ContainerStatus returns a string representation for users
|
||||||
|
@ -416,6 +416,16 @@ func (c *Container) checkDependenciesRunningLocked(depCtrs map[string]*Container
|
|||||||
return notRunning, nil
|
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
|
// Initialize a container, creating it in the runtime
|
||||||
func (c *Container) init(ctx context.Context) error {
|
func (c *Container) init(ctx context.Context) error {
|
||||||
if err := c.makeBindMounts(); err != nil {
|
if err := c.makeBindMounts(); err != nil {
|
||||||
@ -442,7 +452,11 @@ func (c *Container) init(ctx context.Context) error {
|
|||||||
|
|
||||||
c.state.State = ContainerStateCreated
|
c.state.State = ContainerStateCreated
|
||||||
|
|
||||||
return c.save()
|
if err := c.save(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.completeNetworkSetup()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reinitialize a container
|
// Reinitialize a container
|
||||||
@ -626,7 +640,7 @@ func (c *Container) prepare() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set up network namespace if not already set up
|
// 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 {
|
if err := c.runtime.createNetNS(c); err != nil {
|
||||||
// Tear down storage before exiting to make sure we
|
// Tear down storage before exiting to make sure we
|
||||||
// don't leak mounts
|
// don't leak mounts
|
||||||
@ -913,8 +927,12 @@ func (c *Container) generateSpec(ctx context.Context) (*spec.Spec, error) {
|
|||||||
|
|
||||||
// If network namespace was requested, add it now
|
// If network namespace was requested, add it now
|
||||||
if c.config.CreateNetNS {
|
if c.config.CreateNetNS {
|
||||||
|
if c.config.PostConfigureNetNS {
|
||||||
|
g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, "")
|
||||||
|
} else {
|
||||||
g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
|
g.AddOrReplaceLinuxNamespace(spec.NetworkNamespace, c.state.NetNS.Path())
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the default /dev/shm mount to ensure we overwrite it
|
// Remove the default /dev/shm mount to ensure we overwrite it
|
||||||
g.RemoveMount("/dev/shm")
|
g.RemoveMount("/dev/shm")
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
package libpod
|
package libpod
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
cnitypes "github.com/containernetworking/cni/pkg/types/current"
|
cnitypes "github.com/containernetworking/cni/pkg/types/current"
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
@ -9,7 +14,7 @@ import (
|
|||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/projectatomic/libpod/utils"
|
"github.com/projectatomic/libpod/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"strings"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get an OCICNI network config
|
// 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
|
// Create and configure a new network namespace for a container
|
||||||
func (r *Runtime) createNetNS(ctr *Container) (err error) {
|
func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (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())
|
|
||||||
podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.PortMappings)
|
podNetwork := getPodNetwork(ctr.ID(), ctr.Name(), ctrNS.Path(), ctr.config.PortMappings)
|
||||||
|
|
||||||
result, err := r.netPlugin.SetUpPod(podNetwork)
|
result, err := r.netPlugin.SetUpPod(podNetwork)
|
||||||
@ -74,6 +66,57 @@ func (r *Runtime) createNetNS(ctr *Container) (err error) {
|
|||||||
return nil
|
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
|
// 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
|
// generates an iptables command to either add or subtract the needed rule
|
||||||
func iptablesDNS(arg, ip string) error {
|
func iptablesDNS(arg, ip string) error {
|
||||||
|
@ -707,7 +707,7 @@ func WithDependencyCtrs(ctrs []*Container) CtrCreateOption {
|
|||||||
// namespace with a minimal configuration.
|
// namespace with a minimal configuration.
|
||||||
// An optional array of port mappings can be provided.
|
// An optional array of port mappings can be provided.
|
||||||
// Conflicts with WithNetNSFrom().
|
// Conflicts with WithNetNSFrom().
|
||||||
func WithNetNS(portMappings []ocicni.PortMapping) CtrCreateOption {
|
func WithNetNS(portMappings []ocicni.PortMapping, postConfigureNetNS bool) CtrCreateOption {
|
||||||
return func(ctr *Container) error {
|
return func(ctr *Container) error {
|
||||||
if ctr.valid {
|
if ctr.valid {
|
||||||
return ErrCtrFinalized
|
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")
|
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.CreateNetNS = true
|
||||||
ctr.config.PortMappings = portMappings
|
ctr.config.PortMappings = portMappings
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user