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
|
language: go
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: xenial
|
||||||
|
|
||||||
go:
|
go:
|
||||||
- 1.11.x
|
- 1.11.x
|
||||||
|
@ -22,17 +22,36 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/containernetworking/plugins/pkg/ns"
|
"github.com/containernetworking/plugins/pkg/ns"
|
||||||
"golang.org/x/sys/unix"
|
"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
|
// Creates a new persistent (bind-mounted) network namespace and returns an object
|
||||||
// representing that namespace, without switching to it.
|
// representing that namespace, without switching to it.
|
||||||
func NewNS() (ns.NetNS, error) {
|
func NewNS() (ns.NetNS, error) {
|
||||||
|
|
||||||
|
nsRunDir := getNsRunDir()
|
||||||
|
|
||||||
b := make([]byte, 16)
|
b := make([]byte, 16)
|
||||||
_, err := rand.Reader.Read(b)
|
_, err := rand.Reader.Read(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -135,7 +154,7 @@ func NewNS() (ns.NetNS, error) {
|
|||||||
func UnmountNS(ns ns.NetNS) error {
|
func UnmountNS(ns ns.NetNS) error {
|
||||||
nsPath := ns.Path()
|
nsPath := ns.Path()
|
||||||
// Only unmount if it's been bind-mounted (don't touch namespaces in /proc...)
|
// 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 {
|
if err := unix.Unmount(nsPath, 0); err != nil {
|
||||||
return fmt.Errorf("failed to unmount NS: at %s: %v", nsPath, err)
|
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}"
|
echo -e "govet checking failed:\n${vetRes}"
|
||||||
exit 255
|
exit 255
|
||||||
fi
|
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