Browse code

dockerinit: drop capabilities

Drop capabilities in dockerinit instead of with lxc utils, since
libvirt-lxc doesn't support it.

This will also be needed for machine container mode, since dockerinit
needs CAP_SYS_ADMIN to setup /dev/console correctly.

Josh Poimboeuf authored on 2013/10/31 12:24:47
Showing 11 changed files
... ...
@@ -594,6 +594,10 @@ func (container *Container) Start() (err error) {
594 594
 		env = append(env, "TERM=xterm")
595 595
 	}
596 596
 
597
+	if container.hostConfig.Privileged {
598
+		params = append(params, "-privileged")
599
+	}
600
+
597 601
 	// Init any links between the parent and children
598 602
 	runtime := container.runtime
599 603
 
... ...
@@ -27,6 +27,8 @@ git_clone github.com/gorilla/context/ 708054d61e5
27 27
 
28 28
 git_clone github.com/gorilla/mux/ 9b36453141c
29 29
 
30
+git_clone github.com/syndtr/gocapability 3454319be2
31
+
30 32
 # Docker requires code.google.com/p/go.net/websocket
31 33
 PKG=code.google.com/p/go.net REV=84a4013f96e0
32 34
 (
... ...
@@ -110,18 +110,11 @@ lxc.mount.entry = {{escapeFstabSpaces $realPath}} {{escapeFstabSpaces $ROOTFS}}/
110 110
 {{end}}
111 111
 
112 112
 {{if (getHostConfig .).Privileged}}
113
-# retain all capabilities; no lxc.cap.drop line
114 113
 {{if (getCapabilities .).AppArmor}}
115 114
 lxc.aa_profile = unconfined
116 115
 {{else}}
117 116
 #lxc.aa_profile = unconfined
118 117
 {{end}}
119
-{{else}}
120
-# drop linux capabilities (apply mainly to the user root in the container)
121
-#  (Note: 'lxc.cap.keep' is coming soon and should replace this under the
122
-#         security principle 'deny all unless explicitly permitted', see
123
-#         http://sourceforge.net/mailarchive/message.php?msg_id=31054627 )
124
-lxc.cap.drop = audit_control audit_write mac_admin mac_override mknod setpcap sys_admin sys_module sys_nice sys_pacct sys_rawio sys_resource sys_time sys_tty_config
125 118
 {{end}}
126 119
 
127 120
 # limits
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"fmt"
7 7
 	"github.com/dotcloud/docker/netlink"
8 8
 	"github.com/dotcloud/docker/utils"
9
+	"github.com/syndtr/gocapability/capability"
9 10
 	"io/ioutil"
10 11
 	"log"
11 12
 	"net"
... ...
@@ -17,11 +18,12 @@ import (
17 17
 )
18 18
 
19 19
 type DockerInitArgs struct {
20
-	user    string
21
-	gateway string
22
-	workDir string
23
-	env     []string
24
-	args    []string
20
+	user       string
21
+	gateway    string
22
+	workDir    string
23
+	privileged bool
24
+	env        []string
25
+	args       []string
25 26
 }
26 27
 
27 28
 // Setup networking
... ...
@@ -82,6 +84,42 @@ func changeUser(args *DockerInitArgs) error {
82 82
 	return nil
83 83
 }
84 84
 
85
+func setupCapabilities(args *DockerInitArgs) error {
86
+
87
+	if args.privileged {
88
+		return nil
89
+	}
90
+
91
+	drop := []capability.Cap{
92
+		capability.CAP_SETPCAP,
93
+		capability.CAP_SYS_MODULE,
94
+		capability.CAP_SYS_RAWIO,
95
+		capability.CAP_SYS_PACCT,
96
+		capability.CAP_SYS_ADMIN,
97
+		capability.CAP_SYS_NICE,
98
+		capability.CAP_SYS_RESOURCE,
99
+		capability.CAP_SYS_TIME,
100
+		capability.CAP_SYS_TTY_CONFIG,
101
+		capability.CAP_MKNOD,
102
+		capability.CAP_AUDIT_WRITE,
103
+		capability.CAP_AUDIT_CONTROL,
104
+		capability.CAP_MAC_OVERRIDE,
105
+		capability.CAP_MAC_ADMIN,
106
+	}
107
+
108
+	c, err := capability.NewPid(os.Getpid())
109
+	if err != nil {
110
+		return err
111
+	}
112
+
113
+	c.Unset(capability.CAPS|capability.BOUNDS, drop...)
114
+
115
+	if err := c.Apply(capability.CAPS | capability.BOUNDS); err != nil {
116
+		return err
117
+	}
118
+	return nil
119
+}
120
+
85 121
 // Clear environment pollution introduced by lxc-start
86 122
 func setupEnv(args *DockerInitArgs) {
87 123
 	os.Clearenv()
... ...
@@ -101,6 +139,10 @@ func executeProgram(args *DockerInitArgs) error {
101 101
 		return err
102 102
 	}
103 103
 
104
+	if err := setupCapabilities(args); err != nil {
105
+		return err
106
+	}
107
+
104 108
 	if err := setupWorkingDirectory(args); err != nil {
105 109
 		return err
106 110
 	}
... ...
@@ -136,6 +178,7 @@ func SysInit() {
136 136
 	user := flag.String("u", "", "username or uid")
137 137
 	gateway := flag.String("g", "", "gateway address")
138 138
 	workDir := flag.String("w", "", "workdir")
139
+	privileged := flag.Bool("privileged", false, "privileged mode")
139 140
 	flag.Parse()
140 141
 
141 142
 	// Get env
... ...
@@ -149,11 +192,12 @@ func SysInit() {
149 149
 	}
150 150
 
151 151
 	args := &DockerInitArgs{
152
-		user:    *user,
153
-		gateway: *gateway,
154
-		workDir: *workDir,
155
-		env:     env,
156
-		args:    flag.Args(),
152
+		user:       *user,
153
+		gateway:    *gateway,
154
+		workDir:    *workDir,
155
+		privileged: *privileged,
156
+		env:        env,
157
+		args:       flag.Args(),
157 158
 	}
158 159
 
159 160
 	if err := executeProgram(args); err != nil {
160 161
new file mode 100644
... ...
@@ -0,0 +1,24 @@
0
+Copyright 2013 Suryandaru Triandana <syndtr@gmail.com>
1
+All rights reserved.
2
+
3
+Redistribution and use in source and binary forms, with or without
4
+modification, are permitted provided that the following conditions are
5
+met:
6
+
7
+    * Redistributions of source code must retain the above copyright
8
+notice, this list of conditions and the following disclaimer.
9
+    * Redistributions in binary form must reproduce the above copyright
10
+notice, this list of conditions and the following disclaimer in the
11
+documentation and/or other materials provided with the distribution.
12
+
13
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 24
new file mode 100644
... ...
@@ -0,0 +1,71 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+// Package capability provides utilities for manipulating POSIX capabilities.
7
+package capability
8
+
9
+type Capabilities interface {
10
+	// Get check whether a capability present in the given
11
+	// capabilities set. The 'which' value should be one of EFFECTIVE,
12
+	// PERMITTED, INHERITABLE or BOUNDING.
13
+	Get(which CapType, what Cap) bool
14
+
15
+	// Empty check whether all capability bits of the given capabilities
16
+	// set are zero. The 'which' value should be one of EFFECTIVE,
17
+	// PERMITTED, INHERITABLE or BOUNDING.
18
+	Empty(which CapType) bool
19
+
20
+	// Full check whether all capability bits of the given capabilities
21
+	// set are one. The 'which' value should be one of EFFECTIVE,
22
+	// PERMITTED, INHERITABLE or BOUNDING.
23
+	Full(which CapType) bool
24
+
25
+	// Set sets capabilities of the given capabilities sets. The
26
+	// 'which' value should be one or combination (OR'ed) of EFFECTIVE,
27
+	// PERMITTED, INHERITABLE or BOUNDING.
28
+	Set(which CapType, caps ...Cap)
29
+
30
+	// Unset unsets capabilities of the given capabilities sets. The
31
+	// 'which' value should be one or combination (OR'ed) of EFFECTIVE,
32
+	// PERMITTED, INHERITABLE or BOUNDING.
33
+	Unset(which CapType, caps ...Cap)
34
+
35
+	// Fill sets all bits of the given capabilities kind to one. The
36
+	// 'kind' value should be one or combination (OR'ed) of CAPS or
37
+	// BOUNDS.
38
+	Fill(kind CapType)
39
+
40
+	// Clear sets all bits of the given capabilities kind to zero. The
41
+	// 'kind' value should be one or combination (OR'ed) of CAPS or
42
+	// BOUNDS.
43
+	Clear(kind CapType)
44
+
45
+	// String return current capabilities state of the given capabilities
46
+	// set as string. The 'which' value should be one of EFFECTIVE,
47
+	// PERMITTED, INHERITABLE or BOUNDING.
48
+	StringCap(which CapType) string
49
+
50
+	// String return current capabilities state as string.
51
+	String() string
52
+
53
+	// Load load actual capabilities value. This will overwrite all
54
+	// outstanding changes.
55
+	Load() error
56
+
57
+	// Apply apply the capabilities settings, so all changes will take
58
+	// effect.
59
+	Apply(kind CapType) error
60
+}
61
+
62
+// NewPid create new initialized Capabilities object for given pid.
63
+func NewPid(pid int) (Capabilities, error) {
64
+	return newPid(pid)
65
+}
66
+
67
+// NewFile create new initialized Capabilities object for given named file.
68
+func NewFile(name string) (Capabilities, error) {
69
+	return newFile(name)
70
+}
0 71
new file mode 100644
... ...
@@ -0,0 +1,561 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+package capability
7
+
8
+import (
9
+	"bufio"
10
+	"errors"
11
+	"fmt"
12
+	"io"
13
+	"os"
14
+	"strings"
15
+	"syscall"
16
+)
17
+
18
+var errUnknownVers = errors.New("unknown capability version")
19
+
20
+const (
21
+	linuxCapVer1 = 0x19980330
22
+	linuxCapVer2 = 0x20071026
23
+	linuxCapVer3 = 0x20080522
24
+)
25
+
26
+var capVers uint32
27
+
28
+func init() {
29
+	var hdr capHeader
30
+	capget(&hdr, nil)
31
+	capVers = hdr.version
32
+}
33
+
34
+func mkStringCap(c Capabilities, which CapType) (ret string) {
35
+	for i, first := Cap(0), true; i <= CAP_LAST_CAP; i++ {
36
+		if !c.Get(which, i) {
37
+			continue
38
+		}
39
+		if first {
40
+			first = false
41
+		} else {
42
+			ret += ", "
43
+		}
44
+		ret += i.String()
45
+	}
46
+	return
47
+}
48
+
49
+func mkString(c Capabilities, max CapType) (ret string) {
50
+	ret = "{"
51
+	for i := CapType(1); i <= max; i <<= 1 {
52
+		ret += " " + i.String() + "=\""
53
+		if c.Empty(i) {
54
+			ret += "empty"
55
+		} else if c.Full(i) {
56
+			ret += "full"
57
+		} else {
58
+			ret += c.StringCap(i)
59
+		}
60
+		ret += "\""
61
+	}
62
+	ret += " }"
63
+	return
64
+}
65
+
66
+func newPid(pid int) (c Capabilities, err error) {
67
+	switch capVers {
68
+	case linuxCapVer1:
69
+		p := new(capsV1)
70
+		p.hdr.version = capVers
71
+		p.hdr.pid = pid
72
+		c = p
73
+	case linuxCapVer2, linuxCapVer3:
74
+		p := new(capsV3)
75
+		p.hdr.version = capVers
76
+		p.hdr.pid = pid
77
+		c = p
78
+	default:
79
+		err = errUnknownVers
80
+		return
81
+	}
82
+	err = c.Load()
83
+	if err != nil {
84
+		c = nil
85
+	}
86
+	return
87
+}
88
+
89
+type capsV1 struct {
90
+	hdr  capHeader
91
+	data capData
92
+}
93
+
94
+func (c *capsV1) Get(which CapType, what Cap) bool {
95
+	if what > 32 {
96
+		return false
97
+	}
98
+
99
+	switch which {
100
+	case EFFECTIVE:
101
+		return (1<<uint(what))&c.data.effective != 0
102
+	case PERMITTED:
103
+		return (1<<uint(what))&c.data.permitted != 0
104
+	case INHERITABLE:
105
+		return (1<<uint(what))&c.data.inheritable != 0
106
+	}
107
+
108
+	return false
109
+}
110
+
111
+func (c *capsV1) getData(which CapType) (ret uint32) {
112
+	switch which {
113
+	case EFFECTIVE:
114
+		ret = c.data.effective
115
+	case PERMITTED:
116
+		ret = c.data.permitted
117
+	case INHERITABLE:
118
+		ret = c.data.inheritable
119
+	}
120
+	return
121
+}
122
+
123
+func (c *capsV1) Empty(which CapType) bool {
124
+	return c.getData(which) == 0
125
+}
126
+
127
+func (c *capsV1) Full(which CapType) bool {
128
+	return (c.getData(which) & 0x7fffffff) == 0x7fffffff
129
+}
130
+
131
+func (c *capsV1) Set(which CapType, caps ...Cap) {
132
+	for _, what := range caps {
133
+		if what > 32 {
134
+			continue
135
+		}
136
+
137
+		if which&EFFECTIVE != 0 {
138
+			c.data.effective |= 1 << uint(what)
139
+		}
140
+		if which&PERMITTED != 0 {
141
+			c.data.permitted |= 1 << uint(what)
142
+		}
143
+		if which&INHERITABLE != 0 {
144
+			c.data.inheritable |= 1 << uint(what)
145
+		}
146
+	}
147
+}
148
+
149
+func (c *capsV1) Unset(which CapType, caps ...Cap) {
150
+	for _, what := range caps {
151
+		if what > 32 {
152
+			continue
153
+		}
154
+
155
+		if which&EFFECTIVE != 0 {
156
+			c.data.effective &= ^(1 << uint(what))
157
+		}
158
+		if which&PERMITTED != 0 {
159
+			c.data.permitted &= ^(1 << uint(what))
160
+		}
161
+		if which&INHERITABLE != 0 {
162
+			c.data.inheritable &= ^(1 << uint(what))
163
+		}
164
+	}
165
+}
166
+
167
+func (c *capsV1) Fill(kind CapType) {
168
+	if kind&CAPS == CAPS {
169
+		c.data.effective = 0x7fffffff
170
+		c.data.permitted = 0x7fffffff
171
+		c.data.inheritable = 0
172
+	}
173
+}
174
+
175
+func (c *capsV1) Clear(kind CapType) {
176
+	if kind&CAPS == CAPS {
177
+		c.data.effective = 0
178
+		c.data.permitted = 0
179
+		c.data.inheritable = 0
180
+	}
181
+}
182
+
183
+func (c *capsV1) StringCap(which CapType) (ret string) {
184
+	return mkStringCap(c, which)
185
+}
186
+
187
+func (c *capsV1) String() (ret string) {
188
+	return mkString(c, BOUNDING)
189
+}
190
+
191
+func (c *capsV1) Load() (err error) {
192
+	return capget(&c.hdr, &c.data)
193
+}
194
+
195
+func (c *capsV1) Apply(kind CapType) error {
196
+	if kind&CAPS == CAPS {
197
+		return capset(&c.hdr, &c.data)
198
+	}
199
+	return nil
200
+}
201
+
202
+type capsV3 struct {
203
+	hdr    capHeader
204
+	data   [2]capData
205
+	bounds [2]uint32
206
+}
207
+
208
+func (c *capsV3) Get(which CapType, what Cap) bool {
209
+	var i uint
210
+	if what > 31 {
211
+		i = uint(what) >> 5
212
+		what %= 32
213
+	}
214
+
215
+	switch which {
216
+	case EFFECTIVE:
217
+		return (1<<uint(what))&c.data[i].effective != 0
218
+	case PERMITTED:
219
+		return (1<<uint(what))&c.data[i].permitted != 0
220
+	case INHERITABLE:
221
+		return (1<<uint(what))&c.data[i].inheritable != 0
222
+	case BOUNDING:
223
+		return (1<<uint(what))&c.bounds[i] != 0
224
+	}
225
+
226
+	return false
227
+}
228
+
229
+func (c *capsV3) getData(which CapType, dest []uint32) {
230
+	switch which {
231
+	case EFFECTIVE:
232
+		dest[0] = c.data[0].effective
233
+		dest[1] = c.data[1].effective
234
+	case PERMITTED:
235
+		dest[0] = c.data[0].permitted
236
+		dest[1] = c.data[1].permitted
237
+	case INHERITABLE:
238
+		dest[0] = c.data[0].inheritable
239
+		dest[1] = c.data[1].inheritable
240
+	case BOUNDING:
241
+		dest[0] = c.bounds[0]
242
+		dest[1] = c.bounds[1]
243
+	}
244
+}
245
+
246
+func (c *capsV3) Empty(which CapType) bool {
247
+	var data [2]uint32
248
+	c.getData(which, data[:])
249
+	return data[0] == 0 && data[1] == 0
250
+}
251
+
252
+func (c *capsV3) Full(which CapType) bool {
253
+	var data [2]uint32
254
+	c.getData(which, data[:])
255
+	if (data[0] & 0xffffffff) != 0xffffffff {
256
+		return false
257
+	}
258
+	return (data[1] & capUpperMask) == capUpperMask
259
+}
260
+
261
+func (c *capsV3) Set(which CapType, caps ...Cap) {
262
+	for _, what := range caps {
263
+		var i uint
264
+		if what > 31 {
265
+			i = uint(what) >> 5
266
+			what %= 32
267
+		}
268
+
269
+		if which&EFFECTIVE != 0 {
270
+			c.data[i].effective |= 1 << uint(what)
271
+		}
272
+		if which&PERMITTED != 0 {
273
+			c.data[i].permitted |= 1 << uint(what)
274
+		}
275
+		if which&INHERITABLE != 0 {
276
+			c.data[i].inheritable |= 1 << uint(what)
277
+		}
278
+		if which&BOUNDING != 0 {
279
+			c.bounds[i] |= 1 << uint(what)
280
+		}
281
+	}
282
+}
283
+
284
+func (c *capsV3) Unset(which CapType, caps ...Cap) {
285
+	for _, what := range caps {
286
+		var i uint
287
+		if what > 31 {
288
+			i = uint(what) >> 5
289
+			what %= 32
290
+		}
291
+
292
+		if which&EFFECTIVE != 0 {
293
+			c.data[i].effective &= ^(1 << uint(what))
294
+		}
295
+		if which&PERMITTED != 0 {
296
+			c.data[i].permitted &= ^(1 << uint(what))
297
+		}
298
+		if which&INHERITABLE != 0 {
299
+			c.data[i].inheritable &= ^(1 << uint(what))
300
+		}
301
+		if which&BOUNDING != 0 {
302
+			c.bounds[i] &= ^(1 << uint(what))
303
+		}
304
+	}
305
+}
306
+
307
+func (c *capsV3) Fill(kind CapType) {
308
+	if kind&CAPS == CAPS {
309
+		c.data[0].effective = 0xffffffff
310
+		c.data[0].permitted = 0xffffffff
311
+		c.data[0].inheritable = 0
312
+		c.data[1].effective = 0xffffffff
313
+		c.data[1].permitted = 0xffffffff
314
+		c.data[1].inheritable = 0
315
+	}
316
+
317
+	if kind&BOUNDS == BOUNDS {
318
+		c.bounds[0] = 0xffffffff
319
+		c.bounds[1] = 0xffffffff
320
+	}
321
+}
322
+
323
+func (c *capsV3) Clear(kind CapType) {
324
+	if kind&CAPS == CAPS {
325
+		c.data[0].effective = 0
326
+		c.data[0].permitted = 0
327
+		c.data[0].inheritable = 0
328
+		c.data[1].effective = 0
329
+		c.data[1].permitted = 0
330
+		c.data[1].inheritable = 0
331
+	}
332
+
333
+	if kind&BOUNDS == BOUNDS {
334
+		c.bounds[0] = 0
335
+		c.bounds[1] = 0
336
+	}
337
+}
338
+
339
+func (c *capsV3) StringCap(which CapType) (ret string) {
340
+	return mkStringCap(c, which)
341
+}
342
+
343
+func (c *capsV3) String() (ret string) {
344
+	return mkString(c, BOUNDING)
345
+}
346
+
347
+func (c *capsV3) Load() (err error) {
348
+	err = capget(&c.hdr, &c.data[0])
349
+	if err != nil {
350
+		return
351
+	}
352
+
353
+	f, err := os.Open(fmt.Sprintf("/proc/%d/status", c.hdr.pid))
354
+	if err != nil {
355
+		return
356
+	}
357
+	b := bufio.NewReader(f)
358
+	for {
359
+		line, e := b.ReadString('\n')
360
+		if e != nil {
361
+			if e != io.EOF {
362
+				err = e
363
+			}
364
+			break
365
+		}
366
+		if strings.HasPrefix(line, "CapB") {
367
+			fmt.Sscanf(line[4:], "nd:  %08x%08x", &c.bounds[1], &c.bounds[0])
368
+			break
369
+		}
370
+	}
371
+	f.Close()
372
+
373
+	return
374
+}
375
+
376
+func (c *capsV3) Apply(kind CapType) (err error) {
377
+	if kind&BOUNDS == BOUNDS {
378
+		var data [2]capData
379
+		err = capget(&c.hdr, &data[0])
380
+		if err != nil {
381
+			return
382
+		}
383
+		if (1<<uint(CAP_SETPCAP))&data[0].effective != 0 {
384
+			for i := Cap(0); i <= CAP_LAST_CAP; i++ {
385
+				if c.Get(BOUNDING, i) {
386
+					continue
387
+				}
388
+				err = prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0, 0, 0)
389
+				if err != nil {
390
+					return
391
+				}
392
+			}
393
+		}
394
+	}
395
+
396
+	if kind&CAPS == CAPS {
397
+		return capset(&c.hdr, &c.data[0])
398
+	}
399
+
400
+	return
401
+}
402
+
403
+func newFile(path string) (c Capabilities, err error) {
404
+	c = &capsFile{path: path}
405
+	err = c.Load()
406
+	if err != nil {
407
+		c = nil
408
+	}
409
+	return
410
+}
411
+
412
+type capsFile struct {
413
+	path string
414
+	data vfscapData
415
+}
416
+
417
+func (c *capsFile) Get(which CapType, what Cap) bool {
418
+	var i uint
419
+	if what > 31 {
420
+		if c.data.version == 1 {
421
+			return false
422
+		}
423
+		i = uint(what) >> 5
424
+		what %= 32
425
+	}
426
+
427
+	switch which {
428
+	case EFFECTIVE:
429
+		return (1<<uint(what))&c.data.effective[i] != 0
430
+	case PERMITTED:
431
+		return (1<<uint(what))&c.data.data[i].permitted != 0
432
+	case INHERITABLE:
433
+		return (1<<uint(what))&c.data.data[i].inheritable != 0
434
+	}
435
+
436
+	return false
437
+}
438
+
439
+func (c *capsFile) getData(which CapType, dest []uint32) {
440
+	switch which {
441
+	case EFFECTIVE:
442
+		dest[0] = c.data.effective[0]
443
+		dest[1] = c.data.effective[1]
444
+	case PERMITTED:
445
+		dest[0] = c.data.data[0].permitted
446
+		dest[1] = c.data.data[1].permitted
447
+	case INHERITABLE:
448
+		dest[0] = c.data.data[0].inheritable
449
+		dest[1] = c.data.data[1].inheritable
450
+	}
451
+}
452
+
453
+func (c *capsFile) Empty(which CapType) bool {
454
+	var data [2]uint32
455
+	c.getData(which, data[:])
456
+	return data[0] == 0 && data[1] == 0
457
+}
458
+
459
+func (c *capsFile) Full(which CapType) bool {
460
+	var data [2]uint32
461
+	c.getData(which, data[:])
462
+	if c.data.version == 0 {
463
+		return (data[0] & 0x7fffffff) == 0x7fffffff
464
+	}
465
+	if (data[0] & 0xffffffff) != 0xffffffff {
466
+		return false
467
+	}
468
+	return (data[1] & capUpperMask) == capUpperMask
469
+}
470
+
471
+func (c *capsFile) Set(which CapType, caps ...Cap) {
472
+	for _, what := range caps {
473
+		var i uint
474
+		if what > 31 {
475
+			if c.data.version == 1 {
476
+				continue
477
+			}
478
+			i = uint(what) >> 5
479
+			what %= 32
480
+		}
481
+
482
+		if which&EFFECTIVE != 0 {
483
+			c.data.effective[i] |= 1 << uint(what)
484
+		}
485
+		if which&PERMITTED != 0 {
486
+			c.data.data[i].permitted |= 1 << uint(what)
487
+		}
488
+		if which&INHERITABLE != 0 {
489
+			c.data.data[i].inheritable |= 1 << uint(what)
490
+		}
491
+	}
492
+}
493
+
494
+func (c *capsFile) Unset(which CapType, caps ...Cap) {
495
+	for _, what := range caps {
496
+		var i uint
497
+		if what > 31 {
498
+			if c.data.version == 1 {
499
+				continue
500
+			}
501
+			i = uint(what) >> 5
502
+			what %= 32
503
+		}
504
+
505
+		if which&EFFECTIVE != 0 {
506
+			c.data.effective[i] &= ^(1 << uint(what))
507
+		}
508
+		if which&PERMITTED != 0 {
509
+			c.data.data[i].permitted &= ^(1 << uint(what))
510
+		}
511
+		if which&INHERITABLE != 0 {
512
+			c.data.data[i].inheritable &= ^(1 << uint(what))
513
+		}
514
+	}
515
+}
516
+
517
+func (c *capsFile) Fill(kind CapType) {
518
+	if kind&CAPS == CAPS {
519
+		c.data.effective[0] = 0xffffffff
520
+		c.data.data[0].permitted = 0xffffffff
521
+		c.data.data[0].inheritable = 0
522
+		if c.data.version == 2 {
523
+			c.data.effective[1] = 0xffffffff
524
+			c.data.data[1].permitted = 0xffffffff
525
+			c.data.data[1].inheritable = 0
526
+		}
527
+	}
528
+}
529
+
530
+func (c *capsFile) Clear(kind CapType) {
531
+	if kind&CAPS == CAPS {
532
+		c.data.effective[0] = 0
533
+		c.data.data[0].permitted = 0
534
+		c.data.data[0].inheritable = 0
535
+		if c.data.version == 2 {
536
+			c.data.effective[1] = 0
537
+			c.data.data[1].permitted = 0
538
+			c.data.data[1].inheritable = 0
539
+		}
540
+	}
541
+}
542
+
543
+func (c *capsFile) StringCap(which CapType) (ret string) {
544
+	return mkStringCap(c, which)
545
+}
546
+
547
+func (c *capsFile) String() (ret string) {
548
+	return mkString(c, INHERITABLE)
549
+}
550
+
551
+func (c *capsFile) Load() (err error) {
552
+	return getVfsCap(c.path, &c.data)
553
+}
554
+
555
+func (c *capsFile) Apply(kind CapType) (err error) {
556
+	if kind&CAPS == CAPS {
557
+		return setVfsCap(c.path, &c.data)
558
+	}
559
+	return
560
+}
0 561
new file mode 100644
... ...
@@ -0,0 +1,19 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+// +build !linux
7
+
8
+package capability
9
+
10
+import "errors"
11
+
12
+func newPid(pid int) (Capabilities, error) {
13
+	return nil, errors.New("not supported")
14
+}
15
+
16
+func newFile(path string) (Capabilities, error) {
17
+	return nil, errors.New("not supported")
18
+}
0 19
new file mode 100644
... ...
@@ -0,0 +1,83 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+package capability
7
+
8
+import "testing"
9
+
10
+func TestState(t *testing.T) {
11
+	testEmpty := func(name string, c Capabilities, whats CapType) {
12
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
13
+			if (i&whats) != 0 && !c.Empty(i) {
14
+				t.Errorf(name+": capabilities set %q wasn't empty", i)
15
+			}
16
+		}
17
+	}
18
+	testFull := func(name string, c Capabilities, whats CapType) {
19
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
20
+			if (i&whats) != 0 && !c.Full(i) {
21
+				t.Errorf(name+": capabilities set %q wasn't full", i)
22
+			}
23
+		}
24
+	}
25
+	testPartial := func(name string, c Capabilities, whats CapType) {
26
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
27
+			if (i&whats) != 0 && (c.Empty(i) || c.Full(i)) {
28
+				t.Errorf(name+": capabilities set %q wasn't partial", i)
29
+			}
30
+		}
31
+	}
32
+	testGet := func(name string, c Capabilities, whats CapType, max Cap) {
33
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
34
+			if (i & whats) == 0 {
35
+				continue
36
+			}
37
+			for j := Cap(0); j <= max; j++ {
38
+				if !c.Get(i, j) {
39
+					t.Errorf(name+": capability %q wasn't found on %q", j, i)
40
+				}
41
+			}
42
+		}
43
+	}
44
+
45
+	capf := new(capsFile)
46
+	capf.data.version = 2
47
+	for _, tc := range []struct {
48
+		name string
49
+		c    Capabilities
50
+		sets CapType
51
+		max  Cap
52
+	}{
53
+		{"v1", new(capsV1), EFFECTIVE | PERMITTED, CAP_AUDIT_CONTROL},
54
+		{"v3", new(capsV3), EFFECTIVE | PERMITTED | BOUNDING, CAP_LAST_CAP},
55
+		{"file_v1", new(capsFile), EFFECTIVE | PERMITTED, CAP_AUDIT_CONTROL},
56
+		{"file_v2", capf, EFFECTIVE | PERMITTED, CAP_LAST_CAP},
57
+	} {
58
+		testEmpty(tc.name, tc.c, tc.sets)
59
+		tc.c.Fill(CAPS | BOUNDS)
60
+		testFull(tc.name, tc.c, tc.sets)
61
+		testGet(tc.name, tc.c, tc.sets, tc.max)
62
+		tc.c.Clear(CAPS | BOUNDS)
63
+		testEmpty(tc.name, tc.c, tc.sets)
64
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
65
+			for j := Cap(0); j <= CAP_LAST_CAP; j++ {
66
+				tc.c.Set(i, j)
67
+			}
68
+		}
69
+		testFull(tc.name, tc.c, tc.sets)
70
+		testGet(tc.name, tc.c, tc.sets, tc.max)
71
+		for i := CapType(1); i <= BOUNDING; i <<= 1 {
72
+			for j := Cap(0); j <= CAP_LAST_CAP; j++ {
73
+				tc.c.Unset(i, j)
74
+			}
75
+		}
76
+		testEmpty(tc.name, tc.c, tc.sets)
77
+		tc.c.Set(PERMITTED, CAP_CHOWN)
78
+		testPartial(tc.name, tc.c, PERMITTED)
79
+		tc.c.Clear(CAPS | BOUNDS)
80
+		testEmpty(tc.name, tc.c, tc.sets)
81
+	}
82
+}
0 83
new file mode 100644
... ...
@@ -0,0 +1,338 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+package capability
7
+
8
+type CapType uint
9
+
10
+func (c CapType) String() string {
11
+	switch c {
12
+	case EFFECTIVE:
13
+		return "effective"
14
+	case PERMITTED:
15
+		return "permitted"
16
+	case INHERITABLE:
17
+		return "inheritable"
18
+	case BOUNDING:
19
+		return "bounding"
20
+	case CAPS:
21
+		return "caps"
22
+	}
23
+	return "unknown"
24
+}
25
+
26
+const (
27
+	EFFECTIVE CapType = 1 << iota
28
+	PERMITTED
29
+	INHERITABLE
30
+	BOUNDING
31
+
32
+	CAPS   = EFFECTIVE | PERMITTED | INHERITABLE
33
+	BOUNDS = BOUNDING
34
+)
35
+
36
+type Cap int
37
+
38
+func (c Cap) String() string {
39
+	switch c {
40
+	case CAP_CHOWN:
41
+		return "chown"
42
+	case CAP_DAC_OVERRIDE:
43
+		return "dac_override"
44
+	case CAP_DAC_READ_SEARCH:
45
+		return "dac_read_search"
46
+	case CAP_FOWNER:
47
+		return "fowner"
48
+	case CAP_FSETID:
49
+		return "fsetid"
50
+	case CAP_KILL:
51
+		return "kill"
52
+	case CAP_SETGID:
53
+		return "setgid"
54
+	case CAP_SETUID:
55
+		return "setuid"
56
+	case CAP_SETPCAP:
57
+		return "setpcap"
58
+	case CAP_LINUX_IMMUTABLE:
59
+		return "linux_immutable"
60
+	case CAP_NET_BIND_SERVICE:
61
+		return "net_bind_service"
62
+	case CAP_NET_BROADCAST:
63
+		return "net_broadcast"
64
+	case CAP_NET_ADMIN:
65
+		return "net_admin"
66
+	case CAP_NET_RAW:
67
+		return "net_raw"
68
+	case CAP_IPC_LOCK:
69
+		return "ipc_lock"
70
+	case CAP_IPC_OWNER:
71
+		return "ipc_owner"
72
+	case CAP_SYS_MODULE:
73
+		return "sys_module"
74
+	case CAP_SYS_RAWIO:
75
+		return "sys_rawio"
76
+	case CAP_SYS_CHROOT:
77
+		return "sys_chroot"
78
+	case CAP_SYS_PTRACE:
79
+		return "sys_ptrace"
80
+	case CAP_SYS_PACCT:
81
+		return "sys_psacct"
82
+	case CAP_SYS_ADMIN:
83
+		return "sys_admin"
84
+	case CAP_SYS_BOOT:
85
+		return "sys_boot"
86
+	case CAP_SYS_NICE:
87
+		return "sys_nice"
88
+	case CAP_SYS_RESOURCE:
89
+		return "sys_resource"
90
+	case CAP_SYS_TIME:
91
+		return "sys_time"
92
+	case CAP_SYS_TTY_CONFIG:
93
+		return "sys_tty_config"
94
+	case CAP_MKNOD:
95
+		return "mknod"
96
+	case CAP_LEASE:
97
+		return "lease"
98
+	case CAP_AUDIT_WRITE:
99
+		return "audit_write"
100
+	case CAP_AUDIT_CONTROL:
101
+		return "audit_control"
102
+	case CAP_SETFCAP:
103
+		return "setfcap"
104
+	case CAP_MAC_OVERRIDE:
105
+		return "mac_override"
106
+	case CAP_MAC_ADMIN:
107
+		return "mac_admin"
108
+	case CAP_SYSLOG:
109
+		return "syslog"
110
+	case CAP_WAKE_ALARM:
111
+		return "wake_alarm"
112
+	case CAP_BLOCK_SUSPEND:
113
+		return "block_suspend"
114
+	}
115
+	return "unknown"
116
+}
117
+
118
+const (
119
+	// POSIX-draft defined capabilities.
120
+
121
+	// In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
122
+	// overrides the restriction of changing file ownership and group
123
+	// ownership.
124
+	CAP_CHOWN Cap = 0
125
+
126
+	// Override all DAC access, including ACL execute access if
127
+	// [_POSIX_ACL] is defined. Excluding DAC access covered by
128
+	// CAP_LINUX_IMMUTABLE.
129
+	CAP_DAC_OVERRIDE Cap = 1
130
+
131
+	// Overrides all DAC restrictions regarding read and search on files
132
+	// and directories, including ACL restrictions if [_POSIX_ACL] is
133
+	// defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE.
134
+	CAP_DAC_READ_SEARCH Cap = 2
135
+
136
+	// Overrides all restrictions about allowed operations on files, where
137
+	// file owner ID must be equal to the user ID, except where CAP_FSETID
138
+	// is applicable. It doesn't override MAC and DAC restrictions.
139
+	CAP_FOWNER Cap = 3
140
+
141
+	// Overrides the following restrictions that the effective user ID
142
+	// shall match the file owner ID when setting the S_ISUID and S_ISGID
143
+	// bits on that file; that the effective group ID (or one of the
144
+	// supplementary group IDs) shall match the file owner ID when setting
145
+	// the S_ISGID bit on that file; that the S_ISUID and S_ISGID bits are
146
+	// cleared on successful return from chown(2) (not implemented).
147
+	CAP_FSETID Cap = 4
148
+
149
+	// Overrides the restriction that the real or effective user ID of a
150
+	// process sending a signal must match the real or effective user ID
151
+	// of the process receiving the signal.
152
+	CAP_KILL Cap = 5
153
+
154
+	// Allows setgid(2) manipulation
155
+	// Allows setgroups(2)
156
+	// Allows forged gids on socket credentials passing.
157
+	CAP_SETGID Cap = 6
158
+
159
+	// Allows set*uid(2) manipulation (including fsuid).
160
+	// Allows forged pids on socket credentials passing.
161
+	CAP_SETUID Cap = 7
162
+
163
+	// Linux-specific capabilities
164
+
165
+	// Without VFS support for capabilities:
166
+	//   Transfer any capability in your permitted set to any pid,
167
+	//   remove any capability in your permitted set from any pid
168
+	// With VFS support for capabilities (neither of above, but)
169
+	//   Add any capability from current's capability bounding set
170
+	//     to the current process' inheritable set
171
+	//   Allow taking bits out of capability bounding set
172
+	//   Allow modification of the securebits for a process
173
+	CAP_SETPCAP Cap = 8
174
+
175
+	// Allow modification of S_IMMUTABLE and S_APPEND file attributes
176
+	CAP_LINUX_IMMUTABLE Cap = 9
177
+
178
+	// Allows binding to TCP/UDP sockets below 1024
179
+	// Allows binding to ATM VCIs below 32
180
+	CAP_NET_BIND_SERVICE Cap = 10
181
+
182
+	// Allow broadcasting, listen to multicast
183
+	CAP_NET_BROADCAST Cap = 11
184
+
185
+	// Allow interface configuration
186
+	// Allow administration of IP firewall, masquerading and accounting
187
+	// Allow setting debug option on sockets
188
+	// Allow modification of routing tables
189
+	// Allow setting arbitrary process / process group ownership on
190
+	// sockets
191
+	// Allow binding to any address for transparent proxying (also via NET_RAW)
192
+	// Allow setting TOS (type of service)
193
+	// Allow setting promiscuous mode
194
+	// Allow clearing driver statistics
195
+	// Allow multicasting
196
+	// Allow read/write of device-specific registers
197
+	// Allow activation of ATM control sockets
198
+	CAP_NET_ADMIN Cap = 12
199
+
200
+	// Allow use of RAW sockets
201
+	// Allow use of PACKET sockets
202
+	// Allow binding to any address for transparent proxying (also via NET_ADMIN)
203
+	CAP_NET_RAW Cap = 13
204
+
205
+	// Allow locking of shared memory segments
206
+	// Allow mlock and mlockall (which doesn't really have anything to do
207
+	// with IPC)
208
+	CAP_IPC_LOCK Cap = 14
209
+
210
+	// Override IPC ownership checks
211
+	CAP_IPC_OWNER Cap = 15
212
+
213
+	// Insert and remove kernel modules - modify kernel without limit
214
+	CAP_SYS_MODULE Cap = 16
215
+
216
+	// Allow ioperm/iopl access
217
+	// Allow sending USB messages to any device via /proc/bus/usb
218
+	CAP_SYS_RAWIO Cap = 17
219
+
220
+	// Allow use of chroot()
221
+	CAP_SYS_CHROOT Cap = 18
222
+
223
+	// Allow ptrace() of any process
224
+	CAP_SYS_PTRACE Cap = 19
225
+
226
+	// Allow configuration of process accounting
227
+	CAP_SYS_PACCT Cap = 20
228
+
229
+	// Allow configuration of the secure attention key
230
+	// Allow administration of the random device
231
+	// Allow examination and configuration of disk quotas
232
+	// Allow setting the domainname
233
+	// Allow setting the hostname
234
+	// Allow calling bdflush()
235
+	// Allow mount() and umount(), setting up new smb connection
236
+	// Allow some autofs root ioctls
237
+	// Allow nfsservctl
238
+	// Allow VM86_REQUEST_IRQ
239
+	// Allow to read/write pci config on alpha
240
+	// Allow irix_prctl on mips (setstacksize)
241
+	// Allow flushing all cache on m68k (sys_cacheflush)
242
+	// Allow removing semaphores
243
+	// Used instead of CAP_CHOWN to "chown" IPC message queues, semaphores
244
+	// and shared memory
245
+	// Allow locking/unlocking of shared memory segment
246
+	// Allow turning swap on/off
247
+	// Allow forged pids on socket credentials passing
248
+	// Allow setting readahead and flushing buffers on block devices
249
+	// Allow setting geometry in floppy driver
250
+	// Allow turning DMA on/off in xd driver
251
+	// Allow administration of md devices (mostly the above, but some
252
+	// extra ioctls)
253
+	// Allow tuning the ide driver
254
+	// Allow access to the nvram device
255
+	// Allow administration of apm_bios, serial and bttv (TV) device
256
+	// Allow manufacturer commands in isdn CAPI support driver
257
+	// Allow reading non-standardized portions of pci configuration space
258
+	// Allow DDI debug ioctl on sbpcd driver
259
+	// Allow setting up serial ports
260
+	// Allow sending raw qic-117 commands
261
+	// Allow enabling/disabling tagged queuing on SCSI controllers and sending
262
+	// arbitrary SCSI commands
263
+	// Allow setting encryption key on loopback filesystem
264
+	// Allow setting zone reclaim policy
265
+	CAP_SYS_ADMIN Cap = 21
266
+
267
+	// Allow use of reboot()
268
+	CAP_SYS_BOOT Cap = 22
269
+
270
+	// Allow raising priority and setting priority on other (different
271
+	// UID) processes
272
+	// Allow use of FIFO and round-robin (realtime) scheduling on own
273
+	// processes and setting the scheduling algorithm used by another
274
+	// process.
275
+	// Allow setting cpu affinity on other processes
276
+	CAP_SYS_NICE Cap = 23
277
+
278
+	// Override resource limits. Set resource limits.
279
+	// Override quota limits.
280
+	// Override reserved space on ext2 filesystem
281
+	// Modify data journaling mode on ext3 filesystem (uses journaling
282
+	// resources)
283
+	// NOTE: ext2 honors fsuid when checking for resource overrides, so
284
+	// you can override using fsuid too
285
+	// Override size restrictions on IPC message queues
286
+	// Allow more than 64hz interrupts from the real-time clock
287
+	// Override max number of consoles on console allocation
288
+	// Override max number of keymaps
289
+	CAP_SYS_RESOURCE Cap = 24
290
+
291
+	// Allow manipulation of system clock
292
+	// Allow irix_stime on mips
293
+	// Allow setting the real-time clock
294
+	CAP_SYS_TIME Cap = 25
295
+
296
+	// Allow configuration of tty devices
297
+	// Allow vhangup() of tty
298
+	CAP_SYS_TTY_CONFIG Cap = 26
299
+
300
+	// Allow the privileged aspects of mknod()
301
+	CAP_MKNOD Cap = 27
302
+
303
+	// Allow taking of leases on files
304
+	CAP_LEASE Cap = 28
305
+
306
+	CAP_AUDIT_WRITE   Cap = 29
307
+	CAP_AUDIT_CONTROL Cap = 30
308
+	CAP_SETFCAP       Cap = 31
309
+
310
+	// Override MAC access.
311
+	// The base kernel enforces no MAC policy.
312
+	// An LSM may enforce a MAC policy, and if it does and it chooses
313
+	// to implement capability based overrides of that policy, this is
314
+	// the capability it should use to do so.
315
+	CAP_MAC_OVERRIDE Cap = 32
316
+
317
+	// Allow MAC configuration or state changes.
318
+	// The base kernel requires no MAC configuration.
319
+	// An LSM may enforce a MAC policy, and if it does and it chooses
320
+	// to implement capability based checks on modifications to that
321
+	// policy or the data required to maintain it, this is the
322
+	// capability it should use to do so.
323
+	CAP_MAC_ADMIN Cap = 33
324
+
325
+	// Allow configuring the kernel's syslog (printk behaviour)
326
+	CAP_SYSLOG Cap = 34
327
+
328
+	// Allow triggering something that will wake the system
329
+	CAP_WAKE_ALARM Cap = 35
330
+
331
+	// Allow preventing system suspends
332
+	CAP_BLOCK_SUSPEND Cap = 36
333
+
334
+	CAP_LAST_CAP = CAP_BLOCK_SUSPEND
335
+)
336
+
337
+const capUpperMask = (uint32(1) << (uint(CAP_LAST_CAP) - 31)) - 1
0 338
new file mode 100644
... ...
@@ -0,0 +1,143 @@
0
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
1
+// All rights reserved.
2
+//
3
+// Use of this source code is governed by a BSD-style license that can be
4
+// found in the LICENSE file.
5
+
6
+package capability
7
+
8
+import (
9
+	"syscall"
10
+	"unsafe"
11
+)
12
+
13
+type capHeader struct {
14
+	version uint32
15
+	pid     int
16
+}
17
+
18
+type capData struct {
19
+	effective   uint32
20
+	permitted   uint32
21
+	inheritable uint32
22
+}
23
+
24
+func capget(hdr *capHeader, data *capData) (err error) {
25
+	_, _, e1 := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
26
+	if e1 != 0 {
27
+		err = e1
28
+	}
29
+	return
30
+}
31
+
32
+func capset(hdr *capHeader, data *capData) (err error) {
33
+	_, _, e1 := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0)
34
+	if e1 != 0 {
35
+		err = e1
36
+	}
37
+	return
38
+}
39
+
40
+func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
41
+	_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0)
42
+	if e1 != 0 {
43
+		err = e1
44
+	}
45
+	return
46
+}
47
+
48
+const (
49
+	vfsXattrName = "security.capability"
50
+
51
+	vfsCapVerMask = 0xff000000
52
+	vfsCapVer1    = 0x01000000
53
+	vfsCapVer2    = 0x02000000
54
+
55
+	vfsCapFlagMask      = ^vfsCapVerMask
56
+	vfsCapFlageffective = 0x000001
57
+
58
+	vfscapDataSizeV1 = 4 * (1 + 2*1)
59
+	vfscapDataSizeV2 = 4 * (1 + 2*2)
60
+)
61
+
62
+type vfscapData struct {
63
+	magic uint32
64
+	data  [2]struct {
65
+		permitted   uint32
66
+		inheritable uint32
67
+	}
68
+	effective [2]uint32
69
+	version   int8
70
+}
71
+
72
+var (
73
+	_vfsXattrName *byte
74
+)
75
+
76
+func init() {
77
+	_vfsXattrName, _ = syscall.BytePtrFromString(vfsXattrName)
78
+}
79
+
80
+func getVfsCap(path string, dest *vfscapData) (err error) {
81
+	var _p0 *byte
82
+	_p0, err = syscall.BytePtrFromString(path)
83
+	if err != nil {
84
+		return
85
+	}
86
+	r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0)
87
+	if e1 != 0 {
88
+		err = e1
89
+	}
90
+	switch dest.magic & vfsCapVerMask {
91
+	case vfsCapVer1:
92
+		dest.version = 1
93
+		if r0 != vfscapDataSizeV1 {
94
+			return syscall.EINVAL
95
+		}
96
+		dest.data[1].permitted = 0
97
+		dest.data[1].inheritable = 0
98
+	case vfsCapVer2:
99
+		dest.version = 2
100
+		if r0 != vfscapDataSizeV2 {
101
+			return syscall.EINVAL
102
+		}
103
+	default:
104
+		return syscall.EINVAL
105
+	}
106
+	if dest.magic&vfsCapFlageffective != 0 {
107
+		dest.effective[0] = dest.data[0].permitted | dest.data[0].inheritable
108
+		dest.effective[1] = dest.data[1].permitted | dest.data[1].inheritable
109
+	} else {
110
+		dest.effective[0] = 0
111
+		dest.effective[1] = 0
112
+	}
113
+	return
114
+}
115
+
116
+func setVfsCap(path string, data *vfscapData) (err error) {
117
+	var _p0 *byte
118
+	_p0, err = syscall.BytePtrFromString(path)
119
+	if err != nil {
120
+		return
121
+	}
122
+	var size uintptr
123
+	if data.version == 1 {
124
+		data.magic = vfsCapVer1
125
+		size = vfscapDataSizeV1
126
+	} else if data.version == 2 {
127
+		data.magic = vfsCapVer2
128
+		if data.effective[0] != 0 || data.effective[1] != 0 {
129
+			data.magic |= vfsCapFlageffective
130
+			data.data[0].permitted |= data.effective[0]
131
+			data.data[1].permitted |= data.effective[1]
132
+		}
133
+		size = vfscapDataSizeV2
134
+	} else {
135
+		return syscall.EINVAL
136
+	}
137
+	_, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0)
138
+	if e1 != 0 {
139
+		err = e1
140
+	}
141
+	return
142
+}