pkg/ns: consider PROCFS during NS verification
This is an attempt to bring compatibility with Kernel <3.19, where NSFS where PROCFS was used for network namespaces.
This commit is contained in:
parent
ea073fc4c7
commit
2d47b0396d
65
ns/ns.go
65
ns/ns.go
@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
@ -74,38 +75,58 @@ func GetCurrentNS() (NetNS, error) {
|
|||||||
return GetNS(getCurrentThreadNetNSPath())
|
return GetNS(getCurrentThreadNetNSPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// https://github.com/torvalds/linux/blob/master/include/uapi/linux/magic.h
|
||||||
|
NSFS_MAGIC = 0x6e736673
|
||||||
|
PROCFS_MAGIC = 0x9fa0
|
||||||
|
)
|
||||||
|
|
||||||
|
func IsNS(nspath string) (isNS bool, msg string, err error) {
|
||||||
|
stat := syscall.Statfs_t{}
|
||||||
|
if err = syscall.Statfs(nspath, &stat); err != nil {
|
||||||
|
err = fmt.Errorf("failed to Statfs %s: %v", nspath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch stat.Type {
|
||||||
|
case PROCFS_MAGIC:
|
||||||
|
// Kernel < 3.19
|
||||||
|
|
||||||
|
validPathContent := "ns/"
|
||||||
|
validName := strings.Contains(nspath, validPathContent)
|
||||||
|
if !validName {
|
||||||
|
msg = fmt.Sprintf("path doesn't contain %q", validPathContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isNS = true
|
||||||
|
case NSFS_MAGIC:
|
||||||
|
// Kernel >= 3.19
|
||||||
|
|
||||||
|
isNS = true
|
||||||
|
default:
|
||||||
|
msg = fmt.Sprintf("unknown FS magic: %x", stat.Type)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Returns an object representing the namespace referred to by @path
|
// Returns an object representing the namespace referred to by @path
|
||||||
func GetNS(nspath string) (NetNS, error) {
|
func GetNS(nspath string) (NetNS, error) {
|
||||||
|
isNS, msg, err := IsNS(nspath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !isNS {
|
||||||
|
return nil, fmt.Errorf("no network namespace detected on %s: %s", nspath, msg)
|
||||||
|
}
|
||||||
|
|
||||||
fd, err := os.Open(nspath)
|
fd, err := os.Open(nspath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Failed to open %v: %v", nspath, err)
|
return nil, fmt.Errorf("Failed to open %v: %v", nspath, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
isNSFS, err := IsNSFS(nspath)
|
|
||||||
if err != nil {
|
|
||||||
fd.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !isNSFS {
|
|
||||||
fd.Close()
|
|
||||||
return nil, fmt.Errorf("%v is not of type NSFS", nspath)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &netNS{file: fd}, nil
|
return &netNS{file: fd}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns whether or not the nspath argument points to a network namespace
|
|
||||||
func IsNSFS(nspath string) (bool, error) {
|
|
||||||
const NSFS_MAGIC = 0x6e736673
|
|
||||||
|
|
||||||
stat := syscall.Statfs_t{}
|
|
||||||
if err := syscall.Statfs(nspath, &stat); err != nil {
|
|
||||||
return false, fmt.Errorf("failed to Statfs %q: %v", nspath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return stat.Type == NSFS_MAGIC, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Creates a new persistent network namespace and returns an object
|
// Creates a new persistent network namespace and returns an object
|
||||||
// representing that namespace, without switching to it
|
// representing that namespace, without switching to it
|
||||||
func NewNS() (NetNS, error) {
|
func NewNS() (NetNS, error) {
|
||||||
|
@ -180,7 +180,9 @@ var _ = Describe("Linux namespace operations", func() {
|
|||||||
defer os.Remove(nspath)
|
defer os.Remove(nspath)
|
||||||
|
|
||||||
_, err = ns.GetNS(nspath)
|
_, err = ns.GetNS(nspath)
|
||||||
Expect(err).To(MatchError(fmt.Sprintf("%v is not of type NSFS", nspath)))
|
Expect(err).To(HaveOccurred())
|
||||||
|
errString := fmt.Sprintf("%v", err)
|
||||||
|
Expect(errString).To(HavePrefix("no network namespace detected on %s", nspath))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -212,11 +214,12 @@ var _ = Describe("Linux namespace operations", func() {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
Describe("IsNSFS", func() {
|
Describe("IsNS", func() {
|
||||||
It("should detect a namespace", func() {
|
It("should detect a namespace", func() {
|
||||||
createdNetNS, err := ns.NewNS()
|
createdNetNS, err := ns.NewNS()
|
||||||
isNSFS, err := ns.IsNSFS(createdNetNS.Path())
|
isNSFS, msg, err := ns.IsNS(createdNetNS.Path())
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(msg).To(Equal(""))
|
||||||
Expect(isNSFS).To(Equal(true))
|
Expect(isNSFS).To(Equal(true))
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -228,7 +231,7 @@ var _ = Describe("Linux namespace operations", func() {
|
|||||||
nspath := tempFile.Name()
|
nspath := tempFile.Name()
|
||||||
defer os.Remove(nspath)
|
defer os.Remove(nspath)
|
||||||
|
|
||||||
isNSFS, err := ns.IsNSFS(nspath)
|
isNSFS, _, err := ns.IsNS(nspath)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(isNSFS).To(Equal(false))
|
Expect(isNSFS).To(Equal(false))
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user