Skip to content

Commit

Permalink
Merge pull request containers#12227 from Luap99/net-setup
Browse files Browse the repository at this point in the history
Fix rootless networking with userns and ports
  • Loading branch information
openshift-merge-robot authored Nov 9, 2021
2 parents 43bd57c + 216e2cb commit 5437568
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 48 deletions.
7 changes: 2 additions & 5 deletions libpod/container_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err

// setup slirp4netns again because slirp4netns will die when conmon exits
if c.config.NetMode.IsSlirp4netns() {
err := c.runtime.setupSlirp4netns(c)
err := c.runtime.setupSlirp4netns(c, c.state.NetNS)
if err != nil {
return false, err
}
Expand All @@ -299,7 +299,7 @@ func (c *Container) handleRestartPolicy(ctx context.Context) (_ bool, retErr err
// setup rootlesskit port forwarder again since it dies when conmon exits
// we use rootlesskit port forwarder only as rootless and when bridge network is used
if rootless.IsRootless() && c.config.NetMode.IsBridge() && len(c.config.PortMappings) > 0 {
err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS.Path())
err := c.runtime.setupRootlessPortMappingViaRLK(c, c.state.NetNS.Path(), c.state.NetworkStatus)
if err != nil {
return false, err
}
Expand Down Expand Up @@ -999,9 +999,6 @@ func (c *Container) completeNetworkSetup() error {
if err := c.syncContainer(); err != nil {
return err
}
if c.config.NetMode.IsSlirp4netns() {
return c.runtime.setupSlirp4netns(c)
}
if err := c.runtime.setupNetNS(c); err != nil {
return err
}
Expand Down
9 changes: 0 additions & 9 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,6 @@ func (c *Container) prepare() error {
c.state.NetNS = netNS
c.state.NetworkStatus = networkStatus
}

// handle rootless network namespace setup
if noNetNS && !c.config.PostConfigureNetNS {
if rootless.IsRootless() {
createNetNSErr = c.runtime.setupRootlessNetNS(c)
} else if c.config.NetMode.IsSlirp4netns() {
createNetNSErr = c.runtime.setupSlirp4netns(c)
}
}
}()
// Mount storage if not mounted
go func() {
Expand Down
45 changes: 22 additions & 23 deletions libpod/networking_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -651,6 +651,9 @@ func getCNIPodName(c *Container) string {

// Create and configure a new network namespace for a container
func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]types.StatusBlock, error) {
if ctr.config.NetMode.IsSlirp4netns() {
return nil, r.setupSlirp4netns(ctr, ctrNS)
}
networks, _, err := ctr.networks()
if err != nil {
return nil, err
Expand All @@ -665,7 +668,24 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) (map[string]typ
if err != nil {
return nil, err
}
return r.setUpNetwork(ctrNS.Path(), netOpts)
netStatus, err := r.setUpNetwork(ctrNS.Path(), netOpts)
if err != nil {
return nil, err
}

// setup rootless port forwarder when rootless with ports and the network status is empty,
// if this is called from network reload the network status will not be empty and we should
// not setup port because they are still active
if rootless.IsRootless() && len(ctr.config.PortMappings) > 0 && ctr.getNetworkStatus() == nil {
// set up port forwarder for rootless netns
netnsPath := ctrNS.Path()
// TODO: support slirp4netns port forwarder as well
// make sure to fix this in container.handleRestartPolicy() as well
// Important we have to call this after r.setUpNetwork() so that
// we can use the proper netStatus
err = r.setupRootlessPortMappingViaRLK(ctr, netnsPath, netStatus)
}
return netStatus, err
}

// Create and configure a new network namespace for a container
Expand All @@ -688,31 +708,10 @@ func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q map[string]types.St
logrus.Debugf("Made network namespace at %s for container %s", ctrNS.Path(), ctr.ID())

var networkStatus map[string]types.StatusBlock
if !ctr.config.NetMode.IsSlirp4netns() {
networkStatus, err = r.configureNetNS(ctr, ctrNS)
}
networkStatus, err = r.configureNetNS(ctr, ctrNS)
return ctrNS, networkStatus, err
}

// Configure the network namespace for a rootless container
func (r *Runtime) setupRootlessNetNS(ctr *Container) error {
if ctr.config.NetMode.IsSlirp4netns() {
return r.setupSlirp4netns(ctr)
}
networks, _, err := ctr.networks()
if err != nil {
return err
}
if len(networks) > 0 && len(ctr.config.PortMappings) > 0 {
// set up port forwarder for rootless netns
netnsPath := ctr.state.NetNS.Path()
// TODO: support slirp4netns port forwarder as well
// make sure to fix this in container.handleRestartPolicy() as well
return r.setupRootlessPortMappingViaRLK(ctr, netnsPath)
}
return nil
}

// Configure the network namespace using the container process
func (r *Runtime) setupNetNS(ctr *Container) error {
nsProcess := fmt.Sprintf("/proc/%d/ns/net", ctr.state.PID)
Expand Down
21 changes: 10 additions & 11 deletions libpod/networking_slirp4netns.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"time"

"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/pkg/errorhandling"
"github.com/containers/podman/v3/pkg/rootless"
"github.com/containers/podman/v3/pkg/rootlessport"
Expand Down Expand Up @@ -207,7 +208,7 @@ func createBasicSlirp4netnsCmdArgs(options *slirp4netnsNetworkOptions, features
}

// setupSlirp4netns can be called in rootful as well as in rootless
func (r *Runtime) setupSlirp4netns(ctr *Container) error {
func (r *Runtime) setupSlirp4netns(ctr *Container, netns ns.NetNS) error {
path := r.config.Engine.NetworkCmdPath
if path == "" {
var err error
Expand Down Expand Up @@ -263,7 +264,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
if err != nil {
return errors.Wrapf(err, "failed to create rootless network sync pipe")
}
netnsPath = ctr.state.NetNS.Path()
netnsPath = netns.Path()
cmdArgs = append(cmdArgs, "--netns-type=path", netnsPath, "tap0")
} else {
defer errorhandling.CloseQuiet(ctr.rootlessSlirpSyncR)
Expand Down Expand Up @@ -366,7 +367,7 @@ func (r *Runtime) setupSlirp4netns(ctr *Container) error {
if netOptions.isSlirpHostForward {
return r.setupRootlessPortMappingViaSlirp(ctr, cmd, apiSocket)
}
return r.setupRootlessPortMappingViaRLK(ctr, netnsPath)
return r.setupRootlessPortMappingViaRLK(ctr, netnsPath, nil)
}

return nil
Expand Down Expand Up @@ -479,7 +480,7 @@ func waitForSync(syncR *os.File, cmd *exec.Cmd, logFile io.ReadSeeker, timeout t
return nil
}

func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath string) error {
func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath string, netStatus map[string]types.StatusBlock) error {
syncR, syncW, err := os.Pipe()
if err != nil {
return errors.Wrapf(err, "failed to open pipe")
Expand All @@ -506,7 +507,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin
}
}

childIP := getRootlessPortChildIP(ctr)
childIP := getRootlessPortChildIP(ctr, netStatus)
cfg := rootlessport.Config{
Mappings: ctr.config.PortMappings,
NetNSPath: netnsPath,
Expand All @@ -531,9 +532,7 @@ func (r *Runtime) setupRootlessPortMappingViaRLK(ctr *Container, netnsPath strin
cmd.Args = []string{rootlessport.BinaryName}

// Leak one end of the pipe in rootlessport process, the other will be sent to conmon
if ctr.rootlessPortSyncR != nil {
defer errorhandling.CloseQuiet(ctr.rootlessPortSyncR)
}
defer errorhandling.CloseQuiet(ctr.rootlessPortSyncR)

cmd.ExtraFiles = append(cmd.ExtraFiles, ctr.rootlessPortSyncR, syncW)
cmd.Stdin = cfgR
Expand Down Expand Up @@ -649,7 +648,7 @@ func (r *Runtime) setupRootlessPortMappingViaSlirp(ctr *Container, cmd *exec.Cmd
return nil
}

func getRootlessPortChildIP(c *Container) string {
func getRootlessPortChildIP(c *Container, netStatus map[string]types.StatusBlock) string {
if c.config.NetMode.IsSlirp4netns() {
slirp4netnsIP, err := GetSlirp4netnsIP(c.slirp4netnsSubnet)
if err != nil {
Expand All @@ -659,7 +658,7 @@ func getRootlessPortChildIP(c *Container) string {
}

var ipv6 net.IP
for _, status := range c.getNetworkStatus() {
for _, status := range netStatus {
for _, netInt := range status.Interfaces {
for _, netAddress := range netInt.Networks {
ipv4 := netAddress.Subnet.IP.To4()
Expand All @@ -679,7 +678,7 @@ func getRootlessPortChildIP(c *Container) string {
// reloadRootlessRLKPortMapping will trigger a reload for the port mappings in the rootlessport process.
// This should only be called by network connect/disconnect and only as rootless.
func (c *Container) reloadRootlessRLKPortMapping() error {
childIP := getRootlessPortChildIP(c)
childIP := getRootlessPortChildIP(c, c.state.NetworkStatus)
logrus.Debugf("reloading rootless ports for container %s, childIP is %s", c.config.ID, childIP)

conn, err := openUnixSocket(filepath.Join(c.runtime.config.Engine.TmpDir, "rp", c.config.ID))
Expand Down
3 changes: 3 additions & 0 deletions test/system/500-networking.bats
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ load helpers
if [[ -z $cidr ]]; then
# regex to match that we are in 10.X subnet
match="10\..*"
# force bridge networking also for rootless
# this ensures that rootless + bridge + userns + ports works
network_arg="--network bridge"
else
# Issue #9828 make sure a custom slir4netns cidr also works
network_arg="--network slirp4netns:cidr=$cidr"
Expand Down

0 comments on commit 5437568

Please sign in to comment.