Update to a released version of opencontainers/selinux (1.3.3)

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
Davanum Srinivas 2020-02-28 11:34:40 -05:00
parent 4d242818bf
commit 026e43806a
No known key found for this signature in database
GPG Key ID: 80D83A796103BF59
4 changed files with 104 additions and 113 deletions

View File

@ -66,7 +66,7 @@ github.com/google/gofuzz f140a6486e521aad38f5917de355
github.com/json-iterator/go 03217c3e97663914aec3faafde50d081f197a0a2 # v1.1.8 github.com/json-iterator/go 03217c3e97663914aec3faafde50d081f197a0a2 # v1.1.8
github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3 github.com/modern-go/concurrent bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94 # 1.0.3
github.com/modern-go/reflect2 4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd # 1.0.1 github.com/modern-go/reflect2 4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd # 1.0.1
github.com/opencontainers/selinux 5215b1806f52b1fcc2070a8826c542c9d33cd3cf github.com/opencontainers/selinux 31f70552238c5e017d78c3f1ba65e85f593f48e0 # 1.3.3
github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1 github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1
github.com/stretchr/testify 221dbe5ed46703ee255b1da0dec05086f5035f62 # v1.4.0 github.com/stretchr/testify 221dbe5ed46703ee255b1da0dec05086f5035f62 # v1.4.0
github.com/tchap/go-patricia 666120de432aea38ab06bd5c818f04f4129882c9 # v2.2.6 github.com/tchap/go-patricia 666120de432aea38ab06bd5c818f04f4129882c9 # v2.2.6

View File

@ -7,11 +7,11 @@ import (
"bytes" "bytes"
"crypto/rand" "crypto/rand"
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strconv" "strconv"
@ -19,6 +19,7 @@ import (
"sync" "sync"
"syscall" "syscall"
"github.com/pkg/errors"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -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
@ -289,7 +287,10 @@ func SetFileLabel(fpath string, label string) error {
if fpath == "" { if fpath == "" {
return ErrEmptyPath return ErrEmptyPath
} }
return lsetxattr(fpath, xattrNameSelinux, []byte(label), 0) if err := lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
return errors.Wrapf(err, "failed to set file label on %s", fpath)
}
return nil
} }
// FileLabel returns the SELinux label for this path or returns an error. // FileLabel returns the SELinux label for this path or returns an error.
@ -314,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)
} }
/* /*
@ -322,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.
@ -340,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
} }
@ -359,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 != "" {
@ -370,7 +369,36 @@ func writeCon(fpath string, val string) error {
} else { } else {
_, err = out.Write(nil) _, err = out.Write(nil)
} }
return err if err != nil {
return errors.Wrapf(err, "failed to set %s on procfs", fpath)
}
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)
} }
/* /*
@ -409,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)
} }
/* /*
@ -417,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
@ -443,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
@ -499,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
} }
@ -523,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)
} }
/* /*
@ -705,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
} }

8
vendor/github.com/opencontainers/selinux/go.mod generated vendored Normal file
View File

@ -0,0 +1,8 @@
module github.com/opencontainers/selinux
go 1.13
require (
github.com/pkg/errors v0.8.1
golang.org/x/sys v0.0.0-20191115151921-52ab43148777
)