testutils: newNS() works in a rootless user namespace
When running in a user namespace created by an unprivileged user the owner of /var/run will be reported as the unknown user (as defined in /proc/sys/kernel/overflowuid) so any access to the directory will fail. If the XDG_RUNTIME_DIR environment variable is set, check whether the current user is also the owner of /var/run. If the owner is different than the current user, use the $XDG_RUNTIME_DIR/netns directory. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
411d060b81
commit
85083ea434
@ -1,6 +1,6 @@
|
||||
language: go
|
||||
sudo: required
|
||||
dist: trusty
|
||||
dist: xenial
|
||||
|
||||
go:
|
||||
- 1.11.x
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user