full diff: https://github.com/syndtr/gocapability/compare/2c00daeb6c3b45114c80ac44119e7b8801fdd852...d98352740cb2c55f81556b63d4a1ec64c5a319c2
relevant changes:
- syndtr/gocapability#11 Add support for ambient capabilities
- syndtr/gocapability#13 Fix issue #12: break too early
- syndtr/gocapability#16 Fix capHeader.pid type
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -89,7 +89,7 @@ github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20e |
| 89 | 89 |
# libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json) |
| 90 | 90 |
github.com/coreos/go-systemd 39ca1b05acc7ad1220e09f133283b8859a8b71ab # v17 |
| 91 | 91 |
github.com/godbus/dbus 5f6efc7ef2759c81b7ba876593971bfce311eab3 # v4.0.0 |
| 92 |
-github.com/syndtr/gocapability 2c00daeb6c3b45114c80ac44119e7b8801fdd852 |
|
| 92 |
+github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 |
|
| 93 | 93 |
github.com/golang/protobuf aa810b61a9c79d51363740d207bb46cf8e620ed5 # v1.2.0 |
| 94 | 94 |
|
| 95 | 95 |
# gelf logging driver deps |
| ... | ... |
@@ -10,42 +10,42 @@ package capability |
| 10 | 10 |
type Capabilities interface {
|
| 11 | 11 |
// Get check whether a capability present in the given |
| 12 | 12 |
// capabilities set. The 'which' value should be one of EFFECTIVE, |
| 13 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 13 |
+ // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. |
|
| 14 | 14 |
Get(which CapType, what Cap) bool |
| 15 | 15 |
|
| 16 | 16 |
// Empty check whether all capability bits of the given capabilities |
| 17 | 17 |
// set are zero. The 'which' value should be one of EFFECTIVE, |
| 18 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 18 |
+ // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. |
|
| 19 | 19 |
Empty(which CapType) bool |
| 20 | 20 |
|
| 21 | 21 |
// Full check whether all capability bits of the given capabilities |
| 22 | 22 |
// set are one. The 'which' value should be one of EFFECTIVE, |
| 23 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 23 |
+ // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. |
|
| 24 | 24 |
Full(which CapType) bool |
| 25 | 25 |
|
| 26 | 26 |
// Set sets capabilities of the given capabilities sets. The |
| 27 | 27 |
// 'which' value should be one or combination (OR'ed) of EFFECTIVE, |
| 28 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 28 |
+ // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. |
|
| 29 | 29 |
Set(which CapType, caps ...Cap) |
| 30 | 30 |
|
| 31 | 31 |
// Unset unsets capabilities of the given capabilities sets. The |
| 32 | 32 |
// 'which' value should be one or combination (OR'ed) of EFFECTIVE, |
| 33 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 33 |
+ // PERMITTED, INHERITABLE, BOUNDING or AMBIENT. |
|
| 34 | 34 |
Unset(which CapType, caps ...Cap) |
| 35 | 35 |
|
| 36 | 36 |
// Fill sets all bits of the given capabilities kind to one. The |
| 37 |
- // 'kind' value should be one or combination (OR'ed) of CAPS or |
|
| 38 |
- // BOUNDS. |
|
| 37 |
+ // 'kind' value should be one or combination (OR'ed) of CAPS, |
|
| 38 |
+ // BOUNDS or AMBS. |
|
| 39 | 39 |
Fill(kind CapType) |
| 40 | 40 |
|
| 41 | 41 |
// Clear sets all bits of the given capabilities kind to zero. The |
| 42 |
- // 'kind' value should be one or combination (OR'ed) of CAPS or |
|
| 43 |
- // BOUNDS. |
|
| 42 |
+ // 'kind' value should be one or combination (OR'ed) of CAPS, |
|
| 43 |
+ // BOUNDS or AMBS. |
|
| 44 | 44 |
Clear(kind CapType) |
| 45 | 45 |
|
| 46 | 46 |
// String return current capabilities state of the given capabilities |
| 47 | 47 |
// set as string. The 'which' value should be one of EFFECTIVE, |
| 48 |
- // PERMITTED, INHERITABLE or BOUNDING. |
|
| 48 |
+ // PERMITTED, INHERITABLE BOUNDING or AMBIENT |
|
| 49 | 49 |
StringCap(which CapType) string |
| 50 | 50 |
|
| 51 | 51 |
// String return current capabilities state as string. |
| ... | ... |
@@ -60,13 +60,74 @@ type Capabilities interface {
|
| 60 | 60 |
Apply(kind CapType) error |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
-// NewPid create new initialized Capabilities object for given pid when it |
|
| 64 |
-// is nonzero, or for the current pid if pid is 0 |
|
| 63 |
+// NewPid initializes a new Capabilities object for given pid when |
|
| 64 |
+// it is nonzero, or for the current process if pid is 0. |
|
| 65 |
+// |
|
| 66 |
+// Deprecated: Replace with NewPid2. For example, replace: |
|
| 67 |
+// |
|
| 68 |
+// c, err := NewPid(0) |
|
| 69 |
+// if err != nil {
|
|
| 70 |
+// return err |
|
| 71 |
+// } |
|
| 72 |
+// |
|
| 73 |
+// with: |
|
| 74 |
+// |
|
| 75 |
+// c, err := NewPid2(0) |
|
| 76 |
+// if err != nil {
|
|
| 77 |
+// return err |
|
| 78 |
+// } |
|
| 79 |
+// err = c.Load() |
|
| 80 |
+// if err != nil {
|
|
| 81 |
+// return err |
|
| 82 |
+// } |
|
| 65 | 83 |
func NewPid(pid int) (Capabilities, error) {
|
| 84 |
+ c, err := newPid(pid) |
|
| 85 |
+ if err != nil {
|
|
| 86 |
+ return c, err |
|
| 87 |
+ } |
|
| 88 |
+ err = c.Load() |
|
| 89 |
+ return c, err |
|
| 90 |
+} |
|
| 91 |
+ |
|
| 92 |
+// NewPid2 initializes a new Capabilities object for given pid when |
|
| 93 |
+// it is nonzero, or for the current process if pid is 0. This |
|
| 94 |
+// does not load the process's current capabilities; to do that you |
|
| 95 |
+// must call Load explicitly. |
|
| 96 |
+func NewPid2(pid int) (Capabilities, error) {
|
|
| 66 | 97 |
return newPid(pid) |
| 67 | 98 |
} |
| 68 | 99 |
|
| 69 |
-// NewFile create new initialized Capabilities object for given named file. |
|
| 70 |
-func NewFile(name string) (Capabilities, error) {
|
|
| 71 |
- return newFile(name) |
|
| 100 |
+// NewFile initializes a new Capabilities object for given file path. |
|
| 101 |
+// |
|
| 102 |
+// Deprecated: Replace with NewFile2. For example, replace: |
|
| 103 |
+// |
|
| 104 |
+// c, err := NewFile(path) |
|
| 105 |
+// if err != nil {
|
|
| 106 |
+// return err |
|
| 107 |
+// } |
|
| 108 |
+// |
|
| 109 |
+// with: |
|
| 110 |
+// |
|
| 111 |
+// c, err := NewFile2(path) |
|
| 112 |
+// if err != nil {
|
|
| 113 |
+// return err |
|
| 114 |
+// } |
|
| 115 |
+// err = c.Load() |
|
| 116 |
+// if err != nil {
|
|
| 117 |
+// return err |
|
| 118 |
+// } |
|
| 119 |
+func NewFile(path string) (Capabilities, error) {
|
|
| 120 |
+ c, err := newFile(path) |
|
| 121 |
+ if err != nil {
|
|
| 122 |
+ return c, err |
|
| 123 |
+ } |
|
| 124 |
+ err = c.Load() |
|
| 125 |
+ return c, err |
|
| 126 |
+} |
|
| 127 |
+ |
|
| 128 |
+// NewFile2 creates a new initialized Capabilities object for given |
|
| 129 |
+// file path. This does not load the process's current capabilities; |
|
| 130 |
+// to do that you must call Load explicitly. |
|
| 131 |
+func NewFile2(path string) (Capabilities, error) {
|
|
| 132 |
+ return newFile(path) |
|
| 72 | 133 |
} |
| ... | ... |
@@ -103,21 +103,17 @@ func newPid(pid int) (c Capabilities, err error) {
|
| 103 | 103 |
case linuxCapVer1: |
| 104 | 104 |
p := new(capsV1) |
| 105 | 105 |
p.hdr.version = capVers |
| 106 |
- p.hdr.pid = pid |
|
| 106 |
+ p.hdr.pid = int32(pid) |
|
| 107 | 107 |
c = p |
| 108 | 108 |
case linuxCapVer2, linuxCapVer3: |
| 109 | 109 |
p := new(capsV3) |
| 110 | 110 |
p.hdr.version = capVers |
| 111 |
- p.hdr.pid = pid |
|
| 111 |
+ p.hdr.pid = int32(pid) |
|
| 112 | 112 |
c = p |
| 113 | 113 |
default: |
| 114 | 114 |
err = errUnknownVers |
| 115 | 115 |
return |
| 116 | 116 |
} |
| 117 |
- err = c.Load() |
|
| 118 |
- if err != nil {
|
|
| 119 |
- c = nil |
|
| 120 |
- } |
|
| 121 | 117 |
return |
| 122 | 118 |
} |
| 123 | 119 |
|
| ... | ... |
@@ -235,9 +231,10 @@ func (c *capsV1) Apply(kind CapType) error {
|
| 235 | 235 |
} |
| 236 | 236 |
|
| 237 | 237 |
type capsV3 struct {
|
| 238 |
- hdr capHeader |
|
| 239 |
- data [2]capData |
|
| 240 |
- bounds [2]uint32 |
|
| 238 |
+ hdr capHeader |
|
| 239 |
+ data [2]capData |
|
| 240 |
+ bounds [2]uint32 |
|
| 241 |
+ ambient [2]uint32 |
|
| 241 | 242 |
} |
| 242 | 243 |
|
| 243 | 244 |
func (c *capsV3) Get(which CapType, what Cap) bool {
|
| ... | ... |
@@ -256,6 +253,8 @@ func (c *capsV3) Get(which CapType, what Cap) bool {
|
| 256 | 256 |
return (1<<uint(what))&c.data[i].inheritable != 0 |
| 257 | 257 |
case BOUNDING: |
| 258 | 258 |
return (1<<uint(what))&c.bounds[i] != 0 |
| 259 |
+ case AMBIENT: |
|
| 260 |
+ return (1<<uint(what))&c.ambient[i] != 0 |
|
| 259 | 261 |
} |
| 260 | 262 |
|
| 261 | 263 |
return false |
| ... | ... |
@@ -275,6 +274,9 @@ func (c *capsV3) getData(which CapType, dest []uint32) {
|
| 275 | 275 |
case BOUNDING: |
| 276 | 276 |
dest[0] = c.bounds[0] |
| 277 | 277 |
dest[1] = c.bounds[1] |
| 278 |
+ case AMBIENT: |
|
| 279 |
+ dest[0] = c.ambient[0] |
|
| 280 |
+ dest[1] = c.ambient[1] |
|
| 278 | 281 |
} |
| 279 | 282 |
} |
| 280 | 283 |
|
| ... | ... |
@@ -313,6 +315,9 @@ func (c *capsV3) Set(which CapType, caps ...Cap) {
|
| 313 | 313 |
if which&BOUNDING != 0 {
|
| 314 | 314 |
c.bounds[i] |= 1 << uint(what) |
| 315 | 315 |
} |
| 316 |
+ if which&AMBIENT != 0 {
|
|
| 317 |
+ c.ambient[i] |= 1 << uint(what) |
|
| 318 |
+ } |
|
| 316 | 319 |
} |
| 317 | 320 |
} |
| 318 | 321 |
|
| ... | ... |
@@ -336,6 +341,9 @@ func (c *capsV3) Unset(which CapType, caps ...Cap) {
|
| 336 | 336 |
if which&BOUNDING != 0 {
|
| 337 | 337 |
c.bounds[i] &= ^(1 << uint(what)) |
| 338 | 338 |
} |
| 339 |
+ if which&AMBIENT != 0 {
|
|
| 340 |
+ c.ambient[i] &= ^(1 << uint(what)) |
|
| 341 |
+ } |
|
| 339 | 342 |
} |
| 340 | 343 |
} |
| 341 | 344 |
|
| ... | ... |
@@ -353,6 +361,10 @@ func (c *capsV3) Fill(kind CapType) {
|
| 353 | 353 |
c.bounds[0] = 0xffffffff |
| 354 | 354 |
c.bounds[1] = 0xffffffff |
| 355 | 355 |
} |
| 356 |
+ if kind&AMBS == AMBS {
|
|
| 357 |
+ c.ambient[0] = 0xffffffff |
|
| 358 |
+ c.ambient[1] = 0xffffffff |
|
| 359 |
+ } |
|
| 356 | 360 |
} |
| 357 | 361 |
|
| 358 | 362 |
func (c *capsV3) Clear(kind CapType) {
|
| ... | ... |
@@ -369,6 +381,10 @@ func (c *capsV3) Clear(kind CapType) {
|
| 369 | 369 |
c.bounds[0] = 0 |
| 370 | 370 |
c.bounds[1] = 0 |
| 371 | 371 |
} |
| 372 |
+ if kind&AMBS == AMBS {
|
|
| 373 |
+ c.ambient[0] = 0 |
|
| 374 |
+ c.ambient[1] = 0 |
|
| 375 |
+ } |
|
| 372 | 376 |
} |
| 373 | 377 |
|
| 374 | 378 |
func (c *capsV3) StringCap(which CapType) (ret string) {
|
| ... | ... |
@@ -408,7 +424,11 @@ func (c *capsV3) Load() (err error) {
|
| 408 | 408 |
} |
| 409 | 409 |
if strings.HasPrefix(line, "CapB") {
|
| 410 | 410 |
fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0]) |
| 411 |
- break |
|
| 411 |
+ continue |
|
| 412 |
+ } |
|
| 413 |
+ if strings.HasPrefix(line, "CapA") {
|
|
| 414 |
+ fmt.Sscanf(line[4:], "mb: %08x%08x", &c.ambient[1], &c.ambient[0]) |
|
| 415 |
+ continue |
|
| 412 | 416 |
} |
| 413 | 417 |
} |
| 414 | 418 |
f.Close() |
| ... | ... |
@@ -442,7 +462,25 @@ func (c *capsV3) Apply(kind CapType) (err error) {
|
| 442 | 442 |
} |
| 443 | 443 |
|
| 444 | 444 |
if kind&CAPS == CAPS {
|
| 445 |
- return capset(&c.hdr, &c.data[0]) |
|
| 445 |
+ err = capset(&c.hdr, &c.data[0]) |
|
| 446 |
+ if err != nil {
|
|
| 447 |
+ return |
|
| 448 |
+ } |
|
| 449 |
+ } |
|
| 450 |
+ |
|
| 451 |
+ if kind&AMBS == AMBS {
|
|
| 452 |
+ for i := Cap(0); i <= CAP_LAST_CAP; i++ {
|
|
| 453 |
+ action := pr_CAP_AMBIENT_LOWER |
|
| 454 |
+ if c.Get(AMBIENT, i) {
|
|
| 455 |
+ action = pr_CAP_AMBIENT_RAISE |
|
| 456 |
+ } |
|
| 457 |
+ err := prctl(pr_CAP_AMBIENT, action, uintptr(i), 0, 0) |
|
| 458 |
+ // Ignore EINVAL as not supported on kernels before 4.3 |
|
| 459 |
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL {
|
|
| 460 |
+ err = nil |
|
| 461 |
+ continue |
|
| 462 |
+ } |
|
| 463 |
+ } |
|
| 446 | 464 |
} |
| 447 | 465 |
|
| 448 | 466 |
return |
| ... | ... |
@@ -450,10 +488,6 @@ func (c *capsV3) Apply(kind CapType) (err error) {
|
| 450 | 450 |
|
| 451 | 451 |
func newFile(path string) (c Capabilities, err error) {
|
| 452 | 452 |
c = &capsFile{path: path}
|
| 453 |
- err = c.Load() |
|
| 454 |
- if err != nil {
|
|
| 455 |
- c = nil |
|
| 456 |
- } |
|
| 457 | 453 |
return |
| 458 | 454 |
} |
| 459 | 455 |
|
| ... | ... |
@@ -20,6 +20,8 @@ func (c CapType) String() string {
|
| 20 | 20 |
return "bounding" |
| 21 | 21 |
case CAPS: |
| 22 | 22 |
return "caps" |
| 23 |
+ case AMBIENT: |
|
| 24 |
+ return "ambient" |
|
| 23 | 25 |
} |
| 24 | 26 |
return "unknown" |
| 25 | 27 |
} |
| ... | ... |
@@ -29,9 +31,11 @@ const ( |
| 29 | 29 |
PERMITTED |
| 30 | 30 |
INHERITABLE |
| 31 | 31 |
BOUNDING |
| 32 |
+ AMBIENT |
|
| 32 | 33 |
|
| 33 | 34 |
CAPS = EFFECTIVE | PERMITTED | INHERITABLE |
| 34 | 35 |
BOUNDS = BOUNDING |
| 36 |
+ AMBS = AMBIENT |
|
| 35 | 37 |
) |
| 36 | 38 |
|
| 37 | 39 |
//go:generate go run enumgen/gen.go |
| ... | ... |
@@ -13,7 +13,7 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
type capHeader struct {
|
| 15 | 15 |
version uint32 |
| 16 |
- pid int |
|
| 16 |
+ pid int32 |
|
| 17 | 17 |
} |
| 18 | 18 |
|
| 19 | 19 |
type capData struct {
|
| ... | ... |
@@ -38,6 +38,15 @@ func capset(hdr *capHeader, data *capData) (err error) {
|
| 38 | 38 |
return |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
+// not yet in syscall |
|
| 42 |
+const ( |
|
| 43 |
+ pr_CAP_AMBIENT = 47 |
|
| 44 |
+ pr_CAP_AMBIENT_IS_SET = uintptr(1) |
|
| 45 |
+ pr_CAP_AMBIENT_RAISE = uintptr(2) |
|
| 46 |
+ pr_CAP_AMBIENT_LOWER = uintptr(3) |
|
| 47 |
+ pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4) |
|
| 48 |
+) |
|
| 49 |
+ |
|
| 41 | 50 |
func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) {
|
| 42 | 51 |
_, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) |
| 43 | 52 |
if e1 != 0 {
|