summaryrefslogtreecommitdiff
path: root/vendor/github.com/opencontainers
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/opencontainers')
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/label/label.go134
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go122
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go54
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go208
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go14
-rw-r--r--vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go72
-rw-r--r--vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md42
-rw-r--r--vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go99
8 files changed, 431 insertions, 314 deletions
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
index e178568fd..6e38d3d32 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
+++ b/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
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
index 2730fcf4a..903829958 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
+++ b/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 {
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go
new file mode 100644
index 000000000..cda59d671
--- /dev/null
+++ b/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
+}
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
index 2d4e9f890..599bdb6e2 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
@@ -7,17 +7,19 @@ import (
"bytes"
"crypto/rand"
"encoding/binary"
- "errors"
"fmt"
"io"
"io/ioutil"
"os"
+ "path"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
- "syscall"
+
+ "github.com/opencontainers/selinux/pkg/pwalk"
+ "github.com/pkg/errors"
"golang.org/x/sys/unix"
)
@@ -35,16 +37,14 @@ const (
selinuxTypeTag = "SELINUXTYPE"
selinuxTag = "SELINUX"
xattrNameSelinux = "security.selinux"
- stRdOnly = 0x01
- selinuxfsMagic = 0xf97cff8c
)
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
}
@@ -61,6 +61,10 @@ var (
state = selinuxState{
mcsList: make(map[string]bool),
}
+
+ // for attrPath()
+ attrPathOnce sync.Once
+ haveThreadSelf bool
)
// Context is a representation of the SELinux label broken into 4 parts
@@ -97,30 +101,23 @@ func SetDisabled() {
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 {
- 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
}
- if uint32(buf.Type) != uint32(selinuxfsMagic) {
+
+ if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
return false
}
- if (buf.Flags & stRdOnly) != 0 {
+ if (buf.Flags & unix.ST_RDONLY) != 0 {
return false
}
@@ -165,33 +162,29 @@ func findSELinuxfs() string {
// if there is one, or an empty string in case of EOF or error.
func findSELinuxfsMount(s *bufio.Scanner) string {
for s.Scan() {
- txt := s.Text()
+ txt := s.Bytes()
// The first field after - is fs type.
// Safe as spaces in mountpoints are encoded as \040
- if !strings.Contains(txt, " - selinuxfs ") {
+ if !bytes.Contains(txt, []byte(" - selinuxfs ")) {
continue
}
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 {
continue
}
- return fields[mPos-1]
+ return string(fields[mPos-1])
}
return ""
}
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
@@ -253,6 +246,19 @@ func getSELinuxPolicyRoot() string {
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
}
+func isProcHandle(fh *os.File) error {
+ var buf unix.Statfs_t
+ err := unix.Fstatfs(int(fh.Fd()), &buf)
+ if err != nil {
+ return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
+ }
+ if buf.Type != unix.PROC_SUPER_MAGIC {
+ return errors.Errorf("file %q is not on procfs", fh.Name())
+ }
+
+ return nil
+}
+
func readCon(fpath string) (string, error) {
if fpath == "" {
return "", ErrEmptyPath
@@ -264,6 +270,10 @@ func readCon(fpath string) (string, error) {
}
defer in.Close()
+ if err := isProcHandle(in); err != nil {
+ return "", err
+ }
+
var retval string
if _, err := fmt.Fscanf(in, "%s", &retval); err != nil {
return "", err
@@ -271,12 +281,32 @@ 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
}
- return lsetxattr(fpath, xattrNameSelinux, []byte(label), 0)
+ 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
}
// FileLabel returns the SELinux label for this path or returns an error.
@@ -301,7 +331,7 @@ SetFSCreateLabel tells kernel the label to create all file system objects
created by this task. Setting label="" to return to default.
*/
func SetFSCreateLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/fscreate", syscall.Gettid()), label)
+ return writeAttr("fscreate", label)
}
/*
@@ -309,12 +339,12 @@ FSCreateLabel returns the default label the kernel which the kernel is using
for file system objects created by this task. "" indicates default.
*/
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.
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.
@@ -327,10 +357,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.
*/
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 == "" {
return ErrEmptyPath
}
@@ -346,12 +376,45 @@ func writeCon(fpath string, val string) error {
}
defer out.Close()
+ if err := isProcHandle(out); err != nil {
+ return err
+ }
+
if val != "" {
_, err = out.Write([]byte(val))
} else {
_, 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(unix.Gettid()), "/attr/", attr)
+}
+
+func readAttr(attr string) (string, error) {
+ return readCon(attrPath(attr))
+}
+
+func writeAttr(attr, val string) error {
+ return writeCon(attrPath(attr), val)
}
/*
@@ -363,6 +426,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
@@ -390,41 +465,41 @@ SetExecLabel sets the SELinux label that the kernel will use for any programs
that are executed by the current process thread, or an error.
*/
func SetExecLabel(label string) error {
- return writeCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()), label)
+ return writeAttr("exec", label)
}
/*
-SetTaskLabel sets the SELinux label for the current thread, or an error.
+SetTaskLabel sets the SELinux label for the current thread, or an error.
This requires the dyntransition permission.
*/
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
// label to the next socket that gets created
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
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
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) && !GetEnabled() {
+ if label == "" && os.IsPermission(errors.Cause(err)) {
return nil
}
return err
@@ -480,19 +555,18 @@ func ReserveLabel(label string) {
}
func selinuxEnforcePath() string {
- return fmt.Sprintf("%s/enforce", getSelinuxMountPoint())
+ return path.Join(getSelinuxMountPoint(), "enforce")
}
// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
var enforce int
- enforceS, err := readCon(selinuxEnforcePath())
+ enforceB, err := ioutil.ReadFile(selinuxEnforcePath())
if err != nil {
return -1
}
-
- enforce, err = strconv.Atoi(string(enforceS))
+ enforce, err = strconv.Atoi(string(enforceB))
if err != nil {
return -1
}
@@ -504,7 +578,7 @@ SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time.
*/
func SetEnforceMode(mode int) error {
- return writeCon(selinuxEnforcePath(), fmt.Sprintf("%d", mode))
+ return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
}
/*
@@ -686,7 +760,7 @@ exit:
// SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error {
- return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val)
+ return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
}
/*
@@ -726,14 +800,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 == "" {
@@ -745,19 +819,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
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go b/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
index 0c2e1cd38..f349513d9 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
+++ b/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
@@ -89,6 +94,13 @@ func CanonicalizeContext(val string) (string, error) {
}
/*
+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.
*/
diff --git a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
index 67a9d8ee8..de5c80ef3 100644
--- a/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
+++ b/vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
@@ -3,76 +3,28 @@
package selinux
import (
- "syscall"
- "unsafe"
+ "golang.org/x/sys/unix"
)
-var _zero uintptr
-
// Returns a []byte slice if the xattr is set and nil otherwise
// Requires path and its attribute as arguments
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
- 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)
+ 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
}
+
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
}
- sz = int(_sz)
- return dest[:sz], nil
-}
-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 dest[:sz], nil
}
diff --git a/vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md b/vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
new file mode 100644
index 000000000..16c4dfd3e
--- /dev/null
+++ b/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.
diff --git a/vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go b/vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
new file mode 100644
index 000000000..2ee0d0150
--- /dev/null
+++ b/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
+}