Browse code

vendor: vishvananda/netns db3c7e526aae966c4ccfa6c8189b693d6ac5d202

full diff: https://github.com/vishvananda/netns/compare/0a2b9b5464df8343199164a0321edf3313202f7e...db3c7e526aae966c4ccfa6c8189b693d6ac5d202

- Use golang.org/x/sys/unix instead of syscall
- Set O_CLOEXEC when opening a network namespace
- Fixes "the container‘s netns fds leak, causing the container netns to not
clean up successfully after the container stops"
- Allows to create and delete named network namespaces

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 818bad6ef21e473a80a27564bd2219449633dbb8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2020/07/29 04:26:13
Showing 4 changed files
... ...
@@ -50,7 +50,7 @@ github.com/hashicorp/go-sockaddr                    c7188e74f6acae5a989bdc959aa7
50 50
 github.com/hashicorp/go-multierror                  886a7fbe3eb1c874d46f623bfa70af45f425b3d1 # v1.0.0
51 51
 github.com/hashicorp/serf                           598c54895cc5a7b1a24a398d635e8c0ea0959870
52 52
 github.com/docker/libkv                             458977154600b9f23984d9f4b82e79570b5ae12b
53
-github.com/vishvananda/netns                        0a2b9b5464df8343199164a0321edf3313202f7e
53
+github.com/vishvananda/netns                        db3c7e526aae966c4ccfa6c8189b693d6ac5d202
54 54
 github.com/vishvananda/netlink                      a2ad57a690f3caf3015351d2d6e1c0b95c349752
55 55
 
56 56
 # When updating, consider updating TOMLV_COMMIT in hack/dockerfile/install/tomlv.installer accordingly
... ...
@@ -1,3 +1,5 @@
1 1
 module github.com/vishvananda/netns
2 2
 
3 3
 go 1.12
4
+
5
+require golang.org/x/sys v0.0.0-20200217220822-9197077df867
... ...
@@ -10,7 +10,8 @@ package netns
10 10
 
11 11
 import (
12 12
 	"fmt"
13
-	"syscall"
13
+
14
+	"golang.org/x/sys/unix"
14 15
 )
15 16
 
16 17
 // NsHandle is a handle to a network namespace. It can be cast directly
... ...
@@ -24,11 +25,11 @@ func (ns NsHandle) Equal(other NsHandle) bool {
24 24
 	if ns == other {
25 25
 		return true
26 26
 	}
27
-	var s1, s2 syscall.Stat_t
28
-	if err := syscall.Fstat(int(ns), &s1); err != nil {
27
+	var s1, s2 unix.Stat_t
28
+	if err := unix.Fstat(int(ns), &s1); err != nil {
29 29
 		return false
30 30
 	}
31
-	if err := syscall.Fstat(int(other), &s2); err != nil {
31
+	if err := unix.Fstat(int(other), &s2); err != nil {
32 32
 		return false
33 33
 	}
34 34
 	return (s1.Dev == s2.Dev) && (s1.Ino == s2.Ino)
... ...
@@ -36,11 +37,11 @@ func (ns NsHandle) Equal(other NsHandle) bool {
36 36
 
37 37
 // String shows the file descriptor number and its dev and inode.
38 38
 func (ns NsHandle) String() string {
39
-	var s syscall.Stat_t
40 39
 	if ns == -1 {
41 40
 		return "NS(None)"
42 41
 	}
43
-	if err := syscall.Fstat(int(ns), &s); err != nil {
42
+	var s unix.Stat_t
43
+	if err := unix.Fstat(int(ns), &s); err != nil {
44 44
 		return fmt.Sprintf("NS(%d: unknown)", ns)
45 45
 	}
46 46
 	return fmt.Sprintf("NS(%d: %d, %d)", ns, s.Dev, s.Ino)
... ...
@@ -49,11 +50,11 @@ func (ns NsHandle) String() string {
49 49
 // UniqueId returns a string which uniquely identifies the namespace
50 50
 // associated with the network handle.
51 51
 func (ns NsHandle) UniqueId() string {
52
-	var s syscall.Stat_t
53 52
 	if ns == -1 {
54 53
 		return "NS(none)"
55 54
 	}
56
-	if err := syscall.Fstat(int(ns), &s); err != nil {
55
+	var s unix.Stat_t
56
+	if err := unix.Fstat(int(ns), &s); err != nil {
57 57
 		return "NS(unknown)"
58 58
 	}
59 59
 	return fmt.Sprintf("NS(%d:%d)", s.Dev, s.Ino)
... ...
@@ -67,7 +68,7 @@ func (ns NsHandle) IsOpen() bool {
67 67
 // Close closes the NsHandle and resets its file descriptor to -1.
68 68
 // It is not safe to use an NsHandle after Close() is called.
69 69
 func (ns *NsHandle) Close() error {
70
-	if err := syscall.Close(int(*ns)); err != nil {
70
+	if err := unix.Close(int(*ns)); err != nil {
71 71
 		return err
72 72
 	}
73 73
 	(*ns) = -1
... ...
@@ -6,46 +6,30 @@ import (
6 6
 	"fmt"
7 7
 	"io/ioutil"
8 8
 	"os"
9
+	"path"
9 10
 	"path/filepath"
10
-	"runtime"
11 11
 	"strconv"
12 12
 	"strings"
13 13
 	"syscall"
14
-)
15 14
 
16
-// SYS_SETNS syscall allows changing the namespace of the current process.
17
-var SYS_SETNS = map[string]uintptr{
18
-	"386":     346,
19
-	"amd64":   308,
20
-	"arm64":   268,
21
-	"arm":     375,
22
-	"mips":    4344,
23
-	"mipsle":  4344,
24
-	"mips64le":  4344,
25
-	"ppc64":   350,
26
-	"ppc64le": 350,
27
-	"riscv64": 268,
28
-	"s390x":   339,
29
-}[runtime.GOARCH]
15
+	"golang.org/x/sys/unix"
16
+)
30 17
 
31 18
 // Deprecated: use syscall pkg instead (go >= 1.5 needed).
32 19
 const (
33
-	CLONE_NEWUTS  = 0x04000000 /* New utsname group? */
34
-	CLONE_NEWIPC  = 0x08000000 /* New ipcs */
35
-	CLONE_NEWUSER = 0x10000000 /* New user namespace */
36
-	CLONE_NEWPID  = 0x20000000 /* New pid namespace */
37
-	CLONE_NEWNET  = 0x40000000 /* New network namespace */
38
-	CLONE_IO      = 0x80000000 /* Get io context */
20
+	CLONE_NEWUTS  = 0x04000000   /* New utsname group? */
21
+	CLONE_NEWIPC  = 0x08000000   /* New ipcs */
22
+	CLONE_NEWUSER = 0x10000000   /* New user namespace */
23
+	CLONE_NEWPID  = 0x20000000   /* New pid namespace */
24
+	CLONE_NEWNET  = 0x40000000   /* New network namespace */
25
+	CLONE_IO      = 0x80000000   /* Get io context */
26
+	bindMountPath = "/run/netns" /* Bind mount path for named netns */
39 27
 )
40 28
 
41 29
 // Setns sets namespace using syscall. Note that this should be a method
42 30
 // in syscall but it has not been added.
43 31
 func Setns(ns NsHandle, nstype int) (err error) {
44
-	_, _, e1 := syscall.Syscall(SYS_SETNS, uintptr(ns), uintptr(nstype), 0)
45
-	if e1 != 0 {
46
-		err = e1
47
-	}
48
-	return
32
+	return unix.Setns(int(ns), nstype)
49 33
 }
50 34
 
51 35
 // Set sets the current network namespace to the namespace represented
... ...
@@ -57,21 +41,64 @@ func Set(ns NsHandle) (err error) {
57 57
 // New creates a new network namespace, sets it as current and returns
58 58
 // a handle to it.
59 59
 func New() (ns NsHandle, err error) {
60
-	if err := syscall.Unshare(CLONE_NEWNET); err != nil {
60
+	if err := unix.Unshare(CLONE_NEWNET); err != nil {
61 61
 		return -1, err
62 62
 	}
63 63
 	return Get()
64 64
 }
65 65
 
66
+// NewNamed creates a new named network namespace and returns a handle to it
67
+func NewNamed(name string) (NsHandle, error) {
68
+	if _, err := os.Stat(bindMountPath); os.IsNotExist(err) {
69
+		err = os.MkdirAll(bindMountPath, 0755)
70
+		if err != nil {
71
+			return None(), err
72
+		}
73
+	}
74
+
75
+	newNs, err := New()
76
+	if err != nil {
77
+		return None(), err
78
+	}
79
+
80
+	namedPath := path.Join(bindMountPath, name)
81
+
82
+	f, err := os.OpenFile(namedPath, os.O_CREATE|os.O_EXCL, 0444)
83
+	if err != nil {
84
+		return None(), err
85
+	}
86
+	f.Close()
87
+
88
+	nsPath := fmt.Sprintf("/proc/%d/task/%d/ns/net", os.Getpid(), syscall.Gettid())
89
+	err = syscall.Mount(nsPath, namedPath, "bind", syscall.MS_BIND, "")
90
+	if err != nil {
91
+		return None(), err
92
+	}
93
+
94
+	return newNs, nil
95
+}
96
+
97
+// DeleteNamed deletes a named network namespace
98
+func DeleteNamed(name string) error {
99
+	namedPath := path.Join(bindMountPath, name)
100
+
101
+	err := syscall.Unmount(namedPath, syscall.MNT_DETACH)
102
+	if err != nil {
103
+		return err
104
+	}
105
+
106
+	return os.Remove(namedPath)
107
+}
108
+
66 109
 // Get gets a handle to the current threads network namespace.
67 110
 func Get() (NsHandle, error) {
68
-	return GetFromThread(os.Getpid(), syscall.Gettid())
111
+	return GetFromThread(os.Getpid(), unix.Gettid())
69 112
 }
70 113
 
71 114
 // GetFromPath gets a handle to a network namespace
72 115
 // identified by the path
73 116
 func GetFromPath(path string) (NsHandle, error) {
74
-	fd, err := syscall.Open(path, syscall.O_RDONLY, 0)
117
+	fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC, 0)
75 118
 	if err != nil {
76 119
 		return -1, err
77 120
 	}