Merge pull request #401 from giuseppe/run-in-a-userns

testutils: newNS() works in a rootless user namespace
This commit is contained in:
Matt Dupre
2019-10-23 16:29:59 +01:00
committed by GitHub
3 changed files with 26 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
language: go
sudo: required
dist: trusty
dist: xenial
go:
- 1.11.x

View File

@@ -22,17 +22,36 @@ import (
"runtime"
"strings"
"sync"
"syscall"
"github.com/containernetworking/plugins/pkg/ns"
"golang.org/x/sys/unix"
)
const nsRunDir = "/var/run/netns"
func getNsRunDir() string {
xdgRuntimeDir := os.Getenv("XDG_RUNTIME_DIR")
/// If XDG_RUNTIME_DIR is set, check if the current user owns /var/run. If
// the owner is different, we are most likely running in a user namespace.
// In that case use $XDG_RUNTIME_DIR/netns as runtime dir.
if xdgRuntimeDir != "" {
if s, err := os.Stat("/var/run"); err == nil {
st, ok := s.Sys().(*syscall.Stat_t)
if ok && int(st.Uid) != os.Geteuid() {
return path.Join(xdgRuntimeDir, "netns")
}
}
}
return "/var/run/netns"
}
// Creates a new persistent (bind-mounted) network namespace and returns an object
// representing that namespace, without switching to it.
func NewNS() (ns.NetNS, error) {
nsRunDir := getNsRunDir()
b := make([]byte, 16)
_, err := rand.Reader.Read(b)
if err != nil {
@@ -135,7 +154,7 @@ func NewNS() (ns.NetNS, error) {
func UnmountNS(ns ns.NetNS) error {
nsPath := ns.Path()
// Only unmount if it's been bind-mounted (don't touch namespaces in /proc...)
if strings.HasPrefix(nsPath, nsRunDir) {
if strings.HasPrefix(nsPath, getNsRunDir()) {
if err := unix.Unmount(nsPath, 0); err != nil {
return fmt.Errorf("failed to unmount NS: at %s: %v", nsPath, err)
}

View File

@@ -57,3 +57,7 @@ if [ -n "${vetRes}" ]; then
echo -e "govet checking failed:\n${vetRes}"
exit 255
fi
# Run the pkg/ns tests as non root user
mkdir /tmp/cni-rootless
(export XDG_RUNTIME_DIR=/tmp/cni-rootless; cd pkg/ns/; unshare -rmn go test)