Prechádzať zdrojové kódy

Merge pull request #40907 from thaJeztah/bump_selinux

vendor: opencontainers/selinux v1.5.1
Brian Goff 5 rokov pred
rodič
commit
47d9489e7c

+ 2 - 4
daemon/container.go

@@ -23,7 +23,7 @@ import (
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
 	volumemounts "github.com/docker/docker/volume/mounts"
 	volumemounts "github.com/docker/docker/volume/mounts"
 	"github.com/docker/go-connections/nat"
 	"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/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
@@ -97,9 +97,7 @@ func (daemon *Daemon) load(id string) (*container.Container, error) {
 	if err := ctr.FromDisk(); err != nil {
 	if err := ctr.FromDisk(); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
-	if err := label.ReserveLabel(ctr.ProcessLabel); err != nil {
-		return nil, err
-	}
+	selinux.ReserveLabel(ctr.ProcessLabel)
 
 
 	if ctr.ID != id {
 	if ctr.ID != id {
 		return ctr, fmt.Errorf("Container %s is stored at %s", 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/idtools"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/runconfig"
-	"github.com/opencontainers/selinux/go-selinux/label"
+	"github.com/opencontainers/selinux/go-selinux"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"github.com/sirupsen/logrus"
 	"github.com/sirupsen/logrus"
 )
 )
@@ -247,7 +247,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 	pidMode := hostConfig.PidMode
 	pidMode := hostConfig.PidMode
 	privileged := hostConfig.Privileged
 	privileged := hostConfig.Privileged
 	if ipcMode.IsHost() || pidMode.IsHost() || privileged {
 	if ipcMode.IsHost() || pidMode.IsHost() || privileged {
-		return toHostConfigSelinuxLabels(label.DisableSecOpt()), nil
+		return toHostConfigSelinuxLabels(selinux.DisableSecOpt()), nil
 	}
 	}
 
 
 	var ipcLabel []string
 	var ipcLabel []string
@@ -259,7 +259,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
-		ipcLabel, err = label.DupSecOpt(c.ProcessLabel)
+		ipcLabel, err = selinux.DupSecOpt(c.ProcessLabel)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}
@@ -273,7 +273,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
 			return nil, err
 			return nil, err
 		}
 		}
 
 
-		pidLabel, err = label.DupSecOpt(c.ProcessLabel)
+		pidLabel, err = selinux.DupSecOpt(c.ProcessLabel)
 		if err != nil {
 		if err != nil {
 			return nil, err
 			return nil, err
 		}
 		}

+ 1 - 1
vendor.conf

@@ -168,6 +168,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                   31f70552238c5e017d78c3f1ba65e85f593f48e0 # v1.3.3
+github.com/opencontainers/selinux                   0d49ba2a6aae052c614dfe5de62a158711a6c461 # v1.5.1
 
 
 # DO NOT EDIT BELOW THIS LINE -------- reserved for downstream projects --------
 # 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
 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() {
 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 {
 func ReserveLabel(label string) error {
+	selinux.ReserveLabel(label)
 	return nil
 	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 {
 func ReleaseLabel(label string) error {
+	selinux.ReleaseLabel(label)
 	return nil
 	return nil
 }
 }
 
 
 // DupSecOpt takes a process label and returns security options that
 // DupSecOpt takes a process label and returns security options that
 // can be used to set duplicate labels on future container processes
 // 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"
 	"strings"
 
 
 	"github.com/opencontainers/selinux/go-selinux"
 	"github.com/opencontainers/selinux/go-selinux"
+	"github.com/pkg/errors"
 )
 )
 
 
 // Valid Label Options
 // Valid Label Options
@@ -21,7 +22,7 @@ var validOptions = map[string]bool{
 	"level":    true,
 	"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
 // 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 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 != "" {
 	if processLabel != "" {
 		defer func() {
 		defer func() {
 			if Err != nil {
 			if Err != nil {
-				ReleaseLabel(mountLabel)
+				selinux.ReleaseLabel(mountLabel)
 			}
 			}
 		}()
 		}()
 		pcon, err := selinux.NewContext(processLabel)
 		pcon, err := selinux.NewContext(processLabel)
@@ -52,11 +53,11 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
 				return "", mountLabel, nil
 				return "", mountLabel, nil
 			}
 			}
 			if i := strings.Index(opt, ":"); i == -1 {
 			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)
 			con := strings.SplitN(opt, ":", 2)
 			if !validOptions[con[0]] {
 			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" {
 			if con[0] == "filetype" {
@@ -67,19 +68,16 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
 				mcon[con[0]] = con[1]
 				mcon[con[0]] = con[1]
 			}
 			}
 		}
 		}
-		_ = ReleaseLabel(processLabel)
+		selinux.ReleaseLabel(processLabel)
 		processLabel = pcon.Get()
 		processLabel = pcon.Get()
 		mountLabel = mcon.Get()
 		mountLabel = mcon.Get()
-		_ = ReserveLabel(processLabel)
+		selinux.ReserveLabel(processLabel)
 	}
 	}
 	return processLabel, mountLabel, nil
 	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) {
 func GenLabels(options string) (string, string, error) {
 	return InitLabels(strings.Fields(options))
 	return InitLabels(strings.Fields(options))
 }
 }
@@ -102,71 +100,27 @@ func FormatMountLabel(src, mountLabel string) string {
 	return src
 	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
 // SetFileLabel modifies the "path" label to the specified file label
 func SetFileLabel(path string, fileLabel string) error {
 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
 // SetFileCreateLabel tells the kernel the label for all files to be created
 func SetFileCreateLabel(fileLabel string) error {
 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.
 // Relabel changes the label of path to the filelabel string.
 // It changes the MCS label to s0 if shared is true.
 // It changes the MCS label to s0 if shared is true.
 // This will allow all containers to share the content.
 // This will allow all containers to share the content.
 func Relabel(path string, fileLabel string, shared bool) error {
 func Relabel(path string, fileLabel string, shared bool) error {
-	if !selinux.GetEnabled() {
-		return nil
-	}
-
-	if fileLabel == "" {
+	if !selinux.GetEnabled() || fileLabel == "" {
 		return nil
 		return nil
 	}
 	}
 
 
@@ -211,7 +165,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
 		path = strings.TrimSuffix(path, "/")
 		path = strings.TrimSuffix(path, "/")
 	}
 	}
 	if exclude_paths[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 {
 	if shared {
@@ -229,48 +183,10 @@ func Relabel(path string, fileLabel string, shared bool) error {
 	return nil
 	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
 // DisableSecOpt returns a security opt that can disable labeling
 // support for future container processes
 // 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
 // Validate checks that the label does not include unexpected options
 func Validate(label string) error {
 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"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
-	"syscall"
 
 
+	"github.com/opencontainers/selinux/pkg/pwalk"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	"golang.org/x/sys/unix"
 	"golang.org/x/sys/unix"
 )
 )
@@ -31,13 +31,13 @@ const (
 	// Disabled constant to indicate SELinux is disabled
 	// Disabled constant to indicate SELinux is disabled
 	Disabled = -1
 	Disabled = -1
 
 
+	contextFile      = "/usr/share/containers/selinux/contexts"
 	selinuxDir       = "/etc/selinux/"
 	selinuxDir       = "/etc/selinux/"
 	selinuxConfig    = selinuxDir + "config"
 	selinuxConfig    = selinuxDir + "config"
 	selinuxfsMount   = "/sys/fs/selinux"
 	selinuxfsMount   = "/sys/fs/selinux"
 	selinuxTypeTag   = "SELINUXTYPE"
 	selinuxTypeTag   = "SELINUXTYPE"
 	selinuxTag       = "SELINUX"
 	selinuxTag       = "SELINUX"
 	xattrNameSelinux = "security.selinux"
 	xattrNameSelinux = "security.selinux"
-	stRdOnly         = 0x01
 )
 )
 
 
 type selinuxState struct {
 type selinuxState struct {
@@ -103,13 +103,13 @@ func SetDisabled() {
 }
 }
 
 
 func verifySELinuxfsMount(mnt string) bool {
 func verifySELinuxfsMount(mnt string) bool {
-	var buf syscall.Statfs_t
+	var buf unix.Statfs_t
 	for {
 	for {
-		err := syscall.Statfs(mnt, &buf)
+		err := unix.Statfs(mnt, &buf)
 		if err == nil {
 		if err == nil {
 			break
 			break
 		}
 		}
-		if err == syscall.EAGAIN {
+		if err == unix.EAGAIN {
 			continue
 			continue
 		}
 		}
 		return false
 		return false
@@ -118,7 +118,7 @@ func verifySELinuxfsMount(mnt string) bool {
 	if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
 	if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
 		return false
 		return false
 	}
 	}
-	if (buf.Flags & stRdOnly) != 0 {
+	if (buf.Flags & unix.ST_RDONLY) != 0 {
 		return false
 		return false
 	}
 	}
 
 
@@ -251,10 +251,10 @@ 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)
 	if err != nil {
 	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 {
 	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
 	return nil
@@ -282,12 +282,29 @@ func readCon(fpath string) (string, error) {
 	return strings.Trim(retval, "\x00"), nil
 	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.
 // SetFileLabel sets the SELinux label for this path or returns an error.
 func SetFileLabel(fpath string, label string) error {
 func SetFileLabel(fpath string, label string) error {
 	if fpath == "" {
 	if fpath == "" {
 		return ErrEmptyPath
 		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 errors.Wrapf(err, "failed to set file label on %s", fpath)
 	}
 	}
 	return nil
 	return nil
@@ -390,7 +407,7 @@ func attrPath(attr string) string {
 		return path.Join(threadSelfPrefix, attr)
 		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) {
 func readAttr(attr string) (string, error) {
@@ -410,6 +427,18 @@ func CanonicalizeContext(val string) (string, error) {
 	return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
 	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) {
 func readWriteCon(fpath string, val string) (string, error) {
 	if fpath == "" {
 	if fpath == "" {
 		return "", ErrEmptyPath
 		return "", ErrEmptyPath
@@ -461,17 +490,17 @@ func SocketLabel() (string, error) {
 
 
 // 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
 func PeerLabel(fd uintptr) (string, error) {
 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
 // SetKeyLabel takes a process label and tells the kernel to assign the
 // label to the next kernel keyring that gets created
 // label to the next kernel keyring that gets created
 func SetKeyLabel(label string) error {
 func SetKeyLabel(label string) error {
 	err := writeCon("/proc/self/attr/keycreate", label)
 	err := writeCon("/proc/self/attr/keycreate", label)
-	if os.IsNotExist(err) {
+	if os.IsNotExist(errors.Cause(err)) {
 		return nil
 		return nil
 	}
 	}
-	if label == "" && os.IsPermission(err) {
+	if label == "" && os.IsPermission(errors.Cause(err)) {
 		return nil
 		return nil
 	}
 	}
 	return err
 	return err
@@ -656,23 +685,26 @@ func ROFileLabel() string {
 	return roFileLabel
 	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 (
 	var (
 		val, key string
 		val, key string
 		bufin    *bufio.Reader
 		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 {
 	if err != nil {
-		return "", ""
+		return labels
 	}
 	}
 	defer in.Close()
 	defer in.Close()
 
 
@@ -684,7 +716,7 @@ func ContainerLabels() (processLabel string, fileLabel string) {
 			if err == io.EOF {
 			if err == io.EOF {
 				done = true
 				done = true
 			} else {
 			} else {
-				goto exit
+				break
 			}
 			}
 		}
 		}
 		line = strings.TrimSpace(line)
 		line = strings.TrimSpace(line)
@@ -698,26 +730,64 @@ func ContainerLabels() (processLabel string, fileLabel string) {
 		}
 		}
 		if groups := assignRegex.FindStringSubmatch(line); groups != nil {
 		if groups := assignRegex.FindStringSubmatch(line); groups != nil {
 			key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
 			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 "", ""
 		return "", ""
 	}
 	}
 
 
+	processLabel = labels["process"]
+	fileLabel = labels["file"]
+	roFileLabel = labels["ro_file"]
+
+	if processLabel == "" || fileLabel == "" {
+		return "", fileLabel
+	}
+
 	if roFileLabel == "" {
 	if roFileLabel == "" {
 		roFileLabel = fileLabel
 		roFileLabel = fileLabel
 	}
 	}
-exit:
+
+	return addMcs(processLabel, fileLabel)
+}
+
+func addMcs(processLabel, fileLabel string) (string, string) {
 	scon, _ := NewContext(processLabel)
 	scon, _ := NewContext(processLabel)
 	if scon["level"] != "" {
 	if scon["level"] != "" {
 		mcs := uniqMcs(1024)
 		mcs := uniqMcs(1024)
@@ -772,14 +842,14 @@ func badPrefix(fpath string) error {
 	badPrefixes := []string{"/usr"}
 	badPrefixes := []string{"/usr"}
 	for _, prefix := range badPrefixes {
 	for _, prefix := range badPrefixes {
 		if strings.HasPrefix(fpath, prefix) {
 		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
 	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.
 // directory tree setting the label.
 func Chcon(fpath string, label string, recurse bool) error {
 func Chcon(fpath string, label string, recurse bool) error {
 	if fpath == "" {
 	if fpath == "" {
@@ -791,19 +861,19 @@ func Chcon(fpath string, label string, recurse bool) error {
 	if err := badPrefix(fpath); err != nil {
 	if err := badPrefix(fpath); err != nil {
 		return err
 		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)
 		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 nil
 		}
 		}
 		return e
 		return e
-	}
-
-	if recurse {
-		return filepath.Walk(fpath, callback)
-	}
-
-	return SetFileLabel(fpath, label)
+	})
 }
 }
 
 
 // DupSecOpt takes an SELinux process label and returns security options that
 // 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
 package selinux
 
 
@@ -35,6 +35,11 @@ func GetEnabled() bool {
 	return false
 	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.
 // SetFileLabel sets the SELinux label for this path or returns an error.
 func SetFileLabel(fpath string, label string) error {
 func SetFileLabel(fpath string, label string) error {
 	return nil
 	return nil
@@ -88,6 +93,13 @@ func CanonicalizeContext(val string) (string, error) {
 	return "", nil
 	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
 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.
@@ -101,7 +113,7 @@ 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 nil
+	return nil
 }
 }
 
 
 /*
 /*
@@ -189,6 +201,18 @@ func ROFileLabel() string {
 	return ""
 	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
 ContainerLabels returns an allocated processLabel and fileLabel to be used for
 container labeling by the calling process.
 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
 	// Start with a 128 length byte array
 	dest := make([]byte, 128)
 	dest := make([]byte, 128)
 	sz, errno := unix.Lgetxattr(path, attr, dest)
 	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{})
 		sz, errno = unix.Lgetxattr(path, attr, []byte{})
 		if errno != nil {
 		if errno != nil {
 			return nil, errno
 			return nil, errno
@@ -28,7 +28,3 @@ func lgetxattr(path string, attr string) ([]byte, error) {
 
 
 	return dest[:sz], nil
 	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
+}