Browse code

Merge pull request #41786 from thaJeztah/test_selinux_tip

vendor: opencontainers/selinux v1.8.0, and remove selinux build-tag and stubs

Akihiro Suda authored on 2020/12/26 00:07:49
Showing 17 changed files
... ...
@@ -6,7 +6,7 @@ ARG SYSTEMD="false"
6 6
 ARG GO_VERSION=1.13.15
7 7
 ARG DEBIAN_FRONTEND=noninteractive
8 8
 ARG VPNKIT_VERSION=0.4.0
9
-ARG DOCKER_BUILDTAGS="apparmor seccomp selinux"
9
+ARG DOCKER_BUILDTAGS="apparmor seccomp"
10 10
 
11 11
 ARG BASE_DEBIAN_DISTRO="buster"
12 12
 ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
... ...
@@ -45,6 +45,7 @@ import (
45 45
 	lntypes "github.com/docker/libnetwork/types"
46 46
 	"github.com/moby/sys/mount"
47 47
 	specs "github.com/opencontainers/runtime-spec/specs-go"
48
+	"github.com/opencontainers/selinux/go-selinux"
48 49
 	"github.com/opencontainers/selinux/go-selinux/label"
49 50
 	"github.com/pkg/errors"
50 51
 	"github.com/sirupsen/logrus"
... ...
@@ -822,7 +823,7 @@ func overlaySupportsSelinux() (bool, error) {
822 822
 // configureKernelSecuritySupport configures and validates security support for the kernel
823 823
 func configureKernelSecuritySupport(config *config.Config, driverName string) error {
824 824
 	if config.EnableSelinuxSupport {
825
-		if !selinuxEnabled() {
825
+		if !selinux.GetEnabled() {
826 826
 			logrus.Warn("Docker could not enable SELinux on the host system")
827 827
 			return nil
828 828
 		}
... ...
@@ -840,7 +841,7 @@ func configureKernelSecuritySupport(config *config.Config, driverName string) er
840 840
 			}
841 841
 		}
842 842
 	} else {
843
-		selinuxSetDisabled()
843
+		selinux.SetDisabled()
844 844
 	}
845 845
 	return nil
846 846
 }
... ...
@@ -11,6 +11,7 @@ import (
11 11
 	"github.com/docker/docker/container"
12 12
 	"github.com/docker/docker/errdefs"
13 13
 	"github.com/docker/docker/pkg/system"
14
+	"github.com/opencontainers/selinux/go-selinux"
14 15
 	"github.com/pkg/errors"
15 16
 	"github.com/sirupsen/logrus"
16 17
 )
... ...
@@ -134,7 +135,7 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, forceRemo
134 134
 	}
135 135
 
136 136
 	linkNames := daemon.linkIndex.delete(container)
137
-	selinuxFreeLxcContexts(container.ProcessLabel)
137
+	selinux.ReleaseLabel(container.ProcessLabel)
138 138
 	daemon.idIndex.Delete(container.ID)
139 139
 	daemon.containers.Delete(container.ID)
140 140
 	daemon.containersReplica.Delete(container)
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	"github.com/docker/docker/pkg/system"
23 23
 	"github.com/docker/docker/registry"
24 24
 	metrics "github.com/docker/go-metrics"
25
+	"github.com/opencontainers/selinux/go-selinux"
25 26
 	"github.com/sirupsen/logrus"
26 27
 )
27 28
 
... ...
@@ -188,7 +189,7 @@ func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInf
188 188
 		}
189 189
 		securityOptions = append(securityOptions, fmt.Sprintf("name=seccomp,profile=%s", profile))
190 190
 	}
191
-	if selinuxEnabled() {
191
+	if selinux.GetEnabled() {
192 192
 		securityOptions = append(securityOptions, "name=selinux")
193 193
 	}
194 194
 	if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
195 195
deleted file mode 100644
... ...
@@ -1,15 +0,0 @@
1
-package daemon // import "github.com/docker/docker/daemon"
2
-
3
-import selinux "github.com/opencontainers/selinux/go-selinux"
4
-
5
-func selinuxSetDisabled() {
6
-	selinux.SetDisabled()
7
-}
8
-
9
-func selinuxFreeLxcContexts(label string) {
10
-	selinux.ReleaseLabel(label)
11
-}
12
-
13
-func selinuxEnabled() bool {
14
-	return selinux.GetEnabled()
15
-}
16 1
deleted file mode 100644
... ...
@@ -1,13 +0,0 @@
1
-// +build !linux
2
-
3
-package daemon // import "github.com/docker/docker/daemon"
4
-
5
-func selinuxSetDisabled() {
6
-}
7
-
8
-func selinuxFreeLxcContexts(label string) {
9
-}
10
-
11
-func selinuxEnabled() bool {
12
-	return false
13
-}
... ...
@@ -157,12 +157,6 @@ export DOCKER_BUILDTAGS='apparmor'
157 157
 ```
158 158
 
159 159
 If you're building a binary that may need to be used on platforms that include
160
-SELinux, you will need to use the `selinux` build tag:
161
-```bash
162
-export DOCKER_BUILDTAGS='selinux'
163
-```
164
-
165
-If you're building a binary that may need to be used on platforms that include
166 160
 seccomp, you will need to use the `seccomp` build tag:
167 161
 ```bash
168 162
 export DOCKER_BUILDTAGS='seccomp'
... ...
@@ -188,7 +182,7 @@ export DOCKER_BUILDTAGS='exclude_graphdriver_aufs'
188 188
 
189 189
 NOTE: if you need to set more than one build tag, space separate them:
190 190
 ```bash
191
-export DOCKER_BUILDTAGS='apparmor selinux exclude_graphdriver_aufs'
191
+export DOCKER_BUILDTAGS='apparmor exclude_graphdriver_aufs'
192 192
 ```
193 193
 
194 194
 ### LCOW (Linux Containers On Windows)
... ...
@@ -176,7 +176,7 @@ github.com/morikuni/aec                             39771216ff4c63d11f5e604076f9
176 176
 # metrics
177 177
 github.com/docker/go-metrics                        b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
178 178
 
179
-github.com/opencontainers/selinux                   63ad55b76fd78d4c76c2f5491f68516e60c9d523 # v1.7.0
179
+github.com/opencontainers/selinux                   2f45b3796d18f1ab4c9fc0c888a98d0a0fd6e429 # v1.8.0
180 180
 github.com/willf/bitset                             559910e8471e48d76d9e5a1ba15842dee77ad45d # v1.1.11
181 181
 
182 182
 
... ...
@@ -6,7 +6,8 @@ Common SELinux package used across the container ecosystem.
6 6
 
7 7
 ## Usage
8 8
 
9
-When compiling consumers of this project, the `selinux` build tag must be used to enable selinux functionality.
9
+Prior to v1.8.0, the `selinux` build tag had to be used to enable selinux functionality for compiling consumers of this project.
10
+Starting with v1.8.0, the `selinux` build tag is no longer needed.
10 11
 
11 12
 For complete documentation, see [godoc](https://godoc.org/github.com/opencontainers/selinux).
12 13
 
... ...
@@ -5,9 +5,6 @@ This package uses a selinux build tag to enable the selinux functionality. This
5 5
 allows non-linux and linux users who do not have selinux support to still use
6 6
 tools that rely on this library.
7 7
 
8
-To compile with full selinux support use the -tags=selinux option in your build
9
-and test commands.
10
-
11 8
 Usage:
12 9
 
13 10
 	import "github.com/opencontainers/selinux/go-selinux"
14 11
new file mode 100644
... ...
@@ -0,0 +1,190 @@
0
+package label
1
+
2
+import (
3
+	"os"
4
+	"os/user"
5
+	"strings"
6
+
7
+	"github.com/opencontainers/selinux/go-selinux"
8
+	"github.com/pkg/errors"
9
+)
10
+
11
+// Valid Label Options
12
+var validOptions = map[string]bool{
13
+	"disable":  true,
14
+	"type":     true,
15
+	"filetype": true,
16
+	"user":     true,
17
+	"role":     true,
18
+	"level":    true,
19
+}
20
+
21
+var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
22
+
23
+// InitLabels returns the process label and file labels to be used within
24
+// the container.  A list of options can be passed into this function to alter
25
+// the labels.  The labels returned will include a random MCS String, that is
26
+// guaranteed to be unique.
27
+func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
28
+	if !selinux.GetEnabled() {
29
+		return "", "", nil
30
+	}
31
+	processLabel, mountLabel := selinux.ContainerLabels()
32
+	if processLabel != "" {
33
+		defer func() {
34
+			if retErr != nil {
35
+				selinux.ReleaseLabel(mountLabel)
36
+			}
37
+		}()
38
+		pcon, err := selinux.NewContext(processLabel)
39
+		if err != nil {
40
+			return "", "", err
41
+		}
42
+		mcsLevel := pcon["level"]
43
+		mcon, err := selinux.NewContext(mountLabel)
44
+		if err != nil {
45
+			return "", "", err
46
+		}
47
+		for _, opt := range options {
48
+			if opt == "disable" {
49
+				return "", mountLabel, nil
50
+			}
51
+			if i := strings.Index(opt, ":"); i == -1 {
52
+				return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
53
+			}
54
+			con := strings.SplitN(opt, ":", 2)
55
+			if !validOptions[con[0]] {
56
+				return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
57
+			}
58
+			if con[0] == "filetype" {
59
+				mcon["type"] = con[1]
60
+				continue
61
+			}
62
+			pcon[con[0]] = con[1]
63
+			if con[0] == "level" || con[0] == "user" {
64
+				mcon[con[0]] = con[1]
65
+			}
66
+		}
67
+		if pcon.Get() != processLabel {
68
+			if pcon["level"] != mcsLevel {
69
+				selinux.ReleaseLabel(processLabel)
70
+			}
71
+			processLabel = pcon.Get()
72
+			selinux.ReserveLabel(processLabel)
73
+		}
74
+		mountLabel = mcon.Get()
75
+	}
76
+	return processLabel, mountLabel, nil
77
+}
78
+
79
+// Deprecated: The GenLabels function is only to be used during the transition
80
+// to the official API. Use InitLabels(strings.Fields(options)) instead.
81
+func GenLabels(options string) (string, string, error) {
82
+	return InitLabels(strings.Fields(options))
83
+}
84
+
85
+// SetFileLabel modifies the "path" label to the specified file label
86
+func SetFileLabel(path string, fileLabel string) error {
87
+	if !selinux.GetEnabled() || fileLabel == "" {
88
+		return nil
89
+	}
90
+	return selinux.SetFileLabel(path, fileLabel)
91
+}
92
+
93
+// SetFileCreateLabel tells the kernel the label for all files to be created
94
+func SetFileCreateLabel(fileLabel string) error {
95
+	if !selinux.GetEnabled() {
96
+		return nil
97
+	}
98
+	return selinux.SetFSCreateLabel(fileLabel)
99
+}
100
+
101
+// Relabel changes the label of path to the filelabel string.
102
+// It changes the MCS label to s0 if shared is true.
103
+// This will allow all containers to share the content.
104
+func Relabel(path string, fileLabel string, shared bool) error {
105
+	if !selinux.GetEnabled() || fileLabel == "" {
106
+		return nil
107
+	}
108
+
109
+	exclude_paths := map[string]bool{
110
+		"/":           true,
111
+		"/bin":        true,
112
+		"/boot":       true,
113
+		"/dev":        true,
114
+		"/etc":        true,
115
+		"/etc/passwd": true,
116
+		"/etc/pki":    true,
117
+		"/etc/shadow": true,
118
+		"/home":       true,
119
+		"/lib":        true,
120
+		"/lib64":      true,
121
+		"/media":      true,
122
+		"/opt":        true,
123
+		"/proc":       true,
124
+		"/root":       true,
125
+		"/run":        true,
126
+		"/sbin":       true,
127
+		"/srv":        true,
128
+		"/sys":        true,
129
+		"/tmp":        true,
130
+		"/usr":        true,
131
+		"/var":        true,
132
+		"/var/lib":    true,
133
+		"/var/log":    true,
134
+	}
135
+
136
+	if home := os.Getenv("HOME"); home != "" {
137
+		exclude_paths[home] = true
138
+	}
139
+
140
+	if sudoUser := os.Getenv("SUDO_USER"); sudoUser != "" {
141
+		if usr, err := user.Lookup(sudoUser); err == nil {
142
+			exclude_paths[usr.HomeDir] = true
143
+		}
144
+	}
145
+
146
+	if path != "/" {
147
+		path = strings.TrimSuffix(path, "/")
148
+	}
149
+	if exclude_paths[path] {
150
+		return errors.Errorf("SELinux relabeling of %s is not allowed", path)
151
+	}
152
+
153
+	if shared {
154
+		c, err := selinux.NewContext(fileLabel)
155
+		if err != nil {
156
+			return err
157
+		}
158
+
159
+		c["level"] = "s0"
160
+		fileLabel = c.Get()
161
+	}
162
+	if err := selinux.Chcon(path, fileLabel, true); err != nil {
163
+		return err
164
+	}
165
+	return nil
166
+}
167
+
168
+// DisableSecOpt returns a security opt that can disable labeling
169
+// support for future container processes
170
+// Deprecated: use selinux.DisableSecOpt
171
+var DisableSecOpt = selinux.DisableSecOpt
172
+
173
+// Validate checks that the label does not include unexpected options
174
+func Validate(label string) error {
175
+	if strings.Contains(label, "z") && strings.Contains(label, "Z") {
176
+		return ErrIncompatibleLabel
177
+	}
178
+	return nil
179
+}
180
+
181
+// RelabelNeeded checks whether the user requested a relabel
182
+func RelabelNeeded(label string) bool {
183
+	return strings.Contains(label, "z") || strings.Contains(label, "Z")
184
+}
185
+
186
+// IsShared checks that the label includes a "shared" mark
187
+func IsShared(label string) bool {
188
+	return strings.Contains(label, "z")
189
+}
0 190
deleted file mode 100644
... ...
@@ -1,192 +0,0 @@
1
-// +build selinux,linux
2
-
3
-package label
4
-
5
-import (
6
-	"os"
7
-	"os/user"
8
-	"strings"
9
-
10
-	"github.com/opencontainers/selinux/go-selinux"
11
-	"github.com/pkg/errors"
12
-)
13
-
14
-// Valid Label Options
15
-var validOptions = map[string]bool{
16
-	"disable":  true,
17
-	"type":     true,
18
-	"filetype": true,
19
-	"user":     true,
20
-	"role":     true,
21
-	"level":    true,
22
-}
23
-
24
-var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
25
-
26
-// InitLabels returns the process label and file labels to be used within
27
-// the container.  A list of options can be passed into this function to alter
28
-// the labels.  The labels returned will include a random MCS String, that is
29
-// guaranteed to be unique.
30
-func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
31
-	if !selinux.GetEnabled() {
32
-		return "", "", nil
33
-	}
34
-	processLabel, mountLabel := selinux.ContainerLabels()
35
-	if processLabel != "" {
36
-		defer func() {
37
-			if retErr != nil {
38
-				selinux.ReleaseLabel(mountLabel)
39
-			}
40
-		}()
41
-		pcon, err := selinux.NewContext(processLabel)
42
-		if err != nil {
43
-			return "", "", err
44
-		}
45
-		mcsLevel := pcon["level"]
46
-		mcon, err := selinux.NewContext(mountLabel)
47
-		if err != nil {
48
-			return "", "", err
49
-		}
50
-		for _, opt := range options {
51
-			if opt == "disable" {
52
-				return "", mountLabel, nil
53
-			}
54
-			if i := strings.Index(opt, ":"); i == -1 {
55
-				return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
56
-			}
57
-			con := strings.SplitN(opt, ":", 2)
58
-			if !validOptions[con[0]] {
59
-				return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
60
-			}
61
-			if con[0] == "filetype" {
62
-				mcon["type"] = con[1]
63
-				continue
64
-			}
65
-			pcon[con[0]] = con[1]
66
-			if con[0] == "level" || con[0] == "user" {
67
-				mcon[con[0]] = con[1]
68
-			}
69
-		}
70
-		if pcon.Get() != processLabel {
71
-			if pcon["level"] != mcsLevel {
72
-				selinux.ReleaseLabel(processLabel)
73
-			}
74
-			processLabel = pcon.Get()
75
-			selinux.ReserveLabel(processLabel)
76
-		}
77
-		mountLabel = mcon.Get()
78
-	}
79
-	return processLabel, mountLabel, nil
80
-}
81
-
82
-// Deprecated: The GenLabels function is only to be used during the transition
83
-// to the official API. Use InitLabels(strings.Fields(options)) instead.
84
-func GenLabels(options string) (string, string, error) {
85
-	return InitLabels(strings.Fields(options))
86
-}
87
-
88
-// SetFileLabel modifies the "path" label to the specified file label
89
-func SetFileLabel(path string, fileLabel string) error {
90
-	if !selinux.GetEnabled() || fileLabel == "" {
91
-		return nil
92
-	}
93
-	return selinux.SetFileLabel(path, fileLabel)
94
-}
95
-
96
-// SetFileCreateLabel tells the kernel the label for all files to be created
97
-func SetFileCreateLabel(fileLabel string) error {
98
-	if !selinux.GetEnabled() {
99
-		return nil
100
-	}
101
-	return selinux.SetFSCreateLabel(fileLabel)
102
-}
103
-
104
-// Relabel changes the label of path to the filelabel string.
105
-// It changes the MCS label to s0 if shared is true.
106
-// This will allow all containers to share the content.
107
-func Relabel(path string, fileLabel string, shared bool) error {
108
-	if !selinux.GetEnabled() || fileLabel == "" {
109
-		return nil
110
-	}
111
-
112
-	exclude_paths := map[string]bool{
113
-		"/":           true,
114
-		"/bin":        true,
115
-		"/boot":       true,
116
-		"/dev":        true,
117
-		"/etc":        true,
118
-		"/etc/passwd": true,
119
-		"/etc/pki":    true,
120
-		"/etc/shadow": true,
121
-		"/home":       true,
122
-		"/lib":        true,
123
-		"/lib64":      true,
124
-		"/media":      true,
125
-		"/opt":        true,
126
-		"/proc":       true,
127
-		"/root":       true,
128
-		"/run":        true,
129
-		"/sbin":       true,
130
-		"/srv":        true,
131
-		"/sys":        true,
132
-		"/tmp":        true,
133
-		"/usr":        true,
134
-		"/var":        true,
135
-		"/var/lib":    true,
136
-		"/var/log":    true,
137
-	}
138
-
139
-	if home := os.Getenv("HOME"); home != "" {
140
-		exclude_paths[home] = true
141
-	}
142
-
143
-	if sudoUser := os.Getenv("SUDO_USER"); sudoUser != "" {
144
-		if usr, err := user.Lookup(sudoUser); err == nil {
145
-			exclude_paths[usr.HomeDir] = true
146
-		}
147
-	}
148
-
149
-	if path != "/" {
150
-		path = strings.TrimSuffix(path, "/")
151
-	}
152
-	if exclude_paths[path] {
153
-		return errors.Errorf("SELinux relabeling of %s is not allowed", path)
154
-	}
155
-
156
-	if shared {
157
-		c, err := selinux.NewContext(fileLabel)
158
-		if err != nil {
159
-			return err
160
-		}
161
-
162
-		c["level"] = "s0"
163
-		fileLabel = c.Get()
164
-	}
165
-	if err := selinux.Chcon(path, fileLabel, true); err != nil {
166
-		return err
167
-	}
168
-	return nil
169
-}
170
-
171
-// DisableSecOpt returns a security opt that can disable labeling
172
-// support for future container processes
173
-// Deprecated: use selinux.DisableSecOpt
174
-var DisableSecOpt = selinux.DisableSecOpt
175
-
176
-// Validate checks that the label does not include unexpected options
177
-func Validate(label string) error {
178
-	if strings.Contains(label, "z") && strings.Contains(label, "Z") {
179
-		return ErrIncompatibleLabel
180
-	}
181
-	return nil
182
-}
183
-
184
-// RelabelNeeded checks whether the user requested a relabel
185
-func RelabelNeeded(label string) bool {
186
-	return strings.Contains(label, "z") || strings.Contains(label, "Z")
187
-}
188
-
189
-// IsShared checks that the label includes a "shared" mark
190
-func IsShared(label string) bool {
191
-	return strings.Contains(label, "z")
192
-}
... ...
@@ -1,4 +1,4 @@
1
-// +build !selinux !linux
1
+// +build !linux
2 2
 
3 3
 package label
4 4
 
... ...
@@ -1,5 +1,3 @@
1
-// +build selinux,linux
2
-
3 1
 package selinux
4 2
 
5 3
 import (
... ...
@@ -1,4 +1,4 @@
1
-// +build !selinux !linux
1
+// +build !linux
2 2
 
3 3
 package selinux
4 4
 
5 5
deleted file mode 100644
... ...
@@ -1,40 +0,0 @@
1
-// +build selinux,linux
2
-
3
-package selinux
4
-
5
-import (
6
-	"golang.org/x/sys/unix"
7
-)
8
-
9
-// lgetxattr returns a []byte slice containing the value of
10
-// an extended attribute attr set for path.
11
-func lgetxattr(path, attr string) ([]byte, error) {
12
-	// Start with a 128 length byte array
13
-	dest := make([]byte, 128)
14
-	sz, errno := doLgetxattr(path, attr, dest)
15
-	for errno == unix.ERANGE {
16
-		// Buffer too small, use zero-sized buffer to get the actual size
17
-		sz, errno = doLgetxattr(path, attr, []byte{})
18
-		if errno != nil {
19
-			return nil, errno
20
-		}
21
-
22
-		dest = make([]byte, sz)
23
-		sz, errno = doLgetxattr(path, attr, dest)
24
-	}
25
-	if errno != nil {
26
-		return nil, errno
27
-	}
28
-
29
-	return dest[:sz], nil
30
-}
31
-
32
-// doLgetxattr is a wrapper that retries on EINTR
33
-func doLgetxattr(path, attr string, dest []byte) (int, error) {
34
-	for {
35
-		sz, err := unix.Lgetxattr(path, attr, dest)
36
-		if err != unix.EINTR {
37
-			return sz, err
38
-		}
39
-	}
40
-}
41 1
new file mode 100644
... ...
@@ -0,0 +1,38 @@
0
+package selinux
1
+
2
+import (
3
+	"golang.org/x/sys/unix"
4
+)
5
+
6
+// lgetxattr returns a []byte slice containing the value of
7
+// an extended attribute attr set for path.
8
+func lgetxattr(path, attr string) ([]byte, error) {
9
+	// Start with a 128 length byte array
10
+	dest := make([]byte, 128)
11
+	sz, errno := doLgetxattr(path, attr, dest)
12
+	for errno == unix.ERANGE {
13
+		// Buffer too small, use zero-sized buffer to get the actual size
14
+		sz, errno = doLgetxattr(path, attr, []byte{})
15
+		if errno != nil {
16
+			return nil, errno
17
+		}
18
+
19
+		dest = make([]byte, sz)
20
+		sz, errno = doLgetxattr(path, attr, dest)
21
+	}
22
+	if errno != nil {
23
+		return nil, errno
24
+	}
25
+
26
+	return dest[:sz], nil
27
+}
28
+
29
+// doLgetxattr is a wrapper that retries on EINTR
30
+func doLgetxattr(path, attr string, dest []byte) (int, error) {
31
+	for {
32
+		sz, err := unix.Lgetxattr(path, attr, dest)
33
+		if err != unix.EINTR {
34
+			return sz, err
35
+		}
36
+	}
37
+}