vendor: update opencontainers/selinux v1.3.3

full diff: https://github.com/opencontainers/selinux/compare/v1.3.1...v1.3.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2020-02-28 01:25:12 +01:00
parent 22e00ddc03
commit d8953334bb
3 changed files with 87 additions and 110 deletions

View File

@@ -6,7 +6,7 @@ github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4
# Core libcontainer functionality. # Core libcontainer functionality.
github.com/checkpoint-restore/go-criu 17b0214f6c48980c45dc47ecb0cfd6d9e02df723 # v3.11 github.com/checkpoint-restore/go-criu 17b0214f6c48980c45dc47ecb0cfd6d9e02df723 # v3.11
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
github.com/opencontainers/selinux 4defb1c884d2f4f9c890c615380f20f7fc215cf3 # v1.3.1 github.com/opencontainers/selinux 31f70552238c5e017d78c3f1ba65e85f593f48e0 # v1.3.3
github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1 github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1
github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1 github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2 github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2

View File

@@ -11,6 +11,7 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv" "strconv"
@@ -37,13 +38,12 @@ const (
selinuxTag = "SELINUX" selinuxTag = "SELINUX"
xattrNameSelinux = "security.selinux" xattrNameSelinux = "security.selinux"
stRdOnly = 0x01 stRdOnly = 0x01
selinuxfsMagic = 0xf97cff8c
) )
type selinuxState struct { type selinuxState struct {
enabledSet bool enabledSet bool
enabled bool enabled bool
selinuxfsSet bool selinuxfsOnce sync.Once
selinuxfs string selinuxfs string
mcsList map[string]bool mcsList map[string]bool
sync.Mutex sync.Mutex
@@ -62,6 +62,10 @@ var (
state = selinuxState{ state = selinuxState{
mcsList: make(map[string]bool), mcsList: make(map[string]bool),
} }
// for attrPath()
attrPathOnce sync.Once
haveThreadSelf bool
) )
// Context is a representation of the SELinux label broken into 4 parts // Context is a representation of the SELinux label broken into 4 parts
@@ -98,14 +102,6 @@ func SetDisabled() {
state.setEnable(false) state.setEnable(false)
} }
func (s *selinuxState) setSELinuxfs(selinuxfs string) string {
s.Lock()
defer s.Unlock()
s.selinuxfsSet = true
s.selinuxfs = selinuxfs
return s.selinuxfs
}
func verifySELinuxfsMount(mnt string) bool { func verifySELinuxfsMount(mnt string) bool {
var buf syscall.Statfs_t var buf syscall.Statfs_t
for { for {
@@ -118,7 +114,8 @@ func verifySELinuxfsMount(mnt string) bool {
} }
return false return false
} }
if uint32(buf.Type) != uint32(selinuxfsMagic) {
if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
return false return false
} }
if (buf.Flags & stRdOnly) != 0 { if (buf.Flags & stRdOnly) != 0 {
@@ -166,33 +163,29 @@ func findSELinuxfs() string {
// if there is one, or an empty string in case of EOF or error. // if there is one, or an empty string in case of EOF or error.
func findSELinuxfsMount(s *bufio.Scanner) string { func findSELinuxfsMount(s *bufio.Scanner) string {
for s.Scan() { for s.Scan() {
txt := s.Text() txt := s.Bytes()
// The first field after - is fs type. // The first field after - is fs type.
// Safe as spaces in mountpoints are encoded as \040 // Safe as spaces in mountpoints are encoded as \040
if !strings.Contains(txt, " - selinuxfs ") { if !bytes.Contains(txt, []byte(" - selinuxfs ")) {
continue continue
} }
const mPos = 5 // mount point is 5th field const mPos = 5 // mount point is 5th field
fields := strings.SplitN(txt, " ", mPos+1) fields := bytes.SplitN(txt, []byte(" "), mPos+1)
if len(fields) < mPos+1 { if len(fields) < mPos+1 {
continue continue
} }
return fields[mPos-1] return string(fields[mPos-1])
} }
return "" return ""
} }
func (s *selinuxState) getSELinuxfs() string { func (s *selinuxState) getSELinuxfs() string {
s.Lock() s.selinuxfsOnce.Do(func() {
selinuxfs := s.selinuxfs s.selinuxfs = findSELinuxfs()
selinuxfsSet := s.selinuxfsSet })
s.Unlock()
if selinuxfsSet {
return selinuxfs
}
return s.setSELinuxfs(findSELinuxfs()) return s.selinuxfs
} }
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs // getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
@@ -254,10 +247,17 @@ func getSELinuxPolicyRoot() string {
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag)) return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
} }
func isProcHandle(fh *os.File) (bool, error) { func isProcHandle(fh *os.File) error {
var buf unix.Statfs_t var buf unix.Statfs_t
err := unix.Fstatfs(int(fh.Fd()), &buf) err := unix.Fstatfs(int(fh.Fd()), &buf)
return buf.Type == unix.PROC_SUPER_MAGIC, err if err != nil {
return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err)
}
if buf.Type != unix.PROC_SUPER_MAGIC {
return fmt.Errorf("file %q is not on procfs", fh.Name())
}
return nil
} }
func readCon(fpath string) (string, error) { func readCon(fpath string) (string, error) {
@@ -271,10 +271,8 @@ func readCon(fpath string) (string, error) {
} }
defer in.Close() defer in.Close()
if ok, err := isProcHandle(in); err != nil { if err := isProcHandle(in); err != nil {
return "", err return "", err
} else if !ok {
return "", fmt.Errorf("%s not on procfs", fpath)
} }
var retval string var retval string
@@ -317,7 +315,7 @@ SetFSCreateLabel tells kernel the label to create all file system objects
created by this task. Setting label="" to return to default. created by this task. Setting label="" to return to default.
*/ */
func SetFSCreateLabel(label string) error { func SetFSCreateLabel(label string) error {
return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), label) return writeAttr("fscreate", label)
} }
/* /*
@@ -325,12 +323,12 @@ FSCreateLabel returns the default label the kernel which the kernel is using
for file system objects created by this task. "" indicates default. for file system objects created by this task. "" indicates default.
*/ */
func FSCreateLabel() (string, error) { func FSCreateLabel() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid())) return readAttr("fscreate")
} }
// CurrentLabel returns the SELinux label of the current process thread, or an error. // CurrentLabel returns the SELinux label of the current process thread, or an error.
func CurrentLabel() (string, error) { func CurrentLabel() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid())) return readAttr("current")
} }
// PidLabel returns the SELinux label of the given pid, or an error. // PidLabel returns the SELinux label of the given pid, or an error.
@@ -343,10 +341,10 @@ ExecLabel returns the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error. that are executed by the current process thread, or an error.
*/ */
func ExecLabel() (string, error) { func ExecLabel() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid())) return readAttr("exec")
} }
func writeCon(fpath string, val string) error { func writeCon(fpath, val string) error {
if fpath == "" { if fpath == "" {
return ErrEmptyPath return ErrEmptyPath
} }
@@ -362,10 +360,8 @@ func writeCon(fpath string, val string) error {
} }
defer out.Close() defer out.Close()
if ok, err := isProcHandle(out); err != nil { if err := isProcHandle(out); err != nil {
return err return err
} else if !ok {
return fmt.Errorf("%s not on procfs", fpath)
} }
if val != "" { if val != "" {
@@ -379,6 +375,32 @@ func writeCon(fpath string, val string) error {
return nil return nil
} }
func attrPath(attr string) string {
// Linux >= 3.17 provides this
const threadSelfPrefix = "/proc/thread-self/attr"
attrPathOnce.Do(func() {
st, err := os.Stat(threadSelfPrefix)
if err == nil && st.Mode().IsDir() {
haveThreadSelf = true
}
})
if haveThreadSelf {
return path.Join(threadSelfPrefix, attr)
}
return path.Join("/proc/self/task/", strconv.Itoa(syscall.Gettid()), "/attr/", attr)
}
func readAttr(attr string) (string, error) {
return readCon(attrPath(attr))
}
func writeAttr(attr, val string) error {
return writeCon(attrPath(attr), val)
}
/* /*
CanonicalizeContext takes a context string and writes it to the kernel CanonicalizeContext takes a context string and writes it to the kernel
the function then returns the context that the kernel will use. This function the function then returns the context that the kernel will use. This function
@@ -415,7 +437,7 @@ SetExecLabel sets the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error. that are executed by the current process thread, or an error.
*/ */
func SetExecLabel(label string) error { func SetExecLabel(label string) error {
return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), label) return writeAttr("exec", label)
} }
/* /*
@@ -423,18 +445,18 @@ SetTaskLabel sets the SELinux label for the current thread, or an error.
This requires the dyntransition permission. This requires the dyntransition permission.
*/ */
func SetTaskLabel(label string) error { func SetTaskLabel(label string) error {
return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/current", syscall.Gettid()), label) return writeAttr("current", label)
} }
// SetSocketLabel takes a process label and tells the kernel to assign the // SetSocketLabel takes a process label and tells the kernel to assign the
// label to the next socket that gets created // label to the next socket that gets created
func SetSocketLabel(label string) error { func SetSocketLabel(label string) error {
return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/sockcreate", syscall.Gettid()), label) return writeAttr("sockcreate", label)
} }
// SocketLabel retrieves the current socket label setting // SocketLabel retrieves the current socket label setting
func SocketLabel() (string, error) { func SocketLabel() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/sockcreate", syscall.Gettid())) return readAttr("sockcreate")
} }
// PeerLabel retrieves the label of the client on the other side of a socket // PeerLabel retrieves the label of the client on the other side of a socket
@@ -449,7 +471,7 @@ func SetKeyLabel(label string) error {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil return nil
} }
if label == "" && os.IsPermission(err) && !GetEnabled() { if label == "" && os.IsPermission(err) {
return nil return nil
} }
return err return err
@@ -505,19 +527,18 @@ func ReserveLabel(label string) {
} }
func selinuxEnforcePath() string { func selinuxEnforcePath() string {
return fmt.Sprintf("%s/enforce", getSelinuxMountPoint()) return path.Join(getSelinuxMountPoint(), "enforce")
} }
// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled // EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int { func EnforceMode() int {
var enforce int var enforce int
enforceS, err := readCon(selinuxEnforcePath()) enforceB, err := ioutil.ReadFile(selinuxEnforcePath())
if err != nil { if err != nil {
return -1 return -1
} }
enforce, err = strconv.Atoi(string(enforceB))
enforce, err = strconv.Atoi(string(enforceS))
if err != nil { if err != nil {
return -1 return -1
} }
@@ -529,7 +550,7 @@ SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time. Disabled is not valid, since this needs to be set at boot time.
*/ */
func SetEnforceMode(mode int) error { func SetEnforceMode(mode int) error {
return writeCon(selinuxEnforcePath(), fmt.Sprintf("%d", mode)) return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
} }
/* /*
@@ -711,7 +732,7 @@ exit:
// SecurityCheckContext validates that the SELinux label is understood by the kernel // SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error { func SecurityCheckContext(val string) error {
return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val) return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
} }
/* /*

View File

@@ -3,76 +3,32 @@
package selinux package selinux
import ( import (
"syscall" "golang.org/x/sys/unix"
"unsafe"
) )
var _zero uintptr
// Returns a []byte slice if the xattr is set and nil otherwise // Returns a []byte slice if the xattr is set and nil otherwise
// Requires path and its attribute as arguments // Requires path and its attribute as arguments
func lgetxattr(path string, attr string) ([]byte, error) { func lgetxattr(path string, attr string) ([]byte, error) {
var sz int
pathBytes, err := syscall.BytePtrFromString(path)
if err != nil {
return nil, err
}
attrBytes, err := syscall.BytePtrFromString(attr)
if err != nil {
return nil, err
}
// Start with a 128 length byte array // Start with a 128 length byte array
sz = 128 dest := make([]byte, 128)
dest := make([]byte, sz) sz, errno := unix.Lgetxattr(path, attr, dest)
destBytes := unsafe.Pointer(&dest[0]) if errno == unix.ERANGE {
_sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) // Buffer too small, get the real size first
sz, errno = unix.Lgetxattr(path, attr, []byte{})
if errno != nil {
return nil, errno
}
switch {
case errno == syscall.ENODATA:
return nil, errno
case errno == syscall.ENOTSUP:
return nil, errno
case errno == syscall.ERANGE:
// 128 byte array might just not be good enough,
// A dummy buffer is used ``uintptr(0)`` to get real size
// of the xattrs on disk
_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(unsafe.Pointer(nil)), uintptr(0), 0, 0)
sz = int(_sz)
if sz < 0 {
return nil, errno
}
dest = make([]byte, sz) dest = make([]byte, sz)
destBytes := unsafe.Pointer(&dest[0]) sz, errno = unix.Lgetxattr(path, attr, dest)
_sz, _, errno = syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0) }
if errno != 0 { if errno != nil {
return nil, errno return nil, errno
} }
case errno != 0:
return nil, errno
}
sz = int(_sz)
return dest[:sz], nil return dest[:sz], nil
} }
func lsetxattr(path string, attr string, data []byte, flags int) error { func lsetxattr(path string, attr string, data []byte, flags int) error {
pathBytes, err := syscall.BytePtrFromString(path) return unix.Lsetxattr(path, attr, data, flags)
if err != nil {
return err
}
attrBytes, err := syscall.BytePtrFromString(attr)
if err != nil {
return err
}
var dataBytes unsafe.Pointer
if len(data) > 0 {
dataBytes = unsafe.Pointer(&data[0])
} else {
dataBytes = unsafe.Pointer(&_zero)
}
_, _, errno := syscall.Syscall6(syscall.SYS_LSETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(dataBytes), uintptr(len(data)), uintptr(flags), 0)
if errno != 0 {
return errno
}
return nil
} }