Browse Source

Merge pull request #40907 from thaJeztah/bump_selinux

vendor: opencontainers/selinux v1.5.1
Brian Goff 5 years ago
parent
commit
47d9489e7c

+ 2 - 4
daemon/container.go

@@ -23,7 +23,7 @@ import (
 	"github.com/docker/docker/runconfig"
 	volumemounts "github.com/docker/docker/volume/mounts"
 	"github.com/docker/go-connections/nat"
-	"github.com/opencontainers/selinux/go-selinux/label"
+	"github.com/opencontainers/selinux/go-selinux"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
@@ -97,9 +97,7 @@ func (daemon *Daemon) load(id string) (*container.Container, error) {
 	if err := ctr.FromDisk(); err != nil {
 		return nil, err
 	}
-	if err := label.ReserveLabel(ctr.ProcessLabel); err != nil {
-		return nil, err
-	}
+	selinux.ReserveLabel(ctr.ProcessLabel)
 
 	if ctr.ID != id {
 		return ctr, fmt.Errorf("Container %s is stored at %s", ctr.ID, id)

+ 4 - 4
daemon/create.go

@@ -16,7 +16,7 @@ import (
 	"github.com/docker/docker/pkg/idtools"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/runconfig"
-	"github.com/opencontainers/selinux/go-selinux/label"
+	"github.com/opencontainers/selinux/go-selinux"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 )
@@ -247,7 +247,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 	pidMode := hostConfig.PidMode
 	privileged := hostConfig.Privileged
 	if ipcMode.IsHost() || pidMode.IsHost() || privileged {
-		return toHostConfigSelinuxLabels(label.DisableSecOpt()), nil
+		return toHostConfigSelinuxLabels(selinux.DisableSecOpt()), nil
 	}
 
 	var ipcLabel []string
@@ -259,7 +259,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 		if err != nil {
 			return nil, err
 		}
-		ipcLabel, err = label.DupSecOpt(c.ProcessLabel)
+		ipcLabel, err = selinux.DupSecOpt(c.ProcessLabel)
 		if err != nil {
 			return nil, err
 		}
@@ -273,7 +273,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 			return nil, err
 		}
 
-		pidLabel, err = label.DupSecOpt(c.ProcessLabel)
+		pidLabel, err = selinux.DupSecOpt(c.ProcessLabel)
 		if err != nil {
 			return nil, err
 		}

+ 1 - 1
vendor.conf

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

+ 51 - 83
vendor/github.com/opencontainers/selinux/go-selinux/label/label.go

@@ -1,109 +1,77 @@
-// +build !selinux !linux
-
 package label
 
-// InitLabels returns the process label and file labels to be used within
-// the container.  A list of options can be passed into this function to alter
-// the labels.
-func InitLabels(options []string) (string, string, error) {
-	return "", "", nil
-}
-
-func ROMountLabel() string {
-	return ""
-}
-
-func GenLabels(options string) (string, string, error) {
-	return "", "", nil
-}
+import (
+	"github.com/opencontainers/selinux/go-selinux"
+)
 
-func FormatMountLabel(src string, mountLabel string) string {
-	return src
-}
+// Deprecated: use selinux.ROFileLabel
+var ROMountLabel = selinux.ROFileLabel
 
-func SetProcessLabel(processLabel string) error {
-	return nil
-}
+// SetProcessLabel takes a process label and tells the kernel to assign the
+// label to the next program executed by the current process.
+// Deprecated: use selinux.SetExecLabel
+var SetProcessLabel = selinux.SetExecLabel
 
-func ProcessLabel() (string, error) {
-	return "", nil
-}
+// ProcessLabel returns the process label that the kernel will assign
+// to the next program executed by the current process.  If "" is returned
+// this indicates that the default labeling will happen for the process.
+// Deprecated: use selinux.ExecLabel
+var ProcessLabel = selinux.ExecLabel
 
-func SetSocketLabel(processLabel string) error {
-	return nil
-}
+// SetSocketLabel takes a process label and tells the kernel to assign the
+// label to the next socket that gets created
+// Deprecated: use selinux.SetSocketLabel
+var SetSocketLabel = selinux.SetSocketLabel
 
-func SocketLabel() (string, error) {
-	return "", nil
-}
+// SocketLabel retrieves the current default socket label setting
+// Deprecated: use selinux.SocketLabel
+var SocketLabel = selinux.SocketLabel
 
-func SetKeyLabel(processLabel string) error {
-	return nil
-}
+// SetKeyLabel takes a process label and tells the kernel to assign the
+// label to the next kernel keyring that gets created
+// Deprecated: use selinux.SetKeyLabel
+var SetKeyLabel = selinux.SetKeyLabel
 
-func KeyLabel() (string, error) {
-	return "", nil
-}
+// KeyLabel retrieves the current default kernel keyring label setting
+// Deprecated: use selinux.KeyLabel
+var KeyLabel = selinux.KeyLabel
 
-func FileLabel(path string) (string, error) {
-	return "", nil
-}
+// FileLabel returns the label for specified path
+// Deprecated: use selinux.FileLabel
+var FileLabel = selinux.FileLabel
 
-func SetFileLabel(path string, fileLabel string) error {
-	return nil
-}
-
-func SetFileCreateLabel(fileLabel string) error {
-	return nil
-}
-
-func Relabel(path string, fileLabel string, shared bool) error {
-	return nil
-}
-
-func PidLabel(pid int) (string, error) {
-	return "", nil
-}
+// PidLabel will return the label of the process running with the specified pid
+// Deprecated: use selinux.PidLabel
+var PidLabel = selinux.PidLabel
 
+// Init initialises the labeling system
 func Init() {
+	selinux.GetEnabled()
 }
 
-// ClearLabels clears all reserved labels
-func ClearLabels() {
-	return
-}
+// ClearLabels will clear all reserved labels
+// Deprecated: use selinux.ClearLabels
+var ClearLabels = selinux.ClearLabels
 
+// ReserveLabel will record the fact that the MCS label has already been used.
+// This will prevent InitLabels from using the MCS label in a newly created
+// container
+// Deprecated: use selinux.ReserveLabel
 func ReserveLabel(label string) error {
+	selinux.ReserveLabel(label)
 	return nil
 }
 
+// ReleaseLabel will remove the reservation of the MCS label.
+// This will allow InitLabels to use the MCS label in a newly created
+// containers
+// Deprecated: use selinux.ReleaseLabel
 func ReleaseLabel(label string) error {
+	selinux.ReleaseLabel(label)
 	return nil
 }
 
 // DupSecOpt takes a process label and returns security options that
 // can be used to set duplicate labels on future container processes
-func DupSecOpt(src string) ([]string, error) {
-	return nil, nil
-}
-
-// DisableSecOpt returns a security opt that can disable labeling
-// support for future container processes
-func DisableSecOpt() []string {
-	return nil
-}
-
-// Validate checks that the label does not include unexpected options
-func Validate(label string) error {
-	return nil
-}
-
-// RelabelNeeded checks whether the user requested a relabel
-func RelabelNeeded(label string) bool {
-	return false
-}
-
-// IsShared checks that the label includes a "shared" mark
-func IsShared(label string) bool {
-	return false
-}
+// Deprecated: use selinux.DupSecOpt
+var DupSecOpt = selinux.DupSecOpt

+ 19 - 103
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go

@@ -9,6 +9,7 @@ import (
 	"strings"
 
 	"github.com/opencontainers/selinux/go-selinux"
+	"github.com/pkg/errors"
 )
 
 // Valid Label Options
@@ -21,7 +22,7 @@ var validOptions = map[string]bool{
 	"level":    true,
 }
 
-var ErrIncompatibleLabel = fmt.Errorf("Bad SELinux option z and Z can not be used together")
+var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
 
 // InitLabels returns the process label and file labels to be used within
 // the container.  A list of options can be passed into this function to alter
@@ -35,7 +36,7 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
 	if processLabel != "" {
 		defer func() {
 			if Err != nil {
-				ReleaseLabel(mountLabel)
+				selinux.ReleaseLabel(mountLabel)
 			}
 		}()
 		pcon, err := selinux.NewContext(processLabel)
@@ -52,11 +53,11 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
 				return "", mountLabel, nil
 			}
 			if i := strings.Index(opt, ":"); i == -1 {
-				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
+				return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
 			}
 			con := strings.SplitN(opt, ":", 2)
 			if !validOptions[con[0]] {
-				return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
+				return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
 
 			}
 			if con[0] == "filetype" {
@@ -67,19 +68,16 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
 				mcon[con[0]] = con[1]
 			}
 		}
-		_ = ReleaseLabel(processLabel)
+		selinux.ReleaseLabel(processLabel)
 		processLabel = pcon.Get()
 		mountLabel = mcon.Get()
-		_ = ReserveLabel(processLabel)
+		selinux.ReserveLabel(processLabel)
 	}
 	return processLabel, mountLabel, nil
 }
 
-func ROMountLabel() string {
-	return selinux.ROFileLabel()
-}
-
-// DEPRECATED: The GenLabels function is only to be used during the transition to the official API.
+// Deprecated: The GenLabels function is only to be used during the transition
+// to the official API. Use InitLabels(strings.Fields(options)) instead.
 func GenLabels(options string) (string, string, error) {
 	return InitLabels(strings.Fields(options))
 }
@@ -102,71 +100,27 @@ func FormatMountLabel(src, mountLabel string) string {
 	return src
 }
 
-// SetProcessLabel takes a process label and tells the kernel to assign the
-// label to the next program executed by the current process.
-func SetProcessLabel(processLabel string) error {
-	return selinux.SetExecLabel(processLabel)
-}
-
-// SetSocketLabel takes a process label and tells the kernel to assign the
-// label to the next socket that gets created
-func SetSocketLabel(processLabel string) error {
-	return selinux.SetSocketLabel(processLabel)
-}
-
-// SocketLabel retrieves the current default socket label setting
-func SocketLabel() (string, error) {
-	return selinux.SocketLabel()
-}
-
-// SetKeyLabel takes a process label and tells the kernel to assign the
-// label to the next kernel keyring that gets created
-func SetKeyLabel(processLabel string) error {
-	return selinux.SetKeyLabel(processLabel)
-}
-
-// KeyLabel retrieves the current default kernel keyring label setting
-func KeyLabel() (string, error) {
-	return selinux.KeyLabel()
-}
-
-// ProcessLabel returns the process label that the kernel will assign
-// to the next program executed by the current process.  If "" is returned
-// this indicates that the default labeling will happen for the process.
-func ProcessLabel() (string, error) {
-	return selinux.ExecLabel()
-}
-
-// FileLabel returns the label for specified path
-func FileLabel(path string) (string, error) {
-	return selinux.FileLabel(path)
-}
-
 // SetFileLabel modifies the "path" label to the specified file label
 func SetFileLabel(path string, fileLabel string) error {
-	if selinux.GetEnabled() && fileLabel != "" {
-		return selinux.SetFileLabel(path, fileLabel)
+	if !selinux.GetEnabled() || fileLabel == "" {
+		return nil
 	}
-	return nil
+	return selinux.SetFileLabel(path, fileLabel)
 }
 
 // SetFileCreateLabel tells the kernel the label for all files to be created
 func SetFileCreateLabel(fileLabel string) error {
-	if selinux.GetEnabled() {
-		return selinux.SetFSCreateLabel(fileLabel)
+	if !selinux.GetEnabled() {
+		return nil
 	}
-	return nil
+	return selinux.SetFSCreateLabel(fileLabel)
 }
 
 // Relabel changes the label of path to the filelabel string.
 // It changes the MCS label to s0 if shared is true.
 // This will allow all containers to share the content.
 func Relabel(path string, fileLabel string, shared bool) error {
-	if !selinux.GetEnabled() {
-		return nil
-	}
-
-	if fileLabel == "" {
+	if !selinux.GetEnabled() || fileLabel == "" {
 		return nil
 	}
 
@@ -211,7 +165,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
 		path = strings.TrimSuffix(path, "/")
 	}
 	if exclude_paths[path] {
-		return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
+		return errors.Errorf("SELinux relabeling of %s is not allowed", path)
 	}
 
 	if shared {
@@ -229,48 +183,10 @@ func Relabel(path string, fileLabel string, shared bool) error {
 	return nil
 }
 
-// PidLabel will return the label of the process running with the specified pid
-func PidLabel(pid int) (string, error) {
-	return selinux.PidLabel(pid)
-}
-
-// Init initialises the labeling system
-func Init() {
-	selinux.GetEnabled()
-}
-
-// ClearLabels will clear all reserved labels
-func ClearLabels() {
-	selinux.ClearLabels()
-}
-
-// ReserveLabel will record the fact that the MCS label has already been used.
-// This will prevent InitLabels from using the MCS label in a newly created
-// container
-func ReserveLabel(label string) error {
-	selinux.ReserveLabel(label)
-	return nil
-}
-
-// ReleaseLabel will remove the reservation of the MCS label.
-// This will allow InitLabels to use the MCS label in a newly created
-// containers
-func ReleaseLabel(label string) error {
-	selinux.ReleaseLabel(label)
-	return nil
-}
-
-// DupSecOpt takes a process label and returns security options that
-// can be used to set duplicate labels on future container processes
-func DupSecOpt(src string) ([]string, error) {
-	return selinux.DupSecOpt(src)
-}
-
 // DisableSecOpt returns a security opt that can disable labeling
 // support for future container processes
-func DisableSecOpt() []string {
-	return selinux.DisableSecOpt()
-}
+// Deprecated: use selinux.DisableSecOpt
+var DisableSecOpt = selinux.DisableSecOpt
 
 // Validate checks that the label does not include unexpected options
 func Validate(label string) error {

+ 54 - 0
vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go

@@ -0,0 +1,54 @@
+// +build !selinux !linux
+
+package label
+
+// InitLabels returns the process label and file labels to be used within
+// the container.  A list of options can be passed into this function to alter
+// the labels.
+func InitLabels(options []string) (string, string, error) {
+	return "", "", nil
+}
+
+// Deprecated: The GenLabels function is only to be used during the transition
+// to the official API. Use InitLabels(strings.Fields(options)) instead.
+func GenLabels(options string) (string, string, error) {
+	return "", "", nil
+}
+
+func FormatMountLabel(src string, mountLabel string) string {
+	return src
+}
+
+func SetFileLabel(path string, fileLabel string) error {
+	return nil
+}
+
+func SetFileCreateLabel(fileLabel string) error {
+	return nil
+}
+
+func Relabel(path string, fileLabel string, shared bool) error {
+	return nil
+}
+
+// DisableSecOpt returns a security opt that can disable labeling
+// support for future container processes
+func DisableSecOpt() []string {
+	// TODO the selinux.DisableSecOpt stub returns []string{"disable"} instead of "nil"
+	return nil
+}
+
+// Validate checks that the label does not include unexpected options
+func Validate(label string) error {
+	return nil
+}
+
+// RelabelNeeded checks whether the user requested a relabel
+func RelabelNeeded(label string) bool {
+	return false
+}
+
+// IsShared checks that the label includes a "shared" mark
+func IsShared(label string) bool {
+	return false
+}

+ 118 - 48
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go

@@ -17,8 +17,8 @@ import (
 	"strconv"
 	"strings"
 	"sync"
-	"syscall"
 
+	"github.com/opencontainers/selinux/pkg/pwalk"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 )
@@ -31,13 +31,13 @@ const (
 	// Disabled constant to indicate SELinux is disabled
 	Disabled = -1
 
+	contextFile      = "/usr/share/containers/selinux/contexts"
 	selinuxDir       = "/etc/selinux/"
 	selinuxConfig    = selinuxDir + "config"
 	selinuxfsMount   = "/sys/fs/selinux"
 	selinuxTypeTag   = "SELINUXTYPE"
 	selinuxTag       = "SELINUX"
 	xattrNameSelinux = "security.selinux"
-	stRdOnly         = 0x01
 )
 
 type selinuxState struct {
@@ -103,13 +103,13 @@ func SetDisabled() {
 }
 
 func verifySELinuxfsMount(mnt string) bool {
-	var buf syscall.Statfs_t
+	var buf unix.Statfs_t
 	for {
-		err := syscall.Statfs(mnt, &buf)
+		err := unix.Statfs(mnt, &buf)
 		if err == nil {
 			break
 		}
-		if err == syscall.EAGAIN {
+		if err == unix.EAGAIN {
 			continue
 		}
 		return false
@@ -118,7 +118,7 @@ func verifySELinuxfsMount(mnt string) bool {
 	if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
 		return false
 	}
-	if (buf.Flags & stRdOnly) != 0 {
+	if (buf.Flags & unix.ST_RDONLY) != 0 {
 		return false
 	}
 
@@ -251,10 +251,10 @@ func isProcHandle(fh *os.File) error {
 	var buf unix.Statfs_t
 	err := unix.Fstatfs(int(fh.Fd()), &buf)
 	if err != nil {
-		return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err)
+		return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
 	}
 	if buf.Type != unix.PROC_SUPER_MAGIC {
-		return fmt.Errorf("file %q is not on procfs", fh.Name())
+		return errors.Errorf("file %q is not on procfs", fh.Name())
 	}
 
 	return nil
@@ -282,12 +282,29 @@ func readCon(fpath string) (string, error) {
 	return strings.Trim(retval, "\x00"), nil
 }
 
+// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error
+func ClassIndex(class string) (int, error) {
+	permpath := fmt.Sprintf("class/%s/index", class)
+	indexpath := filepath.Join(getSelinuxMountPoint(), permpath)
+
+	indexB, err := ioutil.ReadFile(indexpath)
+	if err != nil {
+		return -1, err
+	}
+	index, err := strconv.Atoi(string(indexB))
+	if err != nil {
+		return -1, err
+	}
+
+	return index, nil
+}
+
 // SetFileLabel sets the SELinux label for this path or returns an error.
 func SetFileLabel(fpath string, label string) error {
 	if fpath == "" {
 		return ErrEmptyPath
 	}
-	if err := lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
+	if err := unix.Lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
 		return errors.Wrapf(err, "failed to set file label on %s", fpath)
 	}
 	return nil
@@ -390,7 +407,7 @@ func attrPath(attr string) string {
 		return path.Join(threadSelfPrefix, attr)
 	}
 
-	return path.Join("/proc/self/task/", strconv.Itoa(syscall.Gettid()), "/attr/", attr)
+	return path.Join("/proc/self/task/", strconv.Itoa(unix.Gettid()), "/attr/", attr)
 }
 
 func readAttr(attr string) (string, error) {
@@ -410,6 +427,18 @@ func CanonicalizeContext(val string) (string, error) {
 	return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
 }
 
+/*
+ComputeCreateContext requests the type transition from source to target for class  from the kernel.
+*/
+func ComputeCreateContext(source string, target string, class string) (string, error) {
+	classidx, err := ClassIndex(class)
+	if err != nil {
+		return "", err
+	}
+
+	return readWriteCon(filepath.Join(getSelinuxMountPoint(), "create"), fmt.Sprintf("%s %s %d", source, target, classidx))
+}
+
 func readWriteCon(fpath string, val string) (string, error) {
 	if fpath == "" {
 		return "", ErrEmptyPath
@@ -461,17 +490,17 @@ func SocketLabel() (string, error) {
 
 // PeerLabel retrieves the label of the client on the other side of a socket
 func PeerLabel(fd uintptr) (string, error) {
-	return unix.GetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERSEC)
+	return unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
 }
 
 // SetKeyLabel takes a process label and tells the kernel to assign the
 // label to the next kernel keyring that gets created
 func SetKeyLabel(label string) error {
 	err := writeCon("/proc/self/attr/keycreate", label)
-	if os.IsNotExist(err) {
+	if os.IsNotExist(errors.Cause(err)) {
 		return nil
 	}
-	if label == "" && os.IsPermission(err) {
+	if label == "" && os.IsPermission(errors.Cause(err)) {
 		return nil
 	}
 	return err
@@ -656,23 +685,26 @@ func ROFileLabel() string {
 	return roFileLabel
 }
 
-/*
-ContainerLabels returns an allocated processLabel and fileLabel to be used for
-container labeling by the calling process.
-*/
-func ContainerLabels() (processLabel string, fileLabel string) {
+func openContextFile() (*os.File, error) {
+	if f, err := os.Open(contextFile); err == nil {
+		return f, nil
+	}
+	lxcPath := filepath.Join(getSELinuxPolicyRoot(), "/contexts/lxc_contexts")
+	return os.Open(lxcPath)
+}
+
+var labels = loadLabels()
+
+func loadLabels() map[string]string {
 	var (
 		val, key string
 		bufin    *bufio.Reader
 	)
 
-	if !GetEnabled() {
-		return "", ""
-	}
-	lxcPath := fmt.Sprintf("%s/contexts/lxc_contexts", getSELinuxPolicyRoot())
-	in, err := os.Open(lxcPath)
+	labels := make(map[string]string)
+	in, err := openContextFile()
 	if err != nil {
-		return "", ""
+		return labels
 	}
 	defer in.Close()
 
@@ -684,7 +716,7 @@ func ContainerLabels() (processLabel string, fileLabel string) {
 			if err == io.EOF {
 				done = true
 			} else {
-				goto exit
+				break
 			}
 		}
 		line = strings.TrimSpace(line)
@@ -698,26 +730,64 @@ func ContainerLabels() (processLabel string, fileLabel string) {
 		}
 		if groups := assignRegex.FindStringSubmatch(line); groups != nil {
 			key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
-			if key == "process" {
-				processLabel = strings.Trim(val, "\"")
-			}
-			if key == "file" {
-				fileLabel = strings.Trim(val, "\"")
-			}
-			if key == "ro_file" {
-				roFileLabel = strings.Trim(val, "\"")
-			}
+			labels[key] = strings.Trim(val, "\"")
 		}
 	}
 
-	if processLabel == "" || fileLabel == "" {
+	return labels
+}
+
+/*
+KVMContainerLabels returns the default processLabel and mountLabel to be used
+for kvm containers by the calling process.
+*/
+func KVMContainerLabels() (string, string) {
+	processLabel := labels["kvm_process"]
+	if processLabel == "" {
+		processLabel = labels["process"]
+	}
+
+	return addMcs(processLabel, labels["file"])
+}
+
+/*
+InitContainerLabels returns the default processLabel and file labels to be
+used for containers running an init system like systemd by the calling process.
+*/
+func InitContainerLabels() (string, string) {
+	processLabel := labels["init_process"]
+	if processLabel == "" {
+		processLabel = labels["process"]
+	}
+
+	return addMcs(processLabel, labels["file"])
+}
+
+/*
+ContainerLabels returns an allocated processLabel and fileLabel to be used for
+container labeling by the calling process.
+*/
+func ContainerLabels() (processLabel string, fileLabel string) {
+	if !GetEnabled() {
 		return "", ""
 	}
 
+	processLabel = labels["process"]
+	fileLabel = labels["file"]
+	roFileLabel = labels["ro_file"]
+
+	if processLabel == "" || fileLabel == "" {
+		return "", fileLabel
+	}
+
 	if roFileLabel == "" {
 		roFileLabel = fileLabel
 	}
-exit:
+
+	return addMcs(processLabel, fileLabel)
+}
+
+func addMcs(processLabel, fileLabel string) (string, string) {
 	scon, _ := NewContext(processLabel)
 	if scon["level"] != "" {
 		mcs := uniqMcs(1024)
@@ -772,14 +842,14 @@ func badPrefix(fpath string) error {
 	badPrefixes := []string{"/usr"}
 	for _, prefix := range badPrefixes {
 		if strings.HasPrefix(fpath, prefix) {
-			return fmt.Errorf("relabeling content in %s is not allowed", prefix)
+			return errors.Errorf("relabeling content in %s is not allowed", prefix)
 		}
 	}
 	return nil
 }
 
-// Chcon changes the `fpath` file object to the SELinux label `label`.
-// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
+// Chcon changes the fpath file object to the SELinux label label.
+// If fpath is a directory and recurse is true, Chcon will walk the
 // directory tree setting the label.
 func Chcon(fpath string, label string, recurse bool) error {
 	if fpath == "" {
@@ -791,19 +861,19 @@ func Chcon(fpath string, label string, recurse bool) error {
 	if err := badPrefix(fpath); err != nil {
 		return err
 	}
-	callback := func(p string, info os.FileInfo, err error) error {
+
+	if !recurse {
+		return SetFileLabel(fpath, label)
+	}
+
+	return pwalk.Walk(fpath, func(p string, info os.FileInfo, err error) error {
 		e := SetFileLabel(p, label)
-		if os.IsNotExist(e) {
+		// Walk a file tree can race with removal, so ignore ENOENT
+		if os.IsNotExist(errors.Cause(e)) {
 			return nil
 		}
 		return e
-	}
-
-	if recurse {
-		return filepath.Walk(fpath, callback)
-	}
-
-	return SetFileLabel(fpath, label)
+	})
 }
 
 // DupSecOpt takes an SELinux process label and returns security options that

+ 26 - 2
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go

@@ -1,4 +1,4 @@
-// +build !selinux
+// +build !selinux !linux
 
 package selinux
 
@@ -35,6 +35,11 @@ func GetEnabled() bool {
 	return false
 }
 
+// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error
+func ClassIndex(class string) (int, error) {
+	return -1, nil
+}
+
 // SetFileLabel sets the SELinux label for this path or returns an error.
 func SetFileLabel(fpath string, label string) error {
 	return nil
@@ -88,6 +93,13 @@ func CanonicalizeContext(val string) (string, error) {
 	return "", nil
 }
 
+/*
+ComputeCreateContext requests the type transition from source to target for class  from the kernel.
+*/
+func ComputeCreateContext(source string, target string, class string) (string, error) {
+	return "", nil
+}
+
 /*
 SetExecLabel sets the SELinux label that the kernel will use for any programs
 that are executed by the current process thread, or an error.
@@ -101,7 +113,7 @@ SetTaskLabel sets the SELinux label for the current thread, or an error.
 This requires the dyntransition permission.
 */
 func SetTaskLabel(label string) error {
-        return nil
+	return nil
 }
 
 /*
@@ -189,6 +201,18 @@ func ROFileLabel() string {
 	return ""
 }
 
+// KVMContainerLabels returns the default processLabel and mountLabel to be used
+// for kvm containers by the calling process.
+func KVMContainerLabels() (string, string) {
+	return "", ""
+}
+
+// InitContainerLabels returns the default processLabel and file labels to be
+// used for containers running an init system like systemd by the calling
+func InitContainerLabels() (string, string) {
+	return "", ""
+}
+
 /*
 ContainerLabels returns an allocated processLabel and fileLabel to be used for
 container labeling by the calling process.

+ 2 - 6
vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go

@@ -12,8 +12,8 @@ func lgetxattr(path string, attr string) ([]byte, error) {
 	// Start with a 128 length byte array
 	dest := make([]byte, 128)
 	sz, errno := unix.Lgetxattr(path, attr, dest)
-	if errno == unix.ERANGE {
-		// Buffer too small, get the real size first
+	for errno == unix.ERANGE {
+		// Buffer too small, use zero-sized buffer to get the actual size
 		sz, errno = unix.Lgetxattr(path, attr, []byte{})
 		if errno != nil {
 			return nil, errno
@@ -28,7 +28,3 @@ func lgetxattr(path string, attr string) ([]byte, error) {
 
 	return dest[:sz], nil
 }
-
-func lsetxattr(path string, attr string, data []byte, flags int) error {
-	return unix.Lsetxattr(path, attr, data, flags)
-}

+ 42 - 0
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md

@@ -0,0 +1,42 @@
+## pwalk: parallel implementation of filepath.Walk
+
+This is a wrapper for [filepath.Walk](https://pkg.go.dev/path/filepath?tab=doc#Walk)
+which may speed it up by calling multiple callback functions (WalkFunc) in parallel,
+utilizing goroutines.
+
+By default, it utilizes 2\*runtime.NumCPU() goroutines for callbacks.
+This can be changed by using WalkN function which has the additional
+parameter, specifying the number of goroutines (concurrency).
+
+### Caveats
+
+Please note the following limitations of this code:
+
+* Unlike filepath.Walk, the order of calls is non-deterministic;
+
+* Only primitive error handling is supported:
+
+  * filepath.SkipDir is not supported;
+
+  * no errors are ever passed to WalkFunc;
+
+  * once any error is returned from any WalkFunc instance, no more new calls
+    to WalkFunc are made, and the error is returned to the caller of Walk;
+
+  * if more than one walkFunc instance will return an error, only one
+    of such errors will be propagated and returned by Walk, others
+    will be silently discarded.
+
+### Documentation
+
+For the official documentation, see
+https://pkg.go.dev/github.com/opencontainers/selinux/pkg/pwalk?tab=doc
+
+### Benchmarks
+
+For a WalkFunc that consists solely of the return statement, this
+implementation is about 10% slower than the standard library's
+filepath.Walk.
+
+Otherwise (if a WalkFunc is doing something) this is usually faster,
+except when the WalkN(..., 1) is used.

+ 99 - 0
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go

@@ -0,0 +1,99 @@
+package pwalk
+
+import (
+	"os"
+	"path/filepath"
+	"runtime"
+	"sync"
+
+	"github.com/pkg/errors"
+)
+
+type WalkFunc = filepath.WalkFunc
+
+// Walk is a wrapper for filepath.Walk which can call multiple walkFn
+// in parallel, allowing to handle each item concurrently. A maximum of
+// twice the runtime.NumCPU() walkFn will be called at any one time.
+// If you want to change the maximum, use WalkN instead.
+//
+// The order of calls is non-deterministic.
+//
+// Note that this implementation only supports primitive error handling:
+//
+// * no errors are ever passed to WalkFn
+//
+// * once a walkFn returns any error, all further processing stops
+//   and the error is returned to the caller of Walk;
+//
+// * filepath.SkipDir is not supported;
+//
+// * if more than one walkFn instance will return an error, only one
+//   of such errors will be propagated and returned by Walk, others
+//   will be silently discarded.
+//
+func Walk(root string, walkFn WalkFunc) error {
+	return WalkN(root, walkFn, runtime.NumCPU()*2)
+}
+
+// WalkN is a wrapper for filepath.Walk which can call multiple walkFn
+// in parallel, allowing to handle each item concurrently. A maximum of
+// num walkFn will be called at any one time.
+func WalkN(root string, walkFn WalkFunc, num int) error {
+	// make sure limit is sensible
+	if num < 1 {
+		return errors.Errorf("walk(%q): num must be > 0", root)
+	}
+
+	files := make(chan *walkArgs, 2*num)
+	errCh := make(chan error, 1) // get the first error, ignore others
+
+	// Start walking a tree asap
+	var err error
+	go func() {
+		err = filepath.Walk(root, func(p string, info os.FileInfo, err error) error {
+			if err != nil {
+				close(files)
+				return err
+			}
+			// add a file to the queue unless a callback sent an error
+			select {
+			case e := <-errCh:
+				close(files)
+				return e
+			default:
+				files <- &walkArgs{path: p, info: &info}
+				return nil
+			}
+		})
+		if err == nil {
+			close(files)
+		}
+	}()
+
+	var wg sync.WaitGroup
+	wg.Add(num)
+	for i := 0; i < num; i++ {
+		go func() {
+			for file := range files {
+				if e := walkFn(file.path, *file.info, nil); e != nil {
+					select {
+					case errCh <- e: // sent ok
+					default: // buffer full
+					}
+				}
+			}
+			wg.Done()
+		}()
+	}
+
+	wg.Wait()
+
+	return err
+}
+
+// walkArgs holds the arguments that were passed to the Walk or WalkLimit
+// functions.
+type walkArgs struct {
+	path string
+	info *os.FileInfo
+}