Przeglądaj źródła

vendor: update opencontainers/selinux v1.3.3

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

- go-selinux/SetKeyLabel: fix for RHEL7 kernels
- getSELinuxfs: optimize/simplify using sync.Once
- xattr: use x/sys/unix, simplify
- Use /proc/thread-self if available
- Fix EnforceMode, SetEnforceMode, and SecurityCheckContext

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 5 lat temu
rodzic
commit
fa67cff34b

+ 1 - 1
vendor.conf

@@ -161,6 +161,6 @@ github.com/morikuni/aec                             39771216ff4c63d11f5e604076f9
 # metrics
 # metrics
 github.com/docker/go-metrics                        b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
 github.com/docker/go-metrics                        b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
 
 
-github.com/opencontainers/selinux                   4defb1c884d2f4f9c890c615380f20f7fc215cf3 # v1.3.1
+github.com/opencontainers/selinux                   31f70552238c5e017d78c3f1ba65e85f593f48e0 # v1.3.3
 
 
 # DO NOT EDIT BELOW THIS LINE -------- reserved for downstream projects --------
 # DO NOT EDIT BELOW THIS LINE -------- reserved for downstream projects --------

+ 72 - 51
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go

@@ -11,6 +11,7 @@ import (
 	"io"
 	"io"
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
+	"path"
 	"path/filepath"
 	"path/filepath"
 	"regexp"
 	"regexp"
 	"strconv"
 	"strconv"
@@ -37,15 +38,14 @@ 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
-	enabled      bool
-	selinuxfsSet bool
-	selinuxfs    string
-	mcsList      map[string]bool
+	enabledSet    bool
+	enabled       bool
+	selinuxfsOnce sync.Once
+	selinuxfs     string
+	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()
-	selinuxfs := s.selinuxfs
-	selinuxfsSet := s.selinuxfsSet
-	s.Unlock()
-	if selinuxfsSet {
-		return selinuxfs
-	}
+	s.selinuxfsOnce.Do(func() {
+		s.selinuxfs = findSELinuxfs()
+	})
 
 
-	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(enforceS))
+	enforce, err = strconv.Atoi(string(enforceB))
 	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)
 }
 }
 
 
 /*
 /*

+ 13 - 57
vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go

@@ -3,76 +3,32 @@
 package selinux
 package selinux
 
 
 import (
 import (
-	"syscall"
-	"unsafe"
+	"golang.org/x/sys/unix"
 )
 )
 
 
-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, sz)
-	destBytes := unsafe.Pointer(&dest[0])
-	_sz, _, errno := syscall.Syscall6(syscall.SYS_LGETXATTR, uintptr(unsafe.Pointer(pathBytes)), uintptr(unsafe.Pointer(attrBytes)), uintptr(destBytes), uintptr(len(dest)), 0, 0)
-
-	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 {
+	dest := make([]byte, 128)
+	sz, errno := unix.Lgetxattr(path, attr, dest)
+	if errno == unix.ERANGE {
+		// Buffer too small, get the real size first
+		sz, errno = unix.Lgetxattr(path, attr, []byte{})
+		if errno != nil {
 			return nil, errno
 			return nil, errno
 		}
 		}
+
 		dest = make([]byte, sz)
 		dest = make([]byte, sz)
-		destBytes := unsafe.Pointer(&dest[0])
-		_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 {
-			return nil, errno
-		}
-	case errno != 0:
+		sz, errno = unix.Lgetxattr(path, attr, dest)
+	}
+	if errno != nil {
 		return nil, errno
 		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)
-	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
+	return unix.Lsetxattr(path, attr, data, flags)
 }
 }