mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
build(deps): bump github.com/opencontainers/selinux
Bumps [github.com/opencontainers/selinux](https://github.com/opencontainers/selinux) from 1.13.1 to 1.14.1. - [Release notes](https://github.com/opencontainers/selinux/releases) - [Commits](https://github.com/opencontainers/selinux/compare/v1.13.1...v1.14.1) --- updated-dependencies: - dependency-name: github.com/opencontainers/selinux dependency-version: 1.14.1 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
This commit is contained in:
@@ -17,7 +17,7 @@ require (
|
||||
github.com/mrunalp/fileutils v0.5.1
|
||||
github.com/opencontainers/cgroups v0.0.6
|
||||
github.com/opencontainers/runtime-spec v1.3.0
|
||||
github.com/opencontainers/selinux v1.13.1
|
||||
github.com/opencontainers/selinux v1.14.1
|
||||
github.com/seccomp/libseccomp-golang v0.11.1
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
github.com/urfave/cli v1.22.17
|
||||
|
||||
@@ -52,8 +52,8 @@ github.com/opencontainers/cgroups v0.0.6 h1:tfZFWTIIGaUUFImTyuTg+Mr5x8XRiSdZESgE
|
||||
github.com/opencontainers/cgroups v0.0.6/go.mod h1:oWVzJsKK0gG9SCRBfTpnn16WcGEqDI8PAcpMGbqWxcs=
|
||||
github.com/opencontainers/runtime-spec v1.3.0 h1:YZupQUdctfhpZy3TM39nN9Ika5CBWT5diQ8ibYCRkxg=
|
||||
github.com/opencontainers/runtime-spec v1.3.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.13.1 h1:A8nNeceYngH9Ow++M+VVEwJVpdFmrlxsN22F+ISDCJE=
|
||||
github.com/opencontainers/selinux v1.13.1/go.mod h1:S10WXZ/osk2kWOYKy1x2f/eXF5ZHJoUs8UU/2caNRbg=
|
||||
github.com/opencontainers/selinux v1.14.1 h1:a7XlXV/nN/l5zFP1FWZYoExpClu1QOPMfWUV2CZ8kEQ=
|
||||
github.com/opencontainers/selinux v1.14.1/go.mod h1:LenyElirjUHszfxrjuFqC85HIeXZKumHcKMQtnaDlQQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
|
||||
+55
-47
@@ -22,60 +22,68 @@ var ErrIncompatibleLabel = errors.New("bad SELinux option: z and Z can not be us
|
||||
|
||||
// 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. The labels returned will include a random MCS String, that is
|
||||
// guaranteed to be unique.
|
||||
// the labels.
|
||||
//
|
||||
// Unless the "level" option is provided (to set a custom level), the labels
|
||||
// returned will include a random MCS string guaranteed to be unique in the
|
||||
// scope of the process using this package. If the "level" option is provided,
|
||||
// the custom level set is reserved but not checked to be unique.
|
||||
//
|
||||
// If the disabled flag is passed in, the process label will not be set, but the mount label will be set
|
||||
// to the container_file label with the maximum category. This label is not usable by any confined label.
|
||||
func InitLabels(options []string) (plabel string, mlabel string, retErr error) {
|
||||
if !selinux.GetEnabled() {
|
||||
return "", "", nil
|
||||
}
|
||||
processLabel, mountLabel := selinux.ContainerLabels()
|
||||
if processLabel != "" {
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
}
|
||||
}()
|
||||
pcon, err := selinux.NewContext(processLabel)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
mcsLevel := pcon["level"]
|
||||
mcon, err := selinux.NewContext(mountLabel)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
for _, opt := range options {
|
||||
if opt == "disable" {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
return "", selinux.PrivContainerMountLabel(), 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)
|
||||
}
|
||||
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])
|
||||
}
|
||||
if con[0] == "filetype" {
|
||||
mcon["type"] = con[1]
|
||||
continue
|
||||
}
|
||||
pcon[con[0]] = con[1]
|
||||
if con[0] == "level" || con[0] == "user" {
|
||||
mcon[con[0]] = con[1]
|
||||
}
|
||||
}
|
||||
if pcon.Get() != processLabel {
|
||||
if pcon["level"] != mcsLevel {
|
||||
selinux.ReleaseLabel(processLabel)
|
||||
}
|
||||
processLabel = pcon.Get()
|
||||
selinux.ReserveLabel(processLabel)
|
||||
}
|
||||
mountLabel = mcon.Get()
|
||||
processLabel, mountLabel := selinux.ContainerLabels() //nolint:staticcheck // ContainerLabels will be moved to an internal package.
|
||||
if processLabel == "" {
|
||||
// processLabel is required; if empty, do nothing.
|
||||
return processLabel, mountLabel, nil
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
}
|
||||
}()
|
||||
pcon, err := selinux.NewContext(processLabel)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
mcsLevel := pcon["level"]
|
||||
mcon, err := selinux.NewContext(mountLabel)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
for _, opt := range options {
|
||||
if opt == "disable" {
|
||||
selinux.ReleaseLabel(mountLabel)
|
||||
return "", selinux.PrivContainerMountLabel(), nil
|
||||
}
|
||||
k, v, ok := strings.Cut(opt, ":")
|
||||
if !ok || !validOptions[k] {
|
||||
return "", "", fmt.Errorf("bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
|
||||
}
|
||||
if k == "filetype" {
|
||||
mcon["type"] = v
|
||||
continue
|
||||
}
|
||||
pcon[k] = v
|
||||
if k == "level" || k == "user" {
|
||||
mcon[k] = v
|
||||
}
|
||||
}
|
||||
if p := pcon.Get(); p != processLabel {
|
||||
if pcon["level"] != mcsLevel {
|
||||
selinux.ReleaseLabel(processLabel)
|
||||
// Ignore ErrMCSAlreadyExists as label is user-specified and might be
|
||||
// already reserved (e.g. when containers in a pod use the same label).
|
||||
if err := selinux.ReserveLabelV2(p); err != nil && !errors.Is(err, selinux.ErrMCSAlreadyExists) {
|
||||
return "", "", err
|
||||
}
|
||||
}
|
||||
processLabel = p
|
||||
}
|
||||
mountLabel = mcon.Get()
|
||||
return processLabel, mountLabel, nil
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package label
|
||||
|
||||
|
||||
+68
-14
@@ -26,11 +26,6 @@ var (
|
||||
// ErrInvalidLabel is returned when an invalid label is specified.
|
||||
ErrInvalidLabel = errors.New("invalid Label")
|
||||
|
||||
// InvalidLabel is returned when an invalid label is specified.
|
||||
//
|
||||
// Deprecated: use [ErrInvalidLabel].
|
||||
InvalidLabel = ErrInvalidLabel
|
||||
|
||||
// ErrIncomparable is returned two levels are not comparable
|
||||
ErrIncomparable = errors.New("incomparable levels")
|
||||
// ErrLevelSyntax is returned when a sensitivity or category do not have correct syntax in a level
|
||||
@@ -45,7 +40,9 @@ var (
|
||||
// is not the thread group leader.
|
||||
ErrNotTGLeader = errors.New("calling thread is not the thread group leader")
|
||||
|
||||
// CategoryRange allows the upper bound on the category range to be adjusted
|
||||
// CategoryRange allows the upper bound on the category range to be adjusted.
|
||||
//
|
||||
// Deprecated: use [SetCategoryRange] instead.
|
||||
CategoryRange = DefaultCategoryRange
|
||||
|
||||
privContainerMountLabel string
|
||||
@@ -64,6 +61,16 @@ func GetEnabled() bool {
|
||||
return getEnabled()
|
||||
}
|
||||
|
||||
// SetCategoryRange allows to adjust the upper bound of the category range.
|
||||
// It affects subsequent calls to [KVMContainerLabel] and [InitContainerLabel].
|
||||
func SetCategoryRange(upper uint32) error {
|
||||
if upper > DefaultCategoryRange {
|
||||
return errors.New("can't have more than DefaultCategoryRange categories")
|
||||
}
|
||||
CategoryRange = upper
|
||||
return 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) {
|
||||
@@ -107,12 +114,12 @@ func SetFSCreateLabel(label string) error {
|
||||
// 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 fsCreateLabel()
|
||||
return readConThreadSelf("attr/fscreate")
|
||||
}
|
||||
|
||||
// CurrentLabel returns the SELinux label of the current process thread, or an error.
|
||||
func CurrentLabel() (string, error) {
|
||||
return currentLabel()
|
||||
return readConThreadSelf("attr/current")
|
||||
}
|
||||
|
||||
// PidLabel returns the SELinux label of the given pid, or an error.
|
||||
@@ -123,7 +130,7 @@ func PidLabel(pid int) (string, error) {
|
||||
// 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 execLabel()
|
||||
return readConThreadSelf("attr/exec")
|
||||
}
|
||||
|
||||
// CanonicalizeContext takes a context string and writes it to the kernel
|
||||
@@ -180,7 +187,7 @@ 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 peerLabel(fd)
|
||||
return peerLabel(int(fd)) //#nosec G115 -- ignore "integer overflow conversion uintptr -> int".
|
||||
}
|
||||
|
||||
// SetKeyLabel takes a process label and tells the kernel to assign the
|
||||
@@ -216,9 +223,26 @@ func ClearLabels() {
|
||||
clearLabels()
|
||||
}
|
||||
|
||||
// ReserveLabel reserves the MLS/MCS level component of the specified label
|
||||
// ReserveLabel reserves the MLS/MCS level component of the specified label.
|
||||
//
|
||||
// Deprecated: use [ReserveLabelV2] instead.
|
||||
func ReserveLabel(label string) {
|
||||
reserveLabel(label)
|
||||
_ = reserveLabel(label)
|
||||
}
|
||||
|
||||
// ReserveLabelV2 reserves the MLS/MCS level component of the specified label.
|
||||
// Returns an error if the label can't be reserved.
|
||||
//
|
||||
// Callers that are intentionally reusing an existing level/MCS (e.g. multiple
|
||||
// container in a pod sharing a label) may safely ignore [ErrMCSAlreadyExists]
|
||||
// error.
|
||||
func ReserveLabelV2(label string) error {
|
||||
return reserveLabel(label)
|
||||
}
|
||||
|
||||
// CheckLabel check the MLS/MCS level component of the specified label
|
||||
func CheckLabel(label string) error {
|
||||
return checkLabel(label)
|
||||
}
|
||||
|
||||
// MLSEnabled checks if MLS is enabled.
|
||||
@@ -250,25 +274,47 @@ func ReleaseLabel(label string) {
|
||||
releaseLabel(label)
|
||||
}
|
||||
|
||||
// ROFileLabel returns the specified SELinux readonly file label
|
||||
// ROFileLabel returns the specified SELinux readonly file label.
|
||||
//
|
||||
// Deprecated: this (apparently) has no users and will be removed from the
|
||||
// future version of this package. Open a bug report if you use it.
|
||||
func ROFileLabel() string {
|
||||
return roFileLabel()
|
||||
}
|
||||
|
||||
// KVMContainerLabels returns the default processLabel and mountLabel to be used
|
||||
// for kvm containers by the calling process.
|
||||
//
|
||||
// Deprecated: use [KVMContainerLabel] instead.
|
||||
func KVMContainerLabels() (string, string) {
|
||||
return kvmContainerLabels()
|
||||
}
|
||||
|
||||
// KVMContainerLabel returns the default process label to be used
|
||||
// for KVM containers by the calling process.
|
||||
func KVMContainerLabel() (string, error) {
|
||||
return kvmContainerLabel()
|
||||
}
|
||||
|
||||
// InitContainerLabels returns the default processLabel and file labels to be
|
||||
// used for containers running an init system like systemd by the calling process.
|
||||
//
|
||||
// Deprecated: use [InitContainerLabel] instead.
|
||||
func InitContainerLabels() (string, string) {
|
||||
return initContainerLabels()
|
||||
}
|
||||
|
||||
// InitContainerLabel returns the default process label to be used
|
||||
// for containers running an init system like systemd by the calling process.
|
||||
func InitContainerLabel() (string, error) {
|
||||
return initContainerLabel()
|
||||
}
|
||||
|
||||
// ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
||||
// container labeling by the calling process.
|
||||
//
|
||||
// Deprecated: this (apparently) has no users and will be removed from the
|
||||
// future version of this package. Open a bug report if you use it.
|
||||
func ContainerLabels() (processLabel string, fileLabel string) {
|
||||
return containerLabels()
|
||||
}
|
||||
@@ -305,11 +351,19 @@ func DisableSecOpt() []string {
|
||||
return []string{"disable"}
|
||||
}
|
||||
|
||||
// SEUserByName retrieves the SELinux username and security level for a given
|
||||
// Linux username. The username and security level is based on the
|
||||
// /etc/selinux/{SELINUXTYPE}/seusers file.
|
||||
func SEUserByName(username string) (seUser string, level string, err error) {
|
||||
return getSeUserByName(username)
|
||||
}
|
||||
|
||||
// GetDefaultContextWithLevel gets a single context for the specified SELinux user
|
||||
// identity that is reachable from the specified scon context. The context is based
|
||||
// on the per-user /etc/selinux/{SELINUXTYPE}/contexts/users/<username> if it exists,
|
||||
// and falls back to the global /etc/selinux/{SELINUXTYPE}/contexts/default_contexts
|
||||
// file.
|
||||
// file and finally the global /etc/selinux/{SELINUXTYPE}/contexts/failsafe_context
|
||||
// file if no match can be found anywhere else.
|
||||
func GetDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||
return getDefaultContextWithLevel(user, level, scon)
|
||||
}
|
||||
|
||||
+301
-187
@@ -3,16 +3,16 @@ package selinux
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/fs"
|
||||
"math/big"
|
||||
"math/rand/v2"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -30,6 +30,7 @@ const (
|
||||
selinuxDir = "/etc/selinux/"
|
||||
selinuxUsersDir = "contexts/users"
|
||||
defaultContexts = "contexts/default_contexts"
|
||||
failsafeContext = "contexts/failsafe_context"
|
||||
selinuxConfig = selinuxDir + "config"
|
||||
selinuxfsMount = "/sys/fs/selinux"
|
||||
selinuxTypeTag = "SELINUXTYPE"
|
||||
@@ -38,11 +39,9 @@ const (
|
||||
)
|
||||
|
||||
type selinuxState struct {
|
||||
mcsList map[string]bool
|
||||
selinuxfs string
|
||||
selinuxfsOnce sync.Once
|
||||
enabledSet bool
|
||||
enabled bool
|
||||
mcsList map[string]struct{}
|
||||
enabledSet bool
|
||||
enabled bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
@@ -56,10 +55,19 @@ type mlsRange struct {
|
||||
high *level
|
||||
}
|
||||
|
||||
type openReaderCloser func() (io.ReadCloser, error)
|
||||
|
||||
func createOpener(path string) openReaderCloser {
|
||||
return func() (io.ReadCloser, error) {
|
||||
return os.Open(path)
|
||||
}
|
||||
}
|
||||
|
||||
type defaultSECtx struct {
|
||||
userRdr io.Reader
|
||||
openUserRdr openReaderCloser
|
||||
verifier func(string) error
|
||||
defaultRdr io.Reader
|
||||
openDefaultRdr openReaderCloser
|
||||
openFailsafeRdr openReaderCloser
|
||||
user, level, scon string
|
||||
}
|
||||
|
||||
@@ -72,26 +80,15 @@ const (
|
||||
|
||||
var (
|
||||
readOnlyFileLabel string
|
||||
state = selinuxState{
|
||||
mcsList: make(map[string]bool),
|
||||
|
||||
state = selinuxState{
|
||||
mcsList: make(map[string]struct{}),
|
||||
}
|
||||
|
||||
// for policyRoot()
|
||||
policyRootOnce sync.Once
|
||||
policyRootVal string
|
||||
|
||||
// for label()
|
||||
loadLabelsOnce sync.Once
|
||||
labels map[string]string
|
||||
)
|
||||
|
||||
func policyRoot() string {
|
||||
policyRootOnce.Do(func() {
|
||||
policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
|
||||
})
|
||||
|
||||
return policyRootVal
|
||||
}
|
||||
var policyRoot = sync.OnceValue(func() string {
|
||||
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
|
||||
})
|
||||
|
||||
func (s *selinuxState) setEnable(enabled bool) bool {
|
||||
s.Lock()
|
||||
@@ -148,7 +145,12 @@ func verifySELinuxfsMount(mnt string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func findSELinuxfs() string {
|
||||
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
|
||||
// filesystem or an empty string if no mountpoint is found. Selinuxfs is
|
||||
// a proc-like pseudo-filesystem that exposes the SELinux policy API to
|
||||
// processes. The existence of an selinuxfs mount is used to determine
|
||||
// whether SELinux is currently enabled or not.
|
||||
var getSelinuxMountPoint = sync.OnceValue(func() string {
|
||||
// fast path: check the default mount first
|
||||
if verifySELinuxfsMount(selinuxfsMount) {
|
||||
return selinuxfsMount
|
||||
@@ -180,7 +182,7 @@ func findSELinuxfs() string {
|
||||
return mnt
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// findSELinuxfsMount returns a next selinuxfs mount point found,
|
||||
// if there is one, or an empty string in case of EOF or error.
|
||||
@@ -203,23 +205,6 @@ func findSELinuxfsMount(s *bufio.Scanner) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (s *selinuxState) getSELinuxfs() string {
|
||||
s.selinuxfsOnce.Do(func() {
|
||||
s.selinuxfs = findSELinuxfs()
|
||||
})
|
||||
|
||||
return s.selinuxfs
|
||||
}
|
||||
|
||||
// getSelinuxMountPoint returns the path to the mountpoint of an selinuxfs
|
||||
// filesystem or an empty string if no mountpoint is found. Selinuxfs is
|
||||
// a proc-like pseudo-filesystem that exposes the SELinux policy API to
|
||||
// processes. The existence of an selinuxfs mount is used to determine
|
||||
// whether SELinux is currently enabled or not.
|
||||
func getSelinuxMountPoint() string {
|
||||
return state.getSELinuxfs()
|
||||
}
|
||||
|
||||
// getEnabled returns whether SELinux is currently enabled.
|
||||
func getEnabled() bool {
|
||||
return state.getEnabled()
|
||||
@@ -244,12 +229,9 @@ func readConfig(target string) string {
|
||||
// Skip comments
|
||||
continue
|
||||
}
|
||||
fields := bytes.SplitN(line, []byte{'='}, 2)
|
||||
if len(fields) != 2 {
|
||||
continue
|
||||
}
|
||||
if bytes.Equal(fields[0], []byte(target)) {
|
||||
return string(bytes.Trim(fields[1], `"`))
|
||||
key, val, ok := bytes.Cut(line, []byte{'='})
|
||||
if ok && string(key) == target {
|
||||
return string(bytes.Trim(val, `"`))
|
||||
}
|
||||
}
|
||||
return ""
|
||||
@@ -530,17 +512,6 @@ func setFSCreateLabel(label string) error {
|
||||
return writeConThreadSelf("attr/fscreate", label)
|
||||
}
|
||||
|
||||
// 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 readConThreadSelf("attr/fscreate")
|
||||
}
|
||||
|
||||
// currentLabel returns the SELinux label of the current process thread, or an error.
|
||||
func currentLabel() (string, error) {
|
||||
return readConThreadSelf("attr/current")
|
||||
}
|
||||
|
||||
// pidLabel returns the SELinux label of the given pid, or an error.
|
||||
func pidLabel(pid int) (string, error) {
|
||||
it, err := openProcPid(pid, "attr/current", os.O_RDONLY|unix.O_CLOEXEC)
|
||||
@@ -551,12 +522,6 @@ func pidLabel(pid int) (string, error) {
|
||||
return readConFd(it)
|
||||
}
|
||||
|
||||
// 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 readConThreadSelf("exec")
|
||||
}
|
||||
|
||||
// canonicalizeContext takes a context string and writes it to the kernel
|
||||
// the function then returns the context that the kernel will use. Use this
|
||||
// function to check if two contexts are equivalent
|
||||
@@ -581,13 +546,12 @@ func catsToBitset(cats string) (*big.Int, error) {
|
||||
|
||||
catlist := strings.Split(cats, ",")
|
||||
for _, r := range catlist {
|
||||
ranges := strings.SplitN(r, ".", 2)
|
||||
if len(ranges) > 1 {
|
||||
catstart, err := parseLevelItem(ranges[0], category)
|
||||
if s, e, ok := strings.Cut(r, "."); ok {
|
||||
catstart, err := parseLevelItem(s, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
catend, err := parseLevelItem(ranges[1], category)
|
||||
catend, err := parseLevelItem(e, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -595,7 +559,7 @@ func catsToBitset(cats string) (*big.Int, error) {
|
||||
bitset.SetBit(bitset, i, 1)
|
||||
}
|
||||
} else {
|
||||
cat, err := parseLevelItem(ranges[0], category)
|
||||
cat, err := parseLevelItem(r, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -623,14 +587,14 @@ func parseLevelItem(s string, sep levelItem) (int, error) {
|
||||
// parseLevel fills a level from a string that contains
|
||||
// a sensitivity and categories
|
||||
func (l *level) parseLevel(levelStr string) error {
|
||||
lvl := strings.SplitN(levelStr, ":", 2)
|
||||
sens, err := parseLevelItem(lvl[0], sensitivity)
|
||||
s, c, ok := strings.Cut(levelStr, ":")
|
||||
sens, err := parseLevelItem(s, sensitivity)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse sensitivity: %w", err)
|
||||
}
|
||||
l.sens = sens
|
||||
if len(lvl) > 1 {
|
||||
cats, err := catsToBitset(lvl[1])
|
||||
if ok {
|
||||
cats, err := catsToBitset(c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse categories: %w", err)
|
||||
}
|
||||
@@ -643,25 +607,19 @@ func (l *level) parseLevel(levelStr string) error {
|
||||
// rangeStrToMLSRange marshals a string representation of a range.
|
||||
func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
|
||||
r := &mlsRange{}
|
||||
l := strings.SplitN(rangeStr, "-", 2)
|
||||
|
||||
switch len(l) {
|
||||
// rangeStr that has a low and a high level, e.g. s4:c0.c1023-s6:c0.c1023
|
||||
case 2:
|
||||
r.high = &level{}
|
||||
if err := r.high.parseLevel(l[1]); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse high level %q: %w", l[1], err)
|
||||
}
|
||||
fallthrough
|
||||
// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023
|
||||
case 1:
|
||||
r.low = &level{}
|
||||
if err := r.low.parseLevel(l[0]); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse low level %q: %w", l[0], err)
|
||||
}
|
||||
lo, hi, ok := strings.Cut(rangeStr, "-")
|
||||
r.low = &level{}
|
||||
if err := r.low.parseLevel(lo); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse low level %q: %w", lo, err)
|
||||
}
|
||||
|
||||
if r.high == nil {
|
||||
if ok {
|
||||
// rangeStr that has a low and a high level, e.g. s4:c0.c1023-s6:c0.c1023.
|
||||
r.high = &level{}
|
||||
if err := r.high.parseLevel(hi); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse high level %q: %w", hi, err)
|
||||
}
|
||||
} else {
|
||||
// rangeStr that is single level, e.g. s6:c0,c3,c5,c30.c1023.
|
||||
r.high = r.low
|
||||
}
|
||||
|
||||
@@ -732,22 +690,6 @@ func (m mlsRange) String() string {
|
||||
return low + "-" + high
|
||||
}
|
||||
|
||||
// TODO: remove these in favor of built-in min/max
|
||||
// once we stop supporting Go < 1.21.
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func minInt(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// calculateGlbLub computes the glb (greatest lower bound) and lub (least upper bound)
|
||||
// of a source and target range.
|
||||
// The glblub is calculated as the greater of the low sensitivities and
|
||||
@@ -770,10 +712,10 @@ func calculateGlbLub(sourceRange, targetRange string) (string, error) {
|
||||
outrange := &mlsRange{low: &level{}, high: &level{}}
|
||||
|
||||
/* take the greatest of the low */
|
||||
outrange.low.sens = maxInt(s.low.sens, t.low.sens)
|
||||
outrange.low.sens = max(s.low.sens, t.low.sens)
|
||||
|
||||
/* take the least of the high */
|
||||
outrange.high.sens = minInt(s.high.sens, t.high.sens)
|
||||
outrange.high.sens = min(s.high.sens, t.high.sens)
|
||||
|
||||
/* find the intersecting categories */
|
||||
if s.low.cats != nil && t.low.cats != nil {
|
||||
@@ -807,10 +749,10 @@ func readWriteCon(fpath string, val string) (string, error) {
|
||||
}
|
||||
|
||||
// peerLabel retrieves the label of the client on the other side of a socket
|
||||
func peerLabel(fd uintptr) (string, error) {
|
||||
l, err := unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
|
||||
func peerLabel(fd int) (string, error) {
|
||||
l, err := unix.GetsockoptString(fd, unix.SOL_SOCKET, unix.SO_PEERSEC)
|
||||
if err != nil {
|
||||
return "", &os.PathError{Op: "getsockopt", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
|
||||
return "", &os.PathError{Op: "getsockopt", Path: "fd " + strconv.Itoa(fd), Err: err}
|
||||
}
|
||||
return l, nil
|
||||
}
|
||||
@@ -871,18 +813,34 @@ func newContext(label string) (Context, error) {
|
||||
// clearLabels clears all reserved labels
|
||||
func clearLabels() {
|
||||
state.Lock()
|
||||
state.mcsList = make(map[string]bool)
|
||||
state.mcsList = make(map[string]struct{})
|
||||
state.Unlock()
|
||||
}
|
||||
|
||||
// reserveLabel reserves the MLS/MCS level component of the specified label
|
||||
func reserveLabel(label string) {
|
||||
// reserveLabel reserves the MLS/MCS level component of the specified label.
|
||||
func reserveLabel(label string) error {
|
||||
if len(label) != 0 {
|
||||
con := strings.SplitN(label, ":", 4)
|
||||
if len(con) > 3 {
|
||||
_ = mcsAdd(con[3])
|
||||
return mcsAdd(con[3])
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkLabel(label string) error {
|
||||
if len(label) != 0 {
|
||||
con := strings.SplitN(label, ":", 4)
|
||||
if len(con) > 3 {
|
||||
state.Lock()
|
||||
defer state.Unlock()
|
||||
if _, exist := state.mcsList[con[3]]; exist {
|
||||
return ErrMCSAlreadyExists
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func selinuxEnforcePath() string {
|
||||
@@ -938,10 +896,10 @@ func mcsAdd(mcs string) error {
|
||||
}
|
||||
state.Lock()
|
||||
defer state.Unlock()
|
||||
if state.mcsList[mcs] {
|
||||
if _, exist := state.mcsList[mcs]; exist {
|
||||
return ErrMCSAlreadyExists
|
||||
}
|
||||
state.mcsList[mcs] = true
|
||||
state.mcsList[mcs] = struct{}{}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -951,41 +909,21 @@ func mcsDelete(mcs string) {
|
||||
}
|
||||
state.Lock()
|
||||
defer state.Unlock()
|
||||
state.mcsList[mcs] = false
|
||||
}
|
||||
|
||||
func intToMcs(id int, catRange uint32) string {
|
||||
var (
|
||||
SETSIZE = int(catRange)
|
||||
TIER = SETSIZE
|
||||
ORD = id
|
||||
)
|
||||
|
||||
if id < 1 || id > 523776 {
|
||||
return ""
|
||||
}
|
||||
|
||||
for ORD > TIER {
|
||||
ORD -= TIER
|
||||
TIER--
|
||||
}
|
||||
TIER = SETSIZE - TIER
|
||||
ORD += TIER
|
||||
return fmt.Sprintf("s0:c%d,c%d", TIER, ORD)
|
||||
delete(state.mcsList, mcs)
|
||||
}
|
||||
|
||||
func uniqMcs(catRange uint32) string {
|
||||
var (
|
||||
n uint32
|
||||
c1, c2 uint32
|
||||
mcs string
|
||||
)
|
||||
|
||||
for {
|
||||
_ = binary.Read(rand.Reader, binary.LittleEndian, &n)
|
||||
c1 = n % catRange
|
||||
_ = binary.Read(rand.Reader, binary.LittleEndian, &n)
|
||||
c2 = n % catRange
|
||||
//#nosec G404 -- using slightly more predictable MCS labels won't affect security, so it's fine to use math/rand/v2 here.
|
||||
{
|
||||
c1 = rand.Uint32N(catRange)
|
||||
c2 = rand.Uint32N(catRange)
|
||||
}
|
||||
if c1 == c2 {
|
||||
continue
|
||||
} else if c1 > c2 {
|
||||
@@ -1023,11 +961,11 @@ func openContextFile() (*os.File, error) {
|
||||
return os.Open(filepath.Join(policyRoot(), "contexts", "lxc_contexts"))
|
||||
}
|
||||
|
||||
func loadLabels() {
|
||||
labels = make(map[string]string)
|
||||
var loadLabels = sync.OnceValue(func() map[string]string {
|
||||
labels := make(map[string]string)
|
||||
in, err := openContextFile()
|
||||
if err != nil {
|
||||
return
|
||||
return labels
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
@@ -1043,25 +981,21 @@ func loadLabels() {
|
||||
// Skip comments
|
||||
continue
|
||||
}
|
||||
fields := bytes.SplitN(line, []byte{'='}, 2)
|
||||
if len(fields) != 2 {
|
||||
continue
|
||||
if key, val, ok := bytes.Cut(line, []byte{'='}); ok {
|
||||
key, val = bytes.TrimSpace(key), bytes.TrimSpace(val)
|
||||
labels[string(key)] = string(bytes.Trim(val, `"`))
|
||||
}
|
||||
key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
|
||||
labels[string(key)] = string(bytes.Trim(val, `"`))
|
||||
}
|
||||
|
||||
con, _ := NewContext(labels["file"])
|
||||
con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
|
||||
privContainerMountLabel = con.get()
|
||||
reserveLabel(privContainerMountLabel)
|
||||
}
|
||||
_ = reserveLabel(privContainerMountLabel)
|
||||
return labels
|
||||
})
|
||||
|
||||
func label(key string) string {
|
||||
loadLabelsOnce.Do(func() {
|
||||
loadLabels()
|
||||
})
|
||||
return labels[key]
|
||||
return loadLabels()[key]
|
||||
}
|
||||
|
||||
// kvmContainerLabels returns the default processLabel and mountLabel to be used
|
||||
@@ -1075,6 +1009,15 @@ func kvmContainerLabels() (string, string) {
|
||||
return addMcs(processLabel, label("file"))
|
||||
}
|
||||
|
||||
func kvmContainerLabel() (string, error) {
|
||||
processLabel := label("kvm_process")
|
||||
if processLabel == "" {
|
||||
processLabel = label("process")
|
||||
}
|
||||
pLabel, _, err := addMcsProc(processLabel)
|
||||
return pLabel, err
|
||||
}
|
||||
|
||||
// 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) {
|
||||
@@ -1086,6 +1029,16 @@ func initContainerLabels() (string, string) {
|
||||
return addMcs(processLabel, label("file"))
|
||||
}
|
||||
|
||||
func initContainerLabel() (string, error) {
|
||||
processLabel := label("init_process")
|
||||
if processLabel == "" {
|
||||
processLabel = label("process")
|
||||
}
|
||||
|
||||
pLabel, _, err := addMcsProc(processLabel)
|
||||
return pLabel, err
|
||||
}
|
||||
|
||||
// containerLabels returns an allocated processLabel and fileLabel to be used for
|
||||
// container labeling by the calling process.
|
||||
func containerLabels() (processLabel string, fileLabel string) {
|
||||
@@ -1108,13 +1061,24 @@ func containerLabels() (processLabel string, fileLabel string) {
|
||||
return addMcs(processLabel, fileLabel)
|
||||
}
|
||||
|
||||
func addMcs(processLabel, fileLabel string) (string, string) {
|
||||
scon, _ := NewContext(processLabel)
|
||||
func addMcsProc(processLabel string) (string, string, error) {
|
||||
var mcs string
|
||||
scon, err := NewContext(processLabel)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
if scon["level"] != "" {
|
||||
mcs := uniqMcs(CategoryRange)
|
||||
mcs = uniqMcs(CategoryRange)
|
||||
scon["level"] = mcs
|
||||
processLabel = scon.Get()
|
||||
scon, _ = NewContext(fileLabel)
|
||||
}
|
||||
return processLabel, mcs, nil
|
||||
}
|
||||
|
||||
func addMcs(processLabel, fileLabel string) (string, string) {
|
||||
processLabel, mcs, _ := addMcsProc(processLabel)
|
||||
if mcs != "" {
|
||||
scon, _ := NewContext(fileLabel)
|
||||
scon["level"] = mcs
|
||||
fileLabel = scon.Get()
|
||||
}
|
||||
@@ -1281,6 +1245,111 @@ func dupSecOpt(src string) ([]string, error) {
|
||||
return dup, nil
|
||||
}
|
||||
|
||||
// checkGroup returns true if group's GID is in the list of GIDs gids.
|
||||
func checkGroup(group string, gids []string, lookupGroup func(string) (*user.Group, error)) bool {
|
||||
grp, err := lookupGroup(group)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return slices.Contains(gids, grp.Gid)
|
||||
}
|
||||
|
||||
// getSeUserFromReader reads the seusers file: https://www.man7.org/linux/man-pages/man5/seusers.5.html
|
||||
func getSeUserFromReader(username string, gids []string, r io.Reader, lookupGroup func(string) (*user.Group, error)) (seUser string, level string, err error) {
|
||||
var defaultSeUser, defaultLevel string
|
||||
var groupSeUser, groupLevel string
|
||||
|
||||
lineNum := -1
|
||||
scanner := bufio.NewScanner(r)
|
||||
for scanner.Scan() {
|
||||
rawLine := scanner.Text()
|
||||
lineNum++
|
||||
|
||||
// remove any trailing comments, then extra whitespace
|
||||
line, _, _ := strings.Cut(rawLine, "#")
|
||||
line = strings.TrimSpace(line)
|
||||
if line == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
userField, rest, ok := strings.Cut(line, ":")
|
||||
if !ok {
|
||||
return "", "", fmt.Errorf("line %d: malformed line", lineNum)
|
||||
}
|
||||
if userField == "" {
|
||||
return "", "", fmt.Errorf("line %d: user_id or group_id is empty", lineNum)
|
||||
}
|
||||
seUserField, rest, ok := strings.Cut(rest, ":")
|
||||
if seUserField == "" {
|
||||
return "", "", fmt.Errorf("line %d: seuser_id is empty", lineNum)
|
||||
}
|
||||
var levelField string
|
||||
// level is optional
|
||||
if ok {
|
||||
levelField = rest
|
||||
}
|
||||
|
||||
// we found a match, return it
|
||||
if userField == username {
|
||||
return seUserField, levelField, nil
|
||||
}
|
||||
|
||||
// if the first field starts with '%' it's a group, check if
|
||||
// the user is a member of that group and set the group
|
||||
// SELinux user and level if so
|
||||
if userField[0] == '%' && groupSeUser == "" {
|
||||
if checkGroup(userField[1:], gids, lookupGroup) {
|
||||
groupSeUser = seUserField
|
||||
groupLevel = levelField
|
||||
}
|
||||
} else if userField == "__default__" && defaultSeUser == "" {
|
||||
defaultSeUser = seUserField
|
||||
defaultLevel = levelField
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", "", fmt.Errorf("failed to read seusers file: %w", err)
|
||||
}
|
||||
|
||||
if groupSeUser != "" {
|
||||
return groupSeUser, groupLevel, nil
|
||||
}
|
||||
if defaultSeUser != "" {
|
||||
return defaultSeUser, defaultLevel, nil
|
||||
}
|
||||
|
||||
return "", "", fmt.Errorf("could not find SELinux user for %q login", username)
|
||||
}
|
||||
|
||||
// getSeUserByName returns an SELinux user and MLS level that is
|
||||
// mapped to a given Linux user.
|
||||
func getSeUserByName(username string) (string, string, error) {
|
||||
seUsersConf := filepath.Join(policyRoot(), "seusers")
|
||||
confFile, err := os.Open(seUsersConf)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("failed to open seusers file: %w", err)
|
||||
}
|
||||
defer confFile.Close()
|
||||
|
||||
usr, err := user.Lookup(username)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
gids, err := usr.GroupIds()
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
gids = append([]string{usr.Gid}, gids...)
|
||||
|
||||
seUser, level, err := getSeUserFromReader(username, gids, confFile, user.LookupGroup)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("failed to parse seusers file: %w", err)
|
||||
}
|
||||
|
||||
return seUser, level, nil
|
||||
}
|
||||
|
||||
// findUserInContext scans the reader for a valid SELinux context
|
||||
// match that is verified with the verifier. Invalid contexts are
|
||||
// skipped. It returns a matched context or an empty string if no
|
||||
@@ -1338,6 +1407,33 @@ func findUserInContext(context Context, r io.Reader, verifier func(string) error
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// getFailsafeContext returns the context in the failsafe_context file:
|
||||
// https://www.man7.org/linux/man-pages/man5/failsafe_context.5.html
|
||||
func getFailsafeContext(context Context, r io.Reader, verifier func(string) error) (string, error) {
|
||||
conn := make([]byte, 256)
|
||||
limReader := io.LimitReader(r, int64(len(conn)))
|
||||
_, err := limReader.Read(conn)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read failsafe context: %w", err)
|
||||
}
|
||||
|
||||
conn = bytes.TrimSpace(conn)
|
||||
toConns := strings.SplitN(string(conn), ":", 4)
|
||||
if len(toConns) != 3 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
context["role"] = toConns[0]
|
||||
context["type"] = toConns[1]
|
||||
|
||||
outConn := context.get()
|
||||
if err := verifier(outConn); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return outConn, nil
|
||||
}
|
||||
|
||||
func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
|
||||
if c.verifier == nil {
|
||||
return "", ErrVerifierNil
|
||||
@@ -1352,18 +1448,45 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
|
||||
context["user"] = c.user
|
||||
context["level"] = c.level
|
||||
|
||||
conn, err := findUserInContext(context, c.userRdr, c.verifier)
|
||||
userRdr, err := c.openUserRdr()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("failed to open user context file: %w", err)
|
||||
}
|
||||
defer userRdr.Close()
|
||||
|
||||
conn, err := findUserInContext(context, userRdr, c.verifier)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read %q's user context file: %w", c.user, err)
|
||||
}
|
||||
|
||||
if conn != "" {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
conn, err = findUserInContext(context, c.defaultRdr, c.verifier)
|
||||
defaultRdr, err := c.openDefaultRdr()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", fmt.Errorf("failed to open default context file: %w", err)
|
||||
}
|
||||
defer defaultRdr.Close()
|
||||
|
||||
conn, err = findUserInContext(context, defaultRdr, c.verifier)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read default user context file: %w", err)
|
||||
}
|
||||
|
||||
if conn != "" {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
failsafeRdr, err := c.openFailsafeRdr()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open failsafe context file: %w", err)
|
||||
}
|
||||
defer failsafeRdr.Close()
|
||||
|
||||
conn, err = getFailsafeContext(context, failsafeRdr, c.verifier)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read failsafe_context: %w", err)
|
||||
}
|
||||
|
||||
if conn != "" {
|
||||
@@ -1375,26 +1498,17 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
|
||||
|
||||
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
|
||||
userPath := filepath.Join(policyRoot(), selinuxUsersDir, user)
|
||||
fu, err := os.Open(userPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fu.Close()
|
||||
|
||||
defaultPath := filepath.Join(policyRoot(), defaultContexts)
|
||||
fd, err := os.Open(defaultPath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
failsafePath := filepath.Join(policyRoot(), failsafeContext)
|
||||
|
||||
c := defaultSECtx{
|
||||
user: user,
|
||||
level: level,
|
||||
scon: scon,
|
||||
userRdr: fu,
|
||||
defaultRdr: fd,
|
||||
verifier: securityCheckContext,
|
||||
user: user,
|
||||
level: level,
|
||||
scon: scon,
|
||||
openUserRdr: createOpener(userPath),
|
||||
openDefaultRdr: createOpener(defaultPath),
|
||||
openFailsafeRdr: createOpener(failsafePath),
|
||||
verifier: securityCheckContext,
|
||||
}
|
||||
|
||||
return getDefaultContextFromReaders(&c)
|
||||
|
||||
+19
-15
@@ -1,5 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package selinux
|
||||
|
||||
@@ -41,22 +40,10 @@ func setFSCreateLabel(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func fsCreateLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func currentLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func pidLabel(int) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func execLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func canonicalizeContext(string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
@@ -69,7 +56,7 @@ func calculateGlbLub(string, string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func peerLabel(uintptr) (string, error) {
|
||||
func peerLabel(int) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
@@ -92,7 +79,12 @@ func newContext(string) (Context, error) {
|
||||
func clearLabels() {
|
||||
}
|
||||
|
||||
func reserveLabel(string) {
|
||||
func reserveLabel(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkLabel(string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func isMLSEnabled() bool {
|
||||
@@ -122,10 +114,18 @@ func kvmContainerLabels() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func kvmContainerLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func initContainerLabels() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
func initContainerLabel() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func containerLabels() (string, string) {
|
||||
return "", ""
|
||||
}
|
||||
@@ -146,6 +146,10 @@ func dupSecOpt(string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func getSeUserByName(string) (string, string, error) {
|
||||
return "", "", nil
|
||||
}
|
||||
|
||||
func getDefaultContextWithLevel(string, string, string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
+1
-4
@@ -1,6 +1,3 @@
|
||||
//go:build go1.16
|
||||
// +build go1.16
|
||||
|
||||
package pwalkdir
|
||||
|
||||
import (
|
||||
@@ -92,7 +89,7 @@ func WalkN(root string, walkFn fs.WalkDirFunc, num int) error {
|
||||
}()
|
||||
|
||||
wg.Add(num)
|
||||
for i := 0; i < num; i++ {
|
||||
for range num {
|
||||
go func() {
|
||||
for file := range files {
|
||||
if e := walkFn(file.path, file.entry, nil); e != nil {
|
||||
|
||||
Vendored
+2
-2
@@ -85,8 +85,8 @@ github.com/opencontainers/cgroups/systemd
|
||||
## explicit
|
||||
github.com/opencontainers/runtime-spec/specs-go
|
||||
github.com/opencontainers/runtime-spec/specs-go/features
|
||||
# github.com/opencontainers/selinux v1.13.1
|
||||
## explicit; go 1.19
|
||||
# github.com/opencontainers/selinux v1.14.1
|
||||
## explicit; go 1.22
|
||||
github.com/opencontainers/selinux/go-selinux
|
||||
github.com/opencontainers/selinux/go-selinux/label
|
||||
github.com/opencontainers/selinux/pkg/pwalkdir
|
||||
|
||||
Reference in New Issue
Block a user