Browse code

Merge pull request #35986 from thaJeztah/bump-containerd-1.0.1-rc1

Bump containerd to 1.0.1 (9b55aab90508bd389d7654c4baf173a981477d55)

Brian Goff authored on 2018/01/20 05:48:36
Showing 17 changed files
... ...
@@ -12,7 +12,6 @@ import (
12 12
 	"path"
13 13
 	"path/filepath"
14 14
 	"runtime"
15
-	"strconv"
16 15
 	"strings"
17 16
 
18 17
 	"github.com/docker/docker/api/types"
... ...
@@ -24,10 +23,8 @@ import (
24 24
 	"github.com/docker/docker/pkg/containerfs"
25 25
 	"github.com/docker/docker/pkg/idtools"
26 26
 	"github.com/docker/docker/pkg/stringid"
27
-	"github.com/docker/docker/pkg/symlink"
28 27
 	"github.com/docker/docker/pkg/system"
29 28
 	"github.com/docker/go-connections/nat"
30
-	lcUser "github.com/opencontainers/runc/libcontainer/user"
31 29
 	"github.com/pkg/errors"
32 30
 )
33 31
 
... ...
@@ -216,82 +213,6 @@ func (b *Builder) performCopy(state *dispatchState, inst copyInstruction) error
216 216
 	return b.exportImage(state, imageMount, runConfigWithCommentCmd)
217 217
 }
218 218
 
219
-func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
220
-	var userStr, grpStr string
221
-	parts := strings.Split(chown, ":")
222
-	if len(parts) > 2 {
223
-		return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
224
-	}
225
-	if len(parts) == 1 {
226
-		// if no group specified, use the user spec as group as well
227
-		userStr, grpStr = parts[0], parts[0]
228
-	} else {
229
-		userStr, grpStr = parts[0], parts[1]
230
-	}
231
-
232
-	passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
233
-	if err != nil {
234
-		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
235
-	}
236
-	groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
237
-	if err != nil {
238
-		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
239
-	}
240
-	uid, err := lookupUser(userStr, passwdPath)
241
-	if err != nil {
242
-		return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
243
-	}
244
-	gid, err := lookupGroup(grpStr, groupPath)
245
-	if err != nil {
246
-		return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
247
-	}
248
-
249
-	// convert as necessary because of user namespaces
250
-	chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
251
-	if err != nil {
252
-		return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
253
-	}
254
-	return chownPair, nil
255
-}
256
-
257
-func lookupUser(userStr, filepath string) (int, error) {
258
-	// if the string is actually a uid integer, parse to int and return
259
-	// as we don't need to translate with the help of files
260
-	uid, err := strconv.Atoi(userStr)
261
-	if err == nil {
262
-		return uid, nil
263
-	}
264
-	users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
265
-		return u.Name == userStr
266
-	})
267
-	if err != nil {
268
-		return 0, err
269
-	}
270
-	if len(users) == 0 {
271
-		return 0, errors.New("no such user: " + userStr)
272
-	}
273
-	return users[0].Uid, nil
274
-}
275
-
276
-func lookupGroup(groupStr, filepath string) (int, error) {
277
-	// if the string is actually a gid integer, parse to int and return
278
-	// as we don't need to translate with the help of files
279
-	gid, err := strconv.Atoi(groupStr)
280
-	if err == nil {
281
-		return gid, nil
282
-	}
283
-	groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
284
-		return g.Name == groupStr
285
-	})
286
-	if err != nil {
287
-		return 0, err
288
-	}
289
-	if len(groups) == 0 {
290
-		return 0, errors.New("no such group: " + groupStr)
291
-	}
292
-	return groups[0].Gid, nil
293
-}
294
-
295 219
 func createDestInfo(workingDir string, inst copyInstruction, imageMount *imageMount, platform string) (copyInfo, error) {
296 220
 	// Twiddle the destination when it's a relative path - meaning, make it
297 221
 	// relative to the WORKINGDIR
298 222
new file mode 100644
... ...
@@ -0,0 +1,88 @@
0
+package dockerfile
1
+
2
+import (
3
+	"path/filepath"
4
+	"strconv"
5
+	"strings"
6
+
7
+	"github.com/docker/docker/pkg/idtools"
8
+	"github.com/docker/docker/pkg/symlink"
9
+	lcUser "github.com/opencontainers/runc/libcontainer/user"
10
+	"github.com/pkg/errors"
11
+)
12
+
13
+func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
14
+	var userStr, grpStr string
15
+	parts := strings.Split(chown, ":")
16
+	if len(parts) > 2 {
17
+		return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
18
+	}
19
+	if len(parts) == 1 {
20
+		// if no group specified, use the user spec as group as well
21
+		userStr, grpStr = parts[0], parts[0]
22
+	} else {
23
+		userStr, grpStr = parts[0], parts[1]
24
+	}
25
+
26
+	passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
27
+	if err != nil {
28
+		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
29
+	}
30
+	groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
31
+	if err != nil {
32
+		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
33
+	}
34
+	uid, err := lookupUser(userStr, passwdPath)
35
+	if err != nil {
36
+		return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
37
+	}
38
+	gid, err := lookupGroup(grpStr, groupPath)
39
+	if err != nil {
40
+		return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
41
+	}
42
+
43
+	// convert as necessary because of user namespaces
44
+	chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
45
+	if err != nil {
46
+		return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
47
+	}
48
+	return chownPair, nil
49
+}
50
+
51
+func lookupUser(userStr, filepath string) (int, error) {
52
+	// if the string is actually a uid integer, parse to int and return
53
+	// as we don't need to translate with the help of files
54
+	uid, err := strconv.Atoi(userStr)
55
+	if err == nil {
56
+		return uid, nil
57
+	}
58
+	users, err := lcUser.ParsePasswdFileFilter(filepath, func(u lcUser.User) bool {
59
+		return u.Name == userStr
60
+	})
61
+	if err != nil {
62
+		return 0, err
63
+	}
64
+	if len(users) == 0 {
65
+		return 0, errors.New("no such user: " + userStr)
66
+	}
67
+	return users[0].Uid, nil
68
+}
69
+
70
+func lookupGroup(groupStr, filepath string) (int, error) {
71
+	// if the string is actually a gid integer, parse to int and return
72
+	// as we don't need to translate with the help of files
73
+	gid, err := strconv.Atoi(groupStr)
74
+	if err == nil {
75
+		return gid, nil
76
+	}
77
+	groups, err := lcUser.ParseGroupFileFilter(filepath, func(g lcUser.Group) bool {
78
+		return g.Name == groupStr
79
+	})
80
+	if err != nil {
81
+		return 0, err
82
+	}
83
+	if len(groups) == 0 {
84
+		return 0, errors.New("no such group: " + groupStr)
85
+	}
86
+	return groups[0].Gid, nil
87
+}
0 88
new file mode 100644
... ...
@@ -0,0 +1,138 @@
0
+package dockerfile
1
+
2
+import (
3
+	"os"
4
+	"path/filepath"
5
+	"testing"
6
+
7
+	"github.com/docker/docker/pkg/idtools"
8
+	"github.com/stretchr/testify/assert"
9
+	"github.com/stretchr/testify/require"
10
+)
11
+
12
+func TestChownFlagParsing(t *testing.T) {
13
+	testFiles := map[string]string{
14
+		"passwd": `root:x:0:0::/bin:/bin/false
15
+bin:x:1:1::/bin:/bin/false
16
+wwwwww:x:21:33::/bin:/bin/false
17
+unicorn:x:1001:1002::/bin:/bin/false
18
+		`,
19
+		"group": `root:x:0:
20
+bin:x:1:
21
+wwwwww:x:33:
22
+unicorn:x:1002:
23
+somegrp:x:5555:
24
+othergrp:x:6666:
25
+		`,
26
+	}
27
+	// test mappings for validating use of maps
28
+	idMaps := []idtools.IDMap{
29
+		{
30
+			ContainerID: 0,
31
+			HostID:      100000,
32
+			Size:        65536,
33
+		},
34
+	}
35
+	remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
36
+	unmapped := &idtools.IDMappings{}
37
+
38
+	contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
39
+	defer cleanup()
40
+
41
+	if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
42
+		t.Fatalf("error creating test directory: %v", err)
43
+	}
44
+
45
+	for filename, content := range testFiles {
46
+		createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644)
47
+	}
48
+
49
+	// positive tests
50
+	for _, testcase := range []struct {
51
+		name      string
52
+		chownStr  string
53
+		idMapping *idtools.IDMappings
54
+		expected  idtools.IDPair
55
+	}{
56
+		{
57
+			name:      "UIDNoMap",
58
+			chownStr:  "1",
59
+			idMapping: unmapped,
60
+			expected:  idtools.IDPair{UID: 1, GID: 1},
61
+		},
62
+		{
63
+			name:      "UIDGIDNoMap",
64
+			chownStr:  "0:1",
65
+			idMapping: unmapped,
66
+			expected:  idtools.IDPair{UID: 0, GID: 1},
67
+		},
68
+		{
69
+			name:      "UIDWithMap",
70
+			chownStr:  "0",
71
+			idMapping: remapped,
72
+			expected:  idtools.IDPair{UID: 100000, GID: 100000},
73
+		},
74
+		{
75
+			name:      "UIDGIDWithMap",
76
+			chownStr:  "1:33",
77
+			idMapping: remapped,
78
+			expected:  idtools.IDPair{UID: 100001, GID: 100033},
79
+		},
80
+		{
81
+			name:      "UserNoMap",
82
+			chownStr:  "bin:5555",
83
+			idMapping: unmapped,
84
+			expected:  idtools.IDPair{UID: 1, GID: 5555},
85
+		},
86
+		{
87
+			name:      "GroupWithMap",
88
+			chownStr:  "0:unicorn",
89
+			idMapping: remapped,
90
+			expected:  idtools.IDPair{UID: 100000, GID: 101002},
91
+		},
92
+		{
93
+			name:      "UserOnlyWithMap",
94
+			chownStr:  "unicorn",
95
+			idMapping: remapped,
96
+			expected:  idtools.IDPair{UID: 101001, GID: 101002},
97
+		},
98
+	} {
99
+		t.Run(testcase.name, func(t *testing.T) {
100
+			idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
101
+			require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
102
+			assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure")
103
+		})
104
+	}
105
+
106
+	// error tests
107
+	for _, testcase := range []struct {
108
+		name      string
109
+		chownStr  string
110
+		idMapping *idtools.IDMappings
111
+		descr     string
112
+	}{
113
+		{
114
+			name:      "BadChownFlagFormat",
115
+			chownStr:  "bob:1:555",
116
+			idMapping: unmapped,
117
+			descr:     "invalid chown string format: bob:1:555",
118
+		},
119
+		{
120
+			name:      "UserNoExist",
121
+			chownStr:  "bob",
122
+			idMapping: unmapped,
123
+			descr:     "can't find uid for user bob: no such user: bob",
124
+		},
125
+		{
126
+			name:      "GroupNoExist",
127
+			chownStr:  "root:bob",
128
+			idMapping: unmapped,
129
+			descr:     "can't find gid for group bob: no such group: bob",
130
+		},
131
+	} {
132
+		t.Run(testcase.name, func(t *testing.T) {
133
+			_, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
134
+			assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match")
135
+		})
136
+	}
137
+}
... ...
@@ -2,8 +2,6 @@ package dockerfile
2 2
 
3 3
 import (
4 4
 	"fmt"
5
-	"os"
6
-	"path/filepath"
7 5
 	"runtime"
8 6
 	"testing"
9 7
 
... ...
@@ -13,7 +11,6 @@ import (
13 13
 	"github.com/docker/docker/builder"
14 14
 	"github.com/docker/docker/builder/remotecontext"
15 15
 	"github.com/docker/docker/pkg/archive"
16
-	"github.com/docker/docker/pkg/idtools"
17 16
 	"github.com/docker/go-connections/nat"
18 17
 	"github.com/stretchr/testify/assert"
19 18
 	"github.com/stretchr/testify/require"
... ...
@@ -171,130 +168,3 @@ func TestDeepCopyRunConfig(t *testing.T) {
171 171
 	copy.Shell[0] = "sh"
172 172
 	assert.Equal(t, fullMutableRunConfig(), runConfig)
173 173
 }
174
-
175
-func TestChownFlagParsing(t *testing.T) {
176
-	testFiles := map[string]string{
177
-		"passwd": `root:x:0:0::/bin:/bin/false
178
-bin:x:1:1::/bin:/bin/false
179
-wwwwww:x:21:33::/bin:/bin/false
180
-unicorn:x:1001:1002::/bin:/bin/false
181
-		`,
182
-		"group": `root:x:0:
183
-bin:x:1:
184
-wwwwww:x:33:
185
-unicorn:x:1002:
186
-somegrp:x:5555:
187
-othergrp:x:6666:
188
-		`,
189
-	}
190
-	// test mappings for validating use of maps
191
-	idMaps := []idtools.IDMap{
192
-		{
193
-			ContainerID: 0,
194
-			HostID:      100000,
195
-			Size:        65536,
196
-		},
197
-	}
198
-	remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
199
-	unmapped := &idtools.IDMappings{}
200
-
201
-	contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
202
-	defer cleanup()
203
-
204
-	if err := os.Mkdir(filepath.Join(contextDir, "etc"), 0755); err != nil {
205
-		t.Fatalf("error creating test directory: %v", err)
206
-	}
207
-
208
-	for filename, content := range testFiles {
209
-		createTestTempFile(t, filepath.Join(contextDir, "etc"), filename, content, 0644)
210
-	}
211
-
212
-	// positive tests
213
-	for _, testcase := range []struct {
214
-		name      string
215
-		chownStr  string
216
-		idMapping *idtools.IDMappings
217
-		expected  idtools.IDPair
218
-	}{
219
-		{
220
-			name:      "UIDNoMap",
221
-			chownStr:  "1",
222
-			idMapping: unmapped,
223
-			expected:  idtools.IDPair{UID: 1, GID: 1},
224
-		},
225
-		{
226
-			name:      "UIDGIDNoMap",
227
-			chownStr:  "0:1",
228
-			idMapping: unmapped,
229
-			expected:  idtools.IDPair{UID: 0, GID: 1},
230
-		},
231
-		{
232
-			name:      "UIDWithMap",
233
-			chownStr:  "0",
234
-			idMapping: remapped,
235
-			expected:  idtools.IDPair{UID: 100000, GID: 100000},
236
-		},
237
-		{
238
-			name:      "UIDGIDWithMap",
239
-			chownStr:  "1:33",
240
-			idMapping: remapped,
241
-			expected:  idtools.IDPair{UID: 100001, GID: 100033},
242
-		},
243
-		{
244
-			name:      "UserNoMap",
245
-			chownStr:  "bin:5555",
246
-			idMapping: unmapped,
247
-			expected:  idtools.IDPair{UID: 1, GID: 5555},
248
-		},
249
-		{
250
-			name:      "GroupWithMap",
251
-			chownStr:  "0:unicorn",
252
-			idMapping: remapped,
253
-			expected:  idtools.IDPair{UID: 100000, GID: 101002},
254
-		},
255
-		{
256
-			name:      "UserOnlyWithMap",
257
-			chownStr:  "unicorn",
258
-			idMapping: remapped,
259
-			expected:  idtools.IDPair{UID: 101001, GID: 101002},
260
-		},
261
-	} {
262
-		t.Run(testcase.name, func(t *testing.T) {
263
-			idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
264
-			require.NoError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
265
-			assert.Equal(t, testcase.expected, idPair, "chown flag mapping failure")
266
-		})
267
-	}
268
-
269
-	// error tests
270
-	for _, testcase := range []struct {
271
-		name      string
272
-		chownStr  string
273
-		idMapping *idtools.IDMappings
274
-		descr     string
275
-	}{
276
-		{
277
-			name:      "BadChownFlagFormat",
278
-			chownStr:  "bob:1:555",
279
-			idMapping: unmapped,
280
-			descr:     "invalid chown string format: bob:1:555",
281
-		},
282
-		{
283
-			name:      "UserNoExist",
284
-			chownStr:  "bob",
285
-			idMapping: unmapped,
286
-			descr:     "can't find uid for user bob: no such user: bob",
287
-		},
288
-		{
289
-			name:      "GroupNoExist",
290
-			chownStr:  "root:bob",
291
-			idMapping: unmapped,
292
-			descr:     "can't find gid for group bob: no such group: bob",
293
-		},
294
-	} {
295
-		t.Run(testcase.name, func(t *testing.T) {
296
-			_, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
297
-			assert.EqualError(t, err, testcase.descr, "Expected error string doesn't match")
298
-		})
299
-	}
300
-}
301 174
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+package dockerfile
1
+
2
+import "github.com/docker/docker/pkg/idtools"
3
+
4
+func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
5
+	return idMappings.RootPair(), nil
6
+}
... ...
@@ -3,12 +3,12 @@
3 3
 TOMLV_COMMIT=9baf8a8a9f2ed20a8e54160840c492f937eeaf9a
4 4
 
5 5
 # When updating RUNC_COMMIT, also update runc in vendor.conf accordingly
6
-RUNC_COMMIT=b2567b37d7b75eb4cf325b77297b140ea686ce8f
6
+RUNC_COMMIT=7f24b40cc5423969b4554ef04ba0b00e2b4ba010
7 7
 
8 8
 # containerd is also pinned in vendor.conf. When updating the binary
9 9
 # version you may also need to update the vendor version to pick up bug
10 10
 # fixes or new APIs.
11
-CONTAINERD_COMMIT=89623f28b87a6004d4b785663257362d1658a729 # v1.0.0
11
+CONTAINERD_COMMIT=9b55aab90508bd389d7654c4baf173a981477d55 # v1.0.1
12 12
 TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574
13 13
 LIBNETWORK_COMMIT=7b2b1feb1de4817d522cc372af149ff48d25028e
14 14
 VNDR_COMMIT=a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384
... ...
@@ -36,7 +36,6 @@ import (
36 36
 	"github.com/docker/libnetwork/types"
37 37
 	"github.com/go-check/check"
38 38
 	"github.com/gotestyourself/gotestyourself/icmd"
39
-	libcontainerUser "github.com/opencontainers/runc/libcontainer/user"
40 39
 	"golang.org/x/net/context"
41 40
 )
42 41
 
... ...
@@ -751,7 +750,7 @@ func (s *DockerSuite) TestRunUserByIDBig(c *check.C) {
751 751
 	if err == nil {
752 752
 		c.Fatal("No error, but must be.", out)
753 753
 	}
754
-	if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
754
+	if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
755 755
 		c.Fatalf("expected error about uids range, got %s", out)
756 756
 	}
757 757
 }
... ...
@@ -764,7 +763,7 @@ func (s *DockerSuite) TestRunUserByIDNegative(c *check.C) {
764 764
 	if err == nil {
765 765
 		c.Fatal("No error, but must be.", out)
766 766
 	}
767
-	if !strings.Contains(strings.ToUpper(out), strings.ToUpper(libcontainerUser.ErrRange.Error())) {
767
+	if !strings.Contains(strings.ToLower(out), "uids and gids must be in range") {
768 768
 		c.Fatalf("expected error about uids range, got %s", out)
769 769
 	}
770 770
 }
... ...
@@ -66,7 +66,7 @@ github.com/pborman/uuid v1.0
66 66
 google.golang.org/grpc v1.3.0
67 67
 
68 68
 # When updating, also update RUNC_COMMIT in hack/dockerfile/binaries-commits accordingly
69
-github.com/opencontainers/runc b2567b37d7b75eb4cf325b77297b140ea686ce8f
69
+github.com/opencontainers/runc 7f24b40cc5423969b4554ef04ba0b00e2b4ba010
70 70
 github.com/opencontainers/runtime-spec v1.0.1
71 71
 github.com/opencontainers/image-spec v1.0.1
72 72
 github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0
... ...
@@ -56,7 +56,7 @@ make BUILDTAGS='seccomp apparmor'
56 56
 |-----------|------------------------------------|-------------|
57 57
 | seccomp   | Syscall filtering                  | libseccomp  |
58 58
 | selinux   | selinux process and mount labeling | <none>      |
59
-| apparmor  | apparmor profile support           | libapparmor |
59
+| apparmor  | apparmor profile support           | <none>      |
60 60
 | ambient   | ambient capability support         | kernel 4.3  |
61 61
 
62 62
 
... ...
@@ -2,15 +2,10 @@
2 2
 
3 3
 package apparmor
4 4
 
5
-// #cgo LDFLAGS: -lapparmor
6
-// #include <sys/apparmor.h>
7
-// #include <stdlib.h>
8
-import "C"
9 5
 import (
10 6
 	"fmt"
11 7
 	"io/ioutil"
12 8
 	"os"
13
-	"unsafe"
14 9
 )
15 10
 
16 11
 // IsEnabled returns true if apparmor is enabled for the host.
... ...
@@ -24,16 +19,36 @@ func IsEnabled() bool {
24 24
 	return false
25 25
 }
26 26
 
27
+func setprocattr(attr, value string) error {
28
+	// Under AppArmor you can only change your own attr, so use /proc/self/
29
+	// instead of /proc/<tid>/ like libapparmor does
30
+	path := fmt.Sprintf("/proc/self/attr/%s", attr)
31
+
32
+	f, err := os.OpenFile(path, os.O_WRONLY, 0)
33
+	if err != nil {
34
+		return err
35
+	}
36
+	defer f.Close()
37
+
38
+	_, err = fmt.Fprintf(f, "%s", value)
39
+	return err
40
+}
41
+
42
+// changeOnExec reimplements aa_change_onexec from libapparmor in Go
43
+func changeOnExec(name string) error {
44
+	value := "exec " + name
45
+	if err := setprocattr("exec", value); err != nil {
46
+		return fmt.Errorf("apparmor failed to apply profile: %s", err)
47
+	}
48
+	return nil
49
+}
50
+
27 51
 // ApplyProfile will apply the profile with the specified name to the process after
28 52
 // the next exec.
29 53
 func ApplyProfile(name string) error {
30 54
 	if name == "" {
31 55
 		return nil
32 56
 	}
33
-	cName := C.CString(name)
34
-	defer C.free(unsafe.Pointer(cName))
35
-	if _, err := C.aa_change_onexec(cName); err != nil {
36
-		return fmt.Errorf("apparmor failed to apply profile: %s", err)
37
-	}
38
-	return nil
57
+
58
+	return changeOnExec(name)
39 59
 }
40 60
deleted file mode 100644
... ...
@@ -1,6 +0,0 @@
1
-// +build !windows,!linux,!freebsd
2
-
3
-package configs
4
-
5
-type Cgroup struct {
6
-}
... ...
@@ -1,4 +1,4 @@
1
-// +build linux freebsd
1
+// +build linux
2 2
 
3 3
 package configs
4 4
 
5 5
new file mode 100644
... ...
@@ -0,0 +1,104 @@
0
+package devices
1
+
2
+import (
3
+	"errors"
4
+	"io/ioutil"
5
+	"os"
6
+	"path/filepath"
7
+
8
+	"github.com/opencontainers/runc/libcontainer/configs"
9
+
10
+	"golang.org/x/sys/unix"
11
+)
12
+
13
+var (
14
+	ErrNotADevice = errors.New("not a device node")
15
+)
16
+
17
+// Testing dependencies
18
+var (
19
+	unixLstat     = unix.Lstat
20
+	ioutilReadDir = ioutil.ReadDir
21
+)
22
+
23
+// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct.
24
+func DeviceFromPath(path, permissions string) (*configs.Device, error) {
25
+	var stat unix.Stat_t
26
+	err := unixLstat(path, &stat)
27
+	if err != nil {
28
+		return nil, err
29
+	}
30
+
31
+	var (
32
+		devNumber = stat.Rdev
33
+		major     = unix.Major(devNumber)
34
+	)
35
+	if major == 0 {
36
+		return nil, ErrNotADevice
37
+	}
38
+
39
+	var (
40
+		devType rune
41
+		mode    = stat.Mode
42
+	)
43
+	switch {
44
+	case mode&unix.S_IFBLK == unix.S_IFBLK:
45
+		devType = 'b'
46
+	case mode&unix.S_IFCHR == unix.S_IFCHR:
47
+		devType = 'c'
48
+	}
49
+	return &configs.Device{
50
+		Type:        devType,
51
+		Path:        path,
52
+		Major:       int64(major),
53
+		Minor:       int64(unix.Minor(devNumber)),
54
+		Permissions: permissions,
55
+		FileMode:    os.FileMode(mode),
56
+		Uid:         stat.Uid,
57
+		Gid:         stat.Gid,
58
+	}, nil
59
+}
60
+
61
+func HostDevices() ([]*configs.Device, error) {
62
+	return getDevices("/dev")
63
+}
64
+
65
+func getDevices(path string) ([]*configs.Device, error) {
66
+	files, err := ioutilReadDir(path)
67
+	if err != nil {
68
+		return nil, err
69
+	}
70
+	out := []*configs.Device{}
71
+	for _, f := range files {
72
+		switch {
73
+		case f.IsDir():
74
+			switch f.Name() {
75
+			// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
76
+			case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
77
+				continue
78
+			default:
79
+				sub, err := getDevices(filepath.Join(path, f.Name()))
80
+				if err != nil {
81
+					return nil, err
82
+				}
83
+
84
+				out = append(out, sub...)
85
+				continue
86
+			}
87
+		case f.Name() == "console":
88
+			continue
89
+		}
90
+		device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
91
+		if err != nil {
92
+			if err == ErrNotADevice {
93
+				continue
94
+			}
95
+			if os.IsNotExist(err) {
96
+				continue
97
+			}
98
+			return nil, err
99
+		}
100
+		out = append(out, device)
101
+	}
102
+	return out, nil
103
+}
0 104
deleted file mode 100644
... ...
@@ -1,104 +0,0 @@
1
-package devices
2
-
3
-import (
4
-	"errors"
5
-	"io/ioutil"
6
-	"os"
7
-	"path/filepath"
8
-
9
-	"github.com/opencontainers/runc/libcontainer/configs"
10
-
11
-	"golang.org/x/sys/unix"
12
-)
13
-
14
-var (
15
-	ErrNotADevice = errors.New("not a device node")
16
-)
17
-
18
-// Testing dependencies
19
-var (
20
-	unixLstat     = unix.Lstat
21
-	ioutilReadDir = ioutil.ReadDir
22
-)
23
-
24
-// Given the path to a device and its cgroup_permissions(which cannot be easily queried) look up the information about a linux device and return that information as a Device struct.
25
-func DeviceFromPath(path, permissions string) (*configs.Device, error) {
26
-	var stat unix.Stat_t
27
-	err := unixLstat(path, &stat)
28
-	if err != nil {
29
-		return nil, err
30
-	}
31
-
32
-	var (
33
-		devNumber = stat.Rdev
34
-		major     = unix.Major(devNumber)
35
-	)
36
-	if major == 0 {
37
-		return nil, ErrNotADevice
38
-	}
39
-
40
-	var (
41
-		devType rune
42
-		mode    = stat.Mode
43
-	)
44
-	switch {
45
-	case mode&unix.S_IFBLK == unix.S_IFBLK:
46
-		devType = 'b'
47
-	case mode&unix.S_IFCHR == unix.S_IFCHR:
48
-		devType = 'c'
49
-	}
50
-	return &configs.Device{
51
-		Type:        devType,
52
-		Path:        path,
53
-		Major:       int64(major),
54
-		Minor:       int64(unix.Minor(devNumber)),
55
-		Permissions: permissions,
56
-		FileMode:    os.FileMode(mode),
57
-		Uid:         stat.Uid,
58
-		Gid:         stat.Gid,
59
-	}, nil
60
-}
61
-
62
-func HostDevices() ([]*configs.Device, error) {
63
-	return getDevices("/dev")
64
-}
65
-
66
-func getDevices(path string) ([]*configs.Device, error) {
67
-	files, err := ioutilReadDir(path)
68
-	if err != nil {
69
-		return nil, err
70
-	}
71
-	out := []*configs.Device{}
72
-	for _, f := range files {
73
-		switch {
74
-		case f.IsDir():
75
-			switch f.Name() {
76
-			// ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
77
-			case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
78
-				continue
79
-			default:
80
-				sub, err := getDevices(filepath.Join(path, f.Name()))
81
-				if err != nil {
82
-					return nil, err
83
-				}
84
-
85
-				out = append(out, sub...)
86
-				continue
87
-			}
88
-		case f.Name() == "console":
89
-			continue
90
-		}
91
-		device, err := DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
92
-		if err != nil {
93
-			if err == ErrNotADevice {
94
-				continue
95
-			}
96
-			if os.IsNotExist(err) {
97
-				continue
98
-			}
99
-			return nil, err
100
-		}
101
-		out = append(out, device)
102
-	}
103
-	return out, nil
104
-}
105 1
deleted file mode 100644
... ...
@@ -1,3 +0,0 @@
1
-// +build !linux
2
-
3
-package devices
... ...
@@ -1,4 +1,4 @@
1
-// +build cgo,linux cgo,freebsd
1
+// +build cgo,linux
2 2
 
3 3
 package system
4 4
 
5 5
deleted file mode 100644
... ...
@@ -1,38 +0,0 @@
1
-// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!solaris
2
-
3
-package user
4
-
5
-import (
6
-	"io"
7
-	"syscall"
8
-)
9
-
10
-func GetPasswdPath() (string, error) {
11
-	return "", ErrUnsupported
12
-}
13
-
14
-func GetPasswd() (io.ReadCloser, error) {
15
-	return nil, ErrUnsupported
16
-}
17
-
18
-func GetGroupPath() (string, error) {
19
-	return "", ErrUnsupported
20
-}
21
-
22
-func GetGroup() (io.ReadCloser, error) {
23
-	return nil, ErrUnsupported
24
-}
25
-
26
-// CurrentUser looks up the current user by their user id in /etc/passwd. If the
27
-// user cannot be found (or there is no /etc/passwd file on the filesystem),
28
-// then CurrentUser returns an error.
29
-func CurrentUser() (User, error) {
30
-	return LookupUid(syscall.Getuid())
31
-}
32
-
33
-// CurrentGroup looks up the current user's group by their primary group id's
34
-// entry in /etc/passwd. If the group cannot be found (or there is no
35
-// /etc/group file on the filesystem), then CurrentGroup returns an error.
36
-func CurrentGroup() (Group, error) {
37
-	return LookupGid(syscall.Getgid())
38
-}