summaryrefslogtreecommitdiff
path: root/vendor/github.com/syndtr/gocapability/capability/capability_linux.go
diff options
context:
space:
mode:
authorMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
committerMatthew Heon <matthew.heon@gmail.com>2017-11-01 11:24:59 -0400
commita031b83a09a8628435317a03f199cdc18b78262f (patch)
treebc017a96769ce6de33745b8b0b1304ccf38e9df0 /vendor/github.com/syndtr/gocapability/capability/capability_linux.go
parent2b74391cd5281f6fdf391ff8ad50fd1490f6bf89 (diff)
downloadpodman-a031b83a09a8628435317a03f199cdc18b78262f.tar.gz
podman-a031b83a09a8628435317a03f199cdc18b78262f.tar.bz2
podman-a031b83a09a8628435317a03f199cdc18b78262f.zip
Initial checkin from CRI-O repo
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'vendor/github.com/syndtr/gocapability/capability/capability_linux.go')
-rw-r--r--vendor/github.com/syndtr/gocapability/capability/capability_linux.go650
1 files changed, 650 insertions, 0 deletions
diff --git a/vendor/github.com/syndtr/gocapability/capability/capability_linux.go b/vendor/github.com/syndtr/gocapability/capability/capability_linux.go
new file mode 100644
index 000000000..6d2135ac5
--- /dev/null
+++ b/vendor/github.com/syndtr/gocapability/capability/capability_linux.go
@@ -0,0 +1,650 @@
+// Copyright (c) 2013, Suryandaru Triandana <syndtr@gmail.com>
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package capability
+
+import (
+ "bufio"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+ "syscall"
+)
+
+var errUnknownVers = errors.New("unknown capability version")
+
+const (
+ linuxCapVer1 = 0x19980330
+ linuxCapVer2 = 0x20071026
+ linuxCapVer3 = 0x20080522
+)
+
+var (
+ capVers uint32
+ capLastCap Cap
+)
+
+func init() {
+ var hdr capHeader
+ capget(&hdr, nil)
+ capVers = hdr.version
+
+ if initLastCap() == nil {
+ CAP_LAST_CAP = capLastCap
+ if capLastCap > 31 {
+ capUpperMask = (uint32(1) << (uint(capLastCap) - 31)) - 1
+ } else {
+ capUpperMask = 0
+ }
+ }
+}
+
+func initLastCap() error {
+ if capLastCap != 0 {
+ return nil
+ }
+
+ f, err := os.Open("/proc/sys/kernel/cap_last_cap")
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ var b []byte = make([]byte, 11)
+ _, err = f.Read(b)
+ if err != nil {
+ return err
+ }
+
+ fmt.Sscanf(string(b), "%d", &capLastCap)
+
+ return nil
+}
+
+func mkStringCap(c Capabilities, which CapType) (ret string) {
+ for i, first := Cap(0), true; i <= CAP_LAST_CAP; i++ {
+ if !c.Get(which, i) {
+ continue
+ }
+ if first {
+ first = false
+ } else {
+ ret += ", "
+ }
+ ret += i.String()
+ }
+ return
+}
+
+func mkString(c Capabilities, max CapType) (ret string) {
+ ret = "{"
+ for i := CapType(1); i <= max; i <<= 1 {
+ ret += " " + i.String() + "=\""
+ if c.Empty(i) {
+ ret += "empty"
+ } else if c.Full(i) {
+ ret += "full"
+ } else {
+ ret += c.StringCap(i)
+ }
+ ret += "\""
+ }
+ ret += " }"
+ return
+}
+
+func newPid(pid int) (c Capabilities, err error) {
+ switch capVers {
+ case linuxCapVer1:
+ p := new(capsV1)
+ p.hdr.version = capVers
+ p.hdr.pid = pid
+ c = p
+ case linuxCapVer2, linuxCapVer3:
+ p := new(capsV3)
+ p.hdr.version = capVers
+ p.hdr.pid = pid
+ c = p
+ default:
+ err = errUnknownVers
+ return
+ }
+ err = c.Load()
+ if err != nil {
+ c = nil
+ }
+ return
+}
+
+type capsV1 struct {
+ hdr capHeader
+ data capData
+}
+
+func (c *capsV1) Get(which CapType, what Cap) bool {
+ if what > 32 {
+ return false
+ }
+
+ switch which {
+ case EFFECTIVE:
+ return (1<<uint(what))&c.data.effective != 0
+ case PERMITTED:
+ return (1<<uint(what))&c.data.permitted != 0
+ case INHERITABLE:
+ return (1<<uint(what))&c.data.inheritable != 0
+ }
+
+ return false
+}
+
+func (c *capsV1) getData(which CapType) (ret uint32) {
+ switch which {
+ case EFFECTIVE:
+ ret = c.data.effective
+ case PERMITTED:
+ ret = c.data.permitted
+ case INHERITABLE:
+ ret = c.data.inheritable
+ }
+ return
+}
+
+func (c *capsV1) Empty(which CapType) bool {
+ return c.getData(which) == 0
+}
+
+func (c *capsV1) Full(which CapType) bool {
+ return (c.getData(which) & 0x7fffffff) == 0x7fffffff
+}
+
+func (c *capsV1) Set(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ if what > 32 {
+ continue
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data.effective |= 1 << uint(what)
+ }
+ if which&PERMITTED != 0 {
+ c.data.permitted |= 1 << uint(what)
+ }
+ if which&INHERITABLE != 0 {
+ c.data.inheritable |= 1 << uint(what)
+ }
+ }
+}
+
+func (c *capsV1) Unset(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ if what > 32 {
+ continue
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data.effective &= ^(1 << uint(what))
+ }
+ if which&PERMITTED != 0 {
+ c.data.permitted &= ^(1 << uint(what))
+ }
+ if which&INHERITABLE != 0 {
+ c.data.inheritable &= ^(1 << uint(what))
+ }
+ }
+}
+
+func (c *capsV1) Fill(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data.effective = 0x7fffffff
+ c.data.permitted = 0x7fffffff
+ c.data.inheritable = 0
+ }
+}
+
+func (c *capsV1) Clear(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data.effective = 0
+ c.data.permitted = 0
+ c.data.inheritable = 0
+ }
+}
+
+func (c *capsV1) StringCap(which CapType) (ret string) {
+ return mkStringCap(c, which)
+}
+
+func (c *capsV1) String() (ret string) {
+ return mkString(c, BOUNDING)
+}
+
+func (c *capsV1) Load() (err error) {
+ return capget(&c.hdr, &c.data)
+}
+
+func (c *capsV1) Apply(kind CapType) error {
+ if kind&CAPS == CAPS {
+ return capset(&c.hdr, &c.data)
+ }
+ return nil
+}
+
+type capsV3 struct {
+ hdr capHeader
+ data [2]capData
+ bounds [2]uint32
+ ambient [2]uint32
+}
+
+func (c *capsV3) Get(which CapType, what Cap) bool {
+ var i uint
+ if what > 31 {
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ switch which {
+ case EFFECTIVE:
+ return (1<<uint(what))&c.data[i].effective != 0
+ case PERMITTED:
+ return (1<<uint(what))&c.data[i].permitted != 0
+ case INHERITABLE:
+ return (1<<uint(what))&c.data[i].inheritable != 0
+ case BOUNDING:
+ return (1<<uint(what))&c.bounds[i] != 0
+ case AMBIENT:
+ return (1<<uint(what))&c.ambient[i] != 0
+ }
+
+ return false
+}
+
+func (c *capsV3) getData(which CapType, dest []uint32) {
+ switch which {
+ case EFFECTIVE:
+ dest[0] = c.data[0].effective
+ dest[1] = c.data[1].effective
+ case PERMITTED:
+ dest[0] = c.data[0].permitted
+ dest[1] = c.data[1].permitted
+ case INHERITABLE:
+ dest[0] = c.data[0].inheritable
+ dest[1] = c.data[1].inheritable
+ case BOUNDING:
+ dest[0] = c.bounds[0]
+ dest[1] = c.bounds[1]
+ case AMBIENT:
+ dest[0] = c.ambient[0]
+ dest[1] = c.ambient[1]
+ }
+}
+
+func (c *capsV3) Empty(which CapType) bool {
+ var data [2]uint32
+ c.getData(which, data[:])
+ return data[0] == 0 && data[1] == 0
+}
+
+func (c *capsV3) Full(which CapType) bool {
+ var data [2]uint32
+ c.getData(which, data[:])
+ if (data[0] & 0xffffffff) != 0xffffffff {
+ return false
+ }
+ return (data[1] & capUpperMask) == capUpperMask
+}
+
+func (c *capsV3) Set(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ var i uint
+ if what > 31 {
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data[i].effective |= 1 << uint(what)
+ }
+ if which&PERMITTED != 0 {
+ c.data[i].permitted |= 1 << uint(what)
+ }
+ if which&INHERITABLE != 0 {
+ c.data[i].inheritable |= 1 << uint(what)
+ }
+ if which&BOUNDING != 0 {
+ c.bounds[i] |= 1 << uint(what)
+ }
+ if which&AMBIENT != 0 {
+ c.ambient[i] |= 1 << uint(what)
+ }
+ }
+}
+
+func (c *capsV3) Unset(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ var i uint
+ if what > 31 {
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data[i].effective &= ^(1 << uint(what))
+ }
+ if which&PERMITTED != 0 {
+ c.data[i].permitted &= ^(1 << uint(what))
+ }
+ if which&INHERITABLE != 0 {
+ c.data[i].inheritable &= ^(1 << uint(what))
+ }
+ if which&BOUNDING != 0 {
+ c.bounds[i] &= ^(1 << uint(what))
+ }
+ if which&AMBIENT != 0 {
+ c.ambient[i] &= ^(1 << uint(what))
+ }
+ }
+}
+
+func (c *capsV3) Fill(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data[0].effective = 0xffffffff
+ c.data[0].permitted = 0xffffffff
+ c.data[0].inheritable = 0
+ c.data[1].effective = 0xffffffff
+ c.data[1].permitted = 0xffffffff
+ c.data[1].inheritable = 0
+ }
+
+ if kind&BOUNDS == BOUNDS {
+ c.bounds[0] = 0xffffffff
+ c.bounds[1] = 0xffffffff
+ }
+ if kind&AMBS == AMBS {
+ c.ambient[0] = 0xffffffff
+ c.ambient[1] = 0xffffffff
+ }
+}
+
+func (c *capsV3) Clear(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data[0].effective = 0
+ c.data[0].permitted = 0
+ c.data[0].inheritable = 0
+ c.data[1].effective = 0
+ c.data[1].permitted = 0
+ c.data[1].inheritable = 0
+ }
+
+ if kind&BOUNDS == BOUNDS {
+ c.bounds[0] = 0
+ c.bounds[1] = 0
+ }
+ if kind&AMBS == AMBS {
+ c.ambient[0] = 0
+ c.ambient[1] = 0
+ }
+}
+
+func (c *capsV3) StringCap(which CapType) (ret string) {
+ return mkStringCap(c, which)
+}
+
+func (c *capsV3) String() (ret string) {
+ return mkString(c, BOUNDING)
+}
+
+func (c *capsV3) Load() (err error) {
+ err = capget(&c.hdr, &c.data[0])
+ if err != nil {
+ return
+ }
+
+ var status_path string
+
+ if c.hdr.pid == 0 {
+ status_path = fmt.Sprintf("/proc/self/status")
+ } else {
+ status_path = fmt.Sprintf("/proc/%d/status", c.hdr.pid)
+ }
+
+ f, err := os.Open(status_path)
+ if err != nil {
+ return
+ }
+ b := bufio.NewReader(f)
+ for {
+ line, e := b.ReadString('\n')
+ if e != nil {
+ if e != io.EOF {
+ err = e
+ }
+ break
+ }
+ if strings.HasPrefix(line, "CapB") {
+ fmt.Sscanf(line[4:], "nd: %08x%08x", &c.bounds[1], &c.bounds[0])
+ break
+ }
+ if strings.HasPrefix(line, "CapA") {
+ fmt.Sscanf(line[4:], "mb: %08x%08x", &c.ambient[1], &c.ambient[0])
+ break
+ }
+ }
+ f.Close()
+
+ return
+}
+
+func (c *capsV3) Apply(kind CapType) (err error) {
+ if kind&BOUNDS == BOUNDS {
+ var data [2]capData
+ err = capget(&c.hdr, &data[0])
+ if err != nil {
+ return
+ }
+ if (1<<uint(CAP_SETPCAP))&data[0].effective != 0 {
+ for i := Cap(0); i <= CAP_LAST_CAP; i++ {
+ if c.Get(BOUNDING, i) {
+ continue
+ }
+ err = prctl(syscall.PR_CAPBSET_DROP, uintptr(i), 0, 0, 0)
+ if err != nil {
+ // Ignore EINVAL since the capability may not be supported in this system.
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL {
+ err = nil
+ continue
+ }
+ return
+ }
+ }
+ }
+ }
+
+ if kind&CAPS == CAPS {
+ err = capset(&c.hdr, &c.data[0])
+ if err != nil {
+ return
+ }
+ }
+
+ if kind&AMBS == AMBS {
+ for i := Cap(0); i <= CAP_LAST_CAP; i++ {
+ action := pr_CAP_AMBIENT_LOWER
+ if c.Get(AMBIENT, i) {
+ action = pr_CAP_AMBIENT_RAISE
+ }
+ err := prctl(pr_CAP_AMBIENT, action, uintptr(i), 0, 0)
+ // Ignore EINVAL as not supported on kernels before 4.3
+ if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINVAL {
+ err = nil
+ continue
+ }
+ }
+ }
+
+ return
+}
+
+func newFile(path string) (c Capabilities, err error) {
+ c = &capsFile{path: path}
+ err = c.Load()
+ if err != nil {
+ c = nil
+ }
+ return
+}
+
+type capsFile struct {
+ path string
+ data vfscapData
+}
+
+func (c *capsFile) Get(which CapType, what Cap) bool {
+ var i uint
+ if what > 31 {
+ if c.data.version == 1 {
+ return false
+ }
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ switch which {
+ case EFFECTIVE:
+ return (1<<uint(what))&c.data.effective[i] != 0
+ case PERMITTED:
+ return (1<<uint(what))&c.data.data[i].permitted != 0
+ case INHERITABLE:
+ return (1<<uint(what))&c.data.data[i].inheritable != 0
+ }
+
+ return false
+}
+
+func (c *capsFile) getData(which CapType, dest []uint32) {
+ switch which {
+ case EFFECTIVE:
+ dest[0] = c.data.effective[0]
+ dest[1] = c.data.effective[1]
+ case PERMITTED:
+ dest[0] = c.data.data[0].permitted
+ dest[1] = c.data.data[1].permitted
+ case INHERITABLE:
+ dest[0] = c.data.data[0].inheritable
+ dest[1] = c.data.data[1].inheritable
+ }
+}
+
+func (c *capsFile) Empty(which CapType) bool {
+ var data [2]uint32
+ c.getData(which, data[:])
+ return data[0] == 0 && data[1] == 0
+}
+
+func (c *capsFile) Full(which CapType) bool {
+ var data [2]uint32
+ c.getData(which, data[:])
+ if c.data.version == 0 {
+ return (data[0] & 0x7fffffff) == 0x7fffffff
+ }
+ if (data[0] & 0xffffffff) != 0xffffffff {
+ return false
+ }
+ return (data[1] & capUpperMask) == capUpperMask
+}
+
+func (c *capsFile) Set(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ var i uint
+ if what > 31 {
+ if c.data.version == 1 {
+ continue
+ }
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data.effective[i] |= 1 << uint(what)
+ }
+ if which&PERMITTED != 0 {
+ c.data.data[i].permitted |= 1 << uint(what)
+ }
+ if which&INHERITABLE != 0 {
+ c.data.data[i].inheritable |= 1 << uint(what)
+ }
+ }
+}
+
+func (c *capsFile) Unset(which CapType, caps ...Cap) {
+ for _, what := range caps {
+ var i uint
+ if what > 31 {
+ if c.data.version == 1 {
+ continue
+ }
+ i = uint(what) >> 5
+ what %= 32
+ }
+
+ if which&EFFECTIVE != 0 {
+ c.data.effective[i] &= ^(1 << uint(what))
+ }
+ if which&PERMITTED != 0 {
+ c.data.data[i].permitted &= ^(1 << uint(what))
+ }
+ if which&INHERITABLE != 0 {
+ c.data.data[i].inheritable &= ^(1 << uint(what))
+ }
+ }
+}
+
+func (c *capsFile) Fill(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data.effective[0] = 0xffffffff
+ c.data.data[0].permitted = 0xffffffff
+ c.data.data[0].inheritable = 0
+ if c.data.version == 2 {
+ c.data.effective[1] = 0xffffffff
+ c.data.data[1].permitted = 0xffffffff
+ c.data.data[1].inheritable = 0
+ }
+ }
+}
+
+func (c *capsFile) Clear(kind CapType) {
+ if kind&CAPS == CAPS {
+ c.data.effective[0] = 0
+ c.data.data[0].permitted = 0
+ c.data.data[0].inheritable = 0
+ if c.data.version == 2 {
+ c.data.effective[1] = 0
+ c.data.data[1].permitted = 0
+ c.data.data[1].inheritable = 0
+ }
+ }
+}
+
+func (c *capsFile) StringCap(which CapType) (ret string) {
+ return mkStringCap(c, which)
+}
+
+func (c *capsFile) String() (ret string) {
+ return mkString(c, INHERITABLE)
+}
+
+func (c *capsFile) Load() (err error) {
+ return getVfsCap(c.path, &c.data)
+}
+
+func (c *capsFile) Apply(kind CapType) (err error) {
+ if kind&CAPS == CAPS {
+ return setVfsCap(c.path, &c.data)
+ }
+ return
+}