1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

vendor: opencontainers/selinux v1.5.1

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

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn 2020-05-05 15:35:03 +02:00
parent 0a5cec2833
commit a8216806ce
No known key found for this signature in database
GPG key ID: 76698F39D527CE8C
11 changed files with 418 additions and 251 deletions

View file

@ -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)

View file

@ -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
}

View file

@ -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 --------

View file

@ -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
}
import (
"github.com/opencontainers/selinux/go-selinux"
)
func ROMountLabel() string {
return ""
}
// Deprecated: use selinux.ROFileLabel
var ROMountLabel = selinux.ROFileLabel
func GenLabels(options string) (string, 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 FormatMountLabel(src string, mountLabel string) string {
return src
}
// 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 SetProcessLabel(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 ProcessLabel() (string, error) {
return "", nil
}
// SocketLabel retrieves the current default socket label setting
// Deprecated: use selinux.SocketLabel
var SocketLabel = selinux.SocketLabel
func SetSocketLabel(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 SocketLabel() (string, error) {
return "", nil
}
// KeyLabel retrieves the current default kernel keyring label setting
// Deprecated: use selinux.KeyLabel
var KeyLabel = selinux.KeyLabel
func SetKeyLabel(processLabel string) error {
return nil
}
// FileLabel returns the label for specified path
// Deprecated: use selinux.FileLabel
var FileLabel = selinux.FileLabel
func KeyLabel() (string, error) {
return "", nil
}
func FileLabel(path string) (string, error) {
return "", nil
}
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

View file

@ -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 {

View file

@ -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
}

View file

@ -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

View file

@ -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.

View file

@ -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)
}

View file

@ -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.

View file

@ -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
}