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:
parent
0a5cec2833
commit
a8216806ce
11 changed files with 418 additions and 251 deletions
|
@ -23,7 +23,7 @@ import (
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
volumemounts "github.com/docker/docker/volume/mounts"
|
volumemounts "github.com/docker/docker/volume/mounts"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -97,9 +97,7 @@ func (daemon *Daemon) load(id string) (*container.Container, error) {
|
||||||
if err := ctr.FromDisk(); err != nil {
|
if err := ctr.FromDisk(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := label.ReserveLabel(ctr.ProcessLabel); err != nil {
|
selinux.ReserveLabel(ctr.ProcessLabel)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctr.ID != id {
|
if ctr.ID != id {
|
||||||
return ctr, fmt.Errorf("Container %s is stored at %s", ctr.ID, id)
|
return ctr, fmt.Errorf("Container %s is stored at %s", ctr.ID, id)
|
||||||
|
|
|
@ -16,7 +16,7 @@ import (
|
||||||
"github.com/docker/docker/pkg/idtools"
|
"github.com/docker/docker/pkg/idtools"
|
||||||
"github.com/docker/docker/pkg/system"
|
"github.com/docker/docker/pkg/system"
|
||||||
"github.com/docker/docker/runconfig"
|
"github.com/docker/docker/runconfig"
|
||||||
"github.com/opencontainers/selinux/go-selinux/label"
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -247,7 +247,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
|
||||||
pidMode := hostConfig.PidMode
|
pidMode := hostConfig.PidMode
|
||||||
privileged := hostConfig.Privileged
|
privileged := hostConfig.Privileged
|
||||||
if ipcMode.IsHost() || pidMode.IsHost() || privileged {
|
if ipcMode.IsHost() || pidMode.IsHost() || privileged {
|
||||||
return toHostConfigSelinuxLabels(label.DisableSecOpt()), nil
|
return toHostConfigSelinuxLabels(selinux.DisableSecOpt()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var ipcLabel []string
|
var ipcLabel []string
|
||||||
|
@ -259,7 +259,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
ipcLabel, err = label.DupSecOpt(c.ProcessLabel)
|
ipcLabel, err = selinux.DupSecOpt(c.ProcessLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,7 @@ func (daemon *Daemon) generateSecurityOpt(hostConfig *containertypes.HostConfig)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pidLabel, err = label.DupSecOpt(c.ProcessLabel)
|
pidLabel, err = selinux.DupSecOpt(c.ProcessLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,6 +168,6 @@ github.com/morikuni/aec 39771216ff4c63d11f5e604076f9
|
||||||
# metrics
|
# metrics
|
||||||
github.com/docker/go-metrics b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
|
github.com/docker/go-metrics b619b3592b65de4f087d9f16863a7e6ff905973c # v0.0.1
|
||||||
|
|
||||||
github.com/opencontainers/selinux 31f70552238c5e017d78c3f1ba65e85f593f48e0 # v1.3.3
|
github.com/opencontainers/selinux 0d49ba2a6aae052c614dfe5de62a158711a6c461 # v1.5.1
|
||||||
|
|
||||||
# DO NOT EDIT BELOW THIS LINE -------- reserved for downstream projects --------
|
# DO NOT EDIT BELOW THIS LINE -------- reserved for downstream projects --------
|
||||||
|
|
134
vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
generated
vendored
134
vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
generated
vendored
|
@ -1,109 +1,77 @@
|
||||||
// +build !selinux !linux
|
|
||||||
|
|
||||||
package label
|
package label
|
||||||
|
|
||||||
// InitLabels returns the process label and file labels to be used within
|
import (
|
||||||
// the container. A list of options can be passed into this function to alter
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
// the labels.
|
)
|
||||||
func InitLabels(options []string) (string, string, error) {
|
|
||||||
return "", "", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ROMountLabel() string {
|
// Deprecated: use selinux.ROFileLabel
|
||||||
return ""
|
var ROMountLabel = selinux.ROFileLabel
|
||||||
}
|
|
||||||
|
|
||||||
func GenLabels(options string) (string, string, error) {
|
// SetProcessLabel takes a process label and tells the kernel to assign the
|
||||||
return "", "", nil
|
// 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 {
|
// ProcessLabel returns the process label that the kernel will assign
|
||||||
return src
|
// 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 {
|
// SetSocketLabel takes a process label and tells the kernel to assign the
|
||||||
return nil
|
// label to the next socket that gets created
|
||||||
}
|
// Deprecated: use selinux.SetSocketLabel
|
||||||
|
var SetSocketLabel = selinux.SetSocketLabel
|
||||||
|
|
||||||
func ProcessLabel() (string, error) {
|
// SocketLabel retrieves the current default socket label setting
|
||||||
return "", nil
|
// Deprecated: use selinux.SocketLabel
|
||||||
}
|
var SocketLabel = selinux.SocketLabel
|
||||||
|
|
||||||
func SetSocketLabel(processLabel string) error {
|
// SetKeyLabel takes a process label and tells the kernel to assign the
|
||||||
return nil
|
// label to the next kernel keyring that gets created
|
||||||
}
|
// Deprecated: use selinux.SetKeyLabel
|
||||||
|
var SetKeyLabel = selinux.SetKeyLabel
|
||||||
|
|
||||||
func SocketLabel() (string, error) {
|
// KeyLabel retrieves the current default kernel keyring label setting
|
||||||
return "", nil
|
// Deprecated: use selinux.KeyLabel
|
||||||
}
|
var KeyLabel = selinux.KeyLabel
|
||||||
|
|
||||||
func SetKeyLabel(processLabel string) error {
|
// FileLabel returns the label for specified path
|
||||||
return nil
|
// Deprecated: use selinux.FileLabel
|
||||||
}
|
var FileLabel = selinux.FileLabel
|
||||||
|
|
||||||
func KeyLabel() (string, error) {
|
// PidLabel will return the label of the process running with the specified pid
|
||||||
return "", nil
|
// Deprecated: use selinux.PidLabel
|
||||||
}
|
var PidLabel = selinux.PidLabel
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Init initialises the labeling system
|
||||||
func Init() {
|
func Init() {
|
||||||
|
selinux.GetEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearLabels clears all reserved labels
|
// ClearLabels will clear all reserved labels
|
||||||
func ClearLabels() {
|
// Deprecated: use selinux.ClearLabels
|
||||||
return
|
var ClearLabels = selinux.ClearLabels
|
||||||
}
|
|
||||||
|
|
||||||
|
// ReserveLabel will record the fact that the MCS label has already been used.
|
||||||
|
// This will prevent InitLabels from using the MCS label in a newly created
|
||||||
|
// container
|
||||||
|
// Deprecated: use selinux.ReserveLabel
|
||||||
func ReserveLabel(label string) error {
|
func ReserveLabel(label string) error {
|
||||||
|
selinux.ReserveLabel(label)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReleaseLabel will remove the reservation of the MCS label.
|
||||||
|
// This will allow InitLabels to use the MCS label in a newly created
|
||||||
|
// containers
|
||||||
|
// Deprecated: use selinux.ReleaseLabel
|
||||||
func ReleaseLabel(label string) error {
|
func ReleaseLabel(label string) error {
|
||||||
|
selinux.ReleaseLabel(label)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DupSecOpt takes a process label and returns security options that
|
// DupSecOpt takes a process label and returns security options that
|
||||||
// can be used to set duplicate labels on future container processes
|
// can be used to set duplicate labels on future container processes
|
||||||
func DupSecOpt(src string) ([]string, error) {
|
// Deprecated: use selinux.DupSecOpt
|
||||||
return nil, nil
|
var DupSecOpt = selinux.DupSecOpt
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
122
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
generated
vendored
122
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
generated
vendored
|
@ -9,6 +9,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/opencontainers/selinux/go-selinux"
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Valid Label Options
|
// Valid Label Options
|
||||||
|
@ -21,7 +22,7 @@ var validOptions = map[string]bool{
|
||||||
"level": true,
|
"level": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
var ErrIncompatibleLabel = fmt.Errorf("Bad SELinux option z and Z can not be used together")
|
var ErrIncompatibleLabel = errors.New("Bad SELinux option z and Z can not be used together")
|
||||||
|
|
||||||
// InitLabels returns the process label and file labels to be used within
|
// InitLabels returns the process label and file labels to be used within
|
||||||
// the container. A list of options can be passed into this function to alter
|
// the container. A list of options can be passed into this function to alter
|
||||||
|
@ -35,7 +36,7 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
|
||||||
if processLabel != "" {
|
if processLabel != "" {
|
||||||
defer func() {
|
defer func() {
|
||||||
if Err != nil {
|
if Err != nil {
|
||||||
ReleaseLabel(mountLabel)
|
selinux.ReleaseLabel(mountLabel)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
pcon, err := selinux.NewContext(processLabel)
|
pcon, err := selinux.NewContext(processLabel)
|
||||||
|
@ -52,11 +53,11 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
|
||||||
return "", mountLabel, nil
|
return "", mountLabel, nil
|
||||||
}
|
}
|
||||||
if i := strings.Index(opt, ":"); i == -1 {
|
if i := strings.Index(opt, ":"); i == -1 {
|
||||||
return "", "", fmt.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
|
return "", "", errors.Errorf("Bad label option %q, valid options 'disable' or \n'user, role, level, type, filetype' followed by ':' and a value", opt)
|
||||||
}
|
}
|
||||||
con := strings.SplitN(opt, ":", 2)
|
con := strings.SplitN(opt, ":", 2)
|
||||||
if !validOptions[con[0]] {
|
if !validOptions[con[0]] {
|
||||||
return "", "", fmt.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
|
return "", "", errors.Errorf("Bad label option %q, valid options 'disable, user, role, level, type, filetype'", con[0])
|
||||||
|
|
||||||
}
|
}
|
||||||
if con[0] == "filetype" {
|
if con[0] == "filetype" {
|
||||||
|
@ -67,19 +68,16 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
|
||||||
mcon[con[0]] = con[1]
|
mcon[con[0]] = con[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ = ReleaseLabel(processLabel)
|
selinux.ReleaseLabel(processLabel)
|
||||||
processLabel = pcon.Get()
|
processLabel = pcon.Get()
|
||||||
mountLabel = mcon.Get()
|
mountLabel = mcon.Get()
|
||||||
_ = ReserveLabel(processLabel)
|
selinux.ReserveLabel(processLabel)
|
||||||
}
|
}
|
||||||
return processLabel, mountLabel, nil
|
return processLabel, mountLabel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ROMountLabel() string {
|
// Deprecated: The GenLabels function is only to be used during the transition
|
||||||
return selinux.ROFileLabel()
|
// to the official API. Use InitLabels(strings.Fields(options)) instead.
|
||||||
}
|
|
||||||
|
|
||||||
// DEPRECATED: The GenLabels function is only to be used during the transition to the official API.
|
|
||||||
func GenLabels(options string) (string, string, error) {
|
func GenLabels(options string) (string, string, error) {
|
||||||
return InitLabels(strings.Fields(options))
|
return InitLabels(strings.Fields(options))
|
||||||
}
|
}
|
||||||
|
@ -102,71 +100,27 @@ func FormatMountLabel(src, mountLabel string) string {
|
||||||
return src
|
return src
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetProcessLabel takes a process label and tells the kernel to assign the
|
|
||||||
// label to the next program executed by the current process.
|
|
||||||
func SetProcessLabel(processLabel string) error {
|
|
||||||
return selinux.SetExecLabel(processLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetSocketLabel takes a process label and tells the kernel to assign the
|
|
||||||
// label to the next socket that gets created
|
|
||||||
func SetSocketLabel(processLabel string) error {
|
|
||||||
return selinux.SetSocketLabel(processLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SocketLabel retrieves the current default socket label setting
|
|
||||||
func SocketLabel() (string, error) {
|
|
||||||
return selinux.SocketLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetKeyLabel takes a process label and tells the kernel to assign the
|
|
||||||
// label to the next kernel keyring that gets created
|
|
||||||
func SetKeyLabel(processLabel string) error {
|
|
||||||
return selinux.SetKeyLabel(processLabel)
|
|
||||||
}
|
|
||||||
|
|
||||||
// KeyLabel retrieves the current default kernel keyring label setting
|
|
||||||
func KeyLabel() (string, error) {
|
|
||||||
return selinux.KeyLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ProcessLabel returns the process label that the kernel will assign
|
|
||||||
// to the next program executed by the current process. If "" is returned
|
|
||||||
// this indicates that the default labeling will happen for the process.
|
|
||||||
func ProcessLabel() (string, error) {
|
|
||||||
return selinux.ExecLabel()
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileLabel returns the label for specified path
|
|
||||||
func FileLabel(path string) (string, error) {
|
|
||||||
return selinux.FileLabel(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetFileLabel modifies the "path" label to the specified file label
|
// SetFileLabel modifies the "path" label to the specified file label
|
||||||
func SetFileLabel(path string, fileLabel string) error {
|
func SetFileLabel(path string, fileLabel string) error {
|
||||||
if selinux.GetEnabled() && fileLabel != "" {
|
if !selinux.GetEnabled() || fileLabel == "" {
|
||||||
return selinux.SetFileLabel(path, fileLabel)
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return selinux.SetFileLabel(path, fileLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFileCreateLabel tells the kernel the label for all files to be created
|
// SetFileCreateLabel tells the kernel the label for all files to be created
|
||||||
func SetFileCreateLabel(fileLabel string) error {
|
func SetFileCreateLabel(fileLabel string) error {
|
||||||
if selinux.GetEnabled() {
|
if !selinux.GetEnabled() {
|
||||||
return selinux.SetFSCreateLabel(fileLabel)
|
return nil
|
||||||
}
|
}
|
||||||
return nil
|
return selinux.SetFSCreateLabel(fileLabel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relabel changes the label of path to the filelabel string.
|
// Relabel changes the label of path to the filelabel string.
|
||||||
// It changes the MCS label to s0 if shared is true.
|
// It changes the MCS label to s0 if shared is true.
|
||||||
// This will allow all containers to share the content.
|
// This will allow all containers to share the content.
|
||||||
func Relabel(path string, fileLabel string, shared bool) error {
|
func Relabel(path string, fileLabel string, shared bool) error {
|
||||||
if !selinux.GetEnabled() {
|
if !selinux.GetEnabled() || fileLabel == "" {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if fileLabel == "" {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +165,7 @@ func Relabel(path string, fileLabel string, shared bool) error {
|
||||||
path = strings.TrimSuffix(path, "/")
|
path = strings.TrimSuffix(path, "/")
|
||||||
}
|
}
|
||||||
if exclude_paths[path] {
|
if exclude_paths[path] {
|
||||||
return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
|
return errors.Errorf("SELinux relabeling of %s is not allowed", path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if shared {
|
if shared {
|
||||||
|
@ -229,48 +183,10 @@ func Relabel(path string, fileLabel string, shared bool) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PidLabel will return the label of the process running with the specified pid
|
|
||||||
func PidLabel(pid int) (string, error) {
|
|
||||||
return selinux.PidLabel(pid)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init initialises the labeling system
|
|
||||||
func Init() {
|
|
||||||
selinux.GetEnabled()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClearLabels will clear all reserved labels
|
|
||||||
func ClearLabels() {
|
|
||||||
selinux.ClearLabels()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReserveLabel will record the fact that the MCS label has already been used.
|
|
||||||
// This will prevent InitLabels from using the MCS label in a newly created
|
|
||||||
// container
|
|
||||||
func ReserveLabel(label string) error {
|
|
||||||
selinux.ReserveLabel(label)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ReleaseLabel will remove the reservation of the MCS label.
|
|
||||||
// This will allow InitLabels to use the MCS label in a newly created
|
|
||||||
// containers
|
|
||||||
func ReleaseLabel(label string) error {
|
|
||||||
selinux.ReleaseLabel(label)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DupSecOpt takes a process label and returns security options that
|
|
||||||
// can be used to set duplicate labels on future container processes
|
|
||||||
func DupSecOpt(src string) ([]string, error) {
|
|
||||||
return selinux.DupSecOpt(src)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableSecOpt returns a security opt that can disable labeling
|
// DisableSecOpt returns a security opt that can disable labeling
|
||||||
// support for future container processes
|
// support for future container processes
|
||||||
func DisableSecOpt() []string {
|
// Deprecated: use selinux.DisableSecOpt
|
||||||
return selinux.DisableSecOpt()
|
var DisableSecOpt = selinux.DisableSecOpt
|
||||||
}
|
|
||||||
|
|
||||||
// Validate checks that the label does not include unexpected options
|
// Validate checks that the label does not include unexpected options
|
||||||
func Validate(label string) error {
|
func Validate(label string) error {
|
||||||
|
|
54
vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go
generated
vendored
Normal file
54
vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go
generated
vendored
Normal 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
|
||||||
|
}
|
166
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
166
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
|
@ -17,8 +17,8 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
|
"github.com/opencontainers/selinux/pkg/pwalk"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
@ -31,13 +31,13 @@ const (
|
||||||
// Disabled constant to indicate SELinux is disabled
|
// Disabled constant to indicate SELinux is disabled
|
||||||
Disabled = -1
|
Disabled = -1
|
||||||
|
|
||||||
|
contextFile = "/usr/share/containers/selinux/contexts"
|
||||||
selinuxDir = "/etc/selinux/"
|
selinuxDir = "/etc/selinux/"
|
||||||
selinuxConfig = selinuxDir + "config"
|
selinuxConfig = selinuxDir + "config"
|
||||||
selinuxfsMount = "/sys/fs/selinux"
|
selinuxfsMount = "/sys/fs/selinux"
|
||||||
selinuxTypeTag = "SELINUXTYPE"
|
selinuxTypeTag = "SELINUXTYPE"
|
||||||
selinuxTag = "SELINUX"
|
selinuxTag = "SELINUX"
|
||||||
xattrNameSelinux = "security.selinux"
|
xattrNameSelinux = "security.selinux"
|
||||||
stRdOnly = 0x01
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type selinuxState struct {
|
type selinuxState struct {
|
||||||
|
@ -103,13 +103,13 @@ func SetDisabled() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifySELinuxfsMount(mnt string) bool {
|
func verifySELinuxfsMount(mnt string) bool {
|
||||||
var buf syscall.Statfs_t
|
var buf unix.Statfs_t
|
||||||
for {
|
for {
|
||||||
err := syscall.Statfs(mnt, &buf)
|
err := unix.Statfs(mnt, &buf)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if err == syscall.EAGAIN {
|
if err == unix.EAGAIN {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
@ -118,7 +118,7 @@ func verifySELinuxfsMount(mnt string) bool {
|
||||||
if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
|
if uint32(buf.Type) != uint32(unix.SELINUX_MAGIC) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (buf.Flags & stRdOnly) != 0 {
|
if (buf.Flags & unix.ST_RDONLY) != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,10 +251,10 @@ func isProcHandle(fh *os.File) error {
|
||||||
var buf unix.Statfs_t
|
var buf unix.Statfs_t
|
||||||
err := unix.Fstatfs(int(fh.Fd()), &buf)
|
err := unix.Fstatfs(int(fh.Fd()), &buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err)
|
return errors.Wrapf(err, "statfs(%q) failed", fh.Name())
|
||||||
}
|
}
|
||||||
if buf.Type != unix.PROC_SUPER_MAGIC {
|
if buf.Type != unix.PROC_SUPER_MAGIC {
|
||||||
return fmt.Errorf("file %q is not on procfs", fh.Name())
|
return errors.Errorf("file %q is not on procfs", fh.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -282,12 +282,29 @@ func readCon(fpath string) (string, error) {
|
||||||
return strings.Trim(retval, "\x00"), nil
|
return strings.Trim(retval, "\x00"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error
|
||||||
|
func ClassIndex(class string) (int, error) {
|
||||||
|
permpath := fmt.Sprintf("class/%s/index", class)
|
||||||
|
indexpath := filepath.Join(getSelinuxMountPoint(), permpath)
|
||||||
|
|
||||||
|
indexB, err := ioutil.ReadFile(indexpath)
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
index, err := strconv.Atoi(string(indexB))
|
||||||
|
if err != nil {
|
||||||
|
return -1, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return index, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetFileLabel sets the SELinux label for this path or returns an error.
|
// SetFileLabel sets the SELinux label for this path or returns an error.
|
||||||
func SetFileLabel(fpath string, label string) error {
|
func SetFileLabel(fpath string, label string) error {
|
||||||
if fpath == "" {
|
if fpath == "" {
|
||||||
return ErrEmptyPath
|
return ErrEmptyPath
|
||||||
}
|
}
|
||||||
if err := lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
|
if err := unix.Lsetxattr(fpath, xattrNameSelinux, []byte(label), 0); err != nil {
|
||||||
return errors.Wrapf(err, "failed to set file label on %s", fpath)
|
return errors.Wrapf(err, "failed to set file label on %s", fpath)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@ -390,7 +407,7 @@ func attrPath(attr string) string {
|
||||||
return path.Join(threadSelfPrefix, attr)
|
return path.Join(threadSelfPrefix, attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return path.Join("/proc/self/task/", strconv.Itoa(syscall.Gettid()), "/attr/", attr)
|
return path.Join("/proc/self/task/", strconv.Itoa(unix.Gettid()), "/attr/", attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func readAttr(attr string) (string, error) {
|
func readAttr(attr string) (string, error) {
|
||||||
|
@ -410,6 +427,18 @@ func CanonicalizeContext(val string) (string, error) {
|
||||||
return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
|
return readWriteCon(filepath.Join(getSelinuxMountPoint(), "context"), val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ComputeCreateContext requests the type transition from source to target for class from the kernel.
|
||||||
|
*/
|
||||||
|
func ComputeCreateContext(source string, target string, class string) (string, error) {
|
||||||
|
classidx, err := ClassIndex(class)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return readWriteCon(filepath.Join(getSelinuxMountPoint(), "create"), fmt.Sprintf("%s %s %d", source, target, classidx))
|
||||||
|
}
|
||||||
|
|
||||||
func readWriteCon(fpath string, val string) (string, error) {
|
func readWriteCon(fpath string, val string) (string, error) {
|
||||||
if fpath == "" {
|
if fpath == "" {
|
||||||
return "", ErrEmptyPath
|
return "", ErrEmptyPath
|
||||||
|
@ -461,17 +490,17 @@ func SocketLabel() (string, error) {
|
||||||
|
|
||||||
// PeerLabel retrieves the label of the client on the other side of a socket
|
// PeerLabel retrieves the label of the client on the other side of a socket
|
||||||
func PeerLabel(fd uintptr) (string, error) {
|
func PeerLabel(fd uintptr) (string, error) {
|
||||||
return unix.GetsockoptString(int(fd), syscall.SOL_SOCKET, syscall.SO_PEERSEC)
|
return unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetKeyLabel takes a process label and tells the kernel to assign the
|
// SetKeyLabel takes a process label and tells the kernel to assign the
|
||||||
// label to the next kernel keyring that gets created
|
// label to the next kernel keyring that gets created
|
||||||
func SetKeyLabel(label string) error {
|
func SetKeyLabel(label string) error {
|
||||||
err := writeCon("/proc/self/attr/keycreate", label)
|
err := writeCon("/proc/self/attr/keycreate", label)
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(errors.Cause(err)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if label == "" && os.IsPermission(err) {
|
if label == "" && os.IsPermission(errors.Cause(err)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
@ -656,23 +685,26 @@ func ROFileLabel() string {
|
||||||
return roFileLabel
|
return roFileLabel
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
func openContextFile() (*os.File, error) {
|
||||||
ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
if f, err := os.Open(contextFile); err == nil {
|
||||||
container labeling by the calling process.
|
return f, nil
|
||||||
*/
|
}
|
||||||
func ContainerLabels() (processLabel string, fileLabel string) {
|
lxcPath := filepath.Join(getSELinuxPolicyRoot(), "/contexts/lxc_contexts")
|
||||||
|
return os.Open(lxcPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
var labels = loadLabels()
|
||||||
|
|
||||||
|
func loadLabels() map[string]string {
|
||||||
var (
|
var (
|
||||||
val, key string
|
val, key string
|
||||||
bufin *bufio.Reader
|
bufin *bufio.Reader
|
||||||
)
|
)
|
||||||
|
|
||||||
if !GetEnabled() {
|
labels := make(map[string]string)
|
||||||
return "", ""
|
in, err := openContextFile()
|
||||||
}
|
|
||||||
lxcPath := fmt.Sprintf("%s/contexts/lxc_contexts", getSELinuxPolicyRoot())
|
|
||||||
in, err := os.Open(lxcPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", ""
|
return labels
|
||||||
}
|
}
|
||||||
defer in.Close()
|
defer in.Close()
|
||||||
|
|
||||||
|
@ -684,7 +716,7 @@ func ContainerLabels() (processLabel string, fileLabel string) {
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
done = true
|
done = true
|
||||||
} else {
|
} else {
|
||||||
goto exit
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
|
@ -698,26 +730,64 @@ func ContainerLabels() (processLabel string, fileLabel string) {
|
||||||
}
|
}
|
||||||
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
|
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
|
||||||
key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
|
key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
|
||||||
if key == "process" {
|
labels[key] = strings.Trim(val, "\"")
|
||||||
processLabel = strings.Trim(val, "\"")
|
|
||||||
}
|
|
||||||
if key == "file" {
|
|
||||||
fileLabel = strings.Trim(val, "\"")
|
|
||||||
}
|
|
||||||
if key == "ro_file" {
|
|
||||||
roFileLabel = strings.Trim(val, "\"")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if processLabel == "" || fileLabel == "" {
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
KVMContainerLabels returns the default processLabel and mountLabel to be used
|
||||||
|
for kvm containers by the calling process.
|
||||||
|
*/
|
||||||
|
func KVMContainerLabels() (string, string) {
|
||||||
|
processLabel := labels["kvm_process"]
|
||||||
|
if processLabel == "" {
|
||||||
|
processLabel = labels["process"]
|
||||||
|
}
|
||||||
|
|
||||||
|
return addMcs(processLabel, labels["file"])
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
InitContainerLabels returns the default processLabel and file labels to be
|
||||||
|
used for containers running an init system like systemd by the calling process.
|
||||||
|
*/
|
||||||
|
func InitContainerLabels() (string, string) {
|
||||||
|
processLabel := labels["init_process"]
|
||||||
|
if processLabel == "" {
|
||||||
|
processLabel = labels["process"]
|
||||||
|
}
|
||||||
|
|
||||||
|
return addMcs(processLabel, labels["file"])
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
||||||
|
container labeling by the calling process.
|
||||||
|
*/
|
||||||
|
func ContainerLabels() (processLabel string, fileLabel string) {
|
||||||
|
if !GetEnabled() {
|
||||||
return "", ""
|
return "", ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processLabel = labels["process"]
|
||||||
|
fileLabel = labels["file"]
|
||||||
|
roFileLabel = labels["ro_file"]
|
||||||
|
|
||||||
|
if processLabel == "" || fileLabel == "" {
|
||||||
|
return "", fileLabel
|
||||||
|
}
|
||||||
|
|
||||||
if roFileLabel == "" {
|
if roFileLabel == "" {
|
||||||
roFileLabel = fileLabel
|
roFileLabel = fileLabel
|
||||||
}
|
}
|
||||||
exit:
|
|
||||||
|
return addMcs(processLabel, fileLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addMcs(processLabel, fileLabel string) (string, string) {
|
||||||
scon, _ := NewContext(processLabel)
|
scon, _ := NewContext(processLabel)
|
||||||
if scon["level"] != "" {
|
if scon["level"] != "" {
|
||||||
mcs := uniqMcs(1024)
|
mcs := uniqMcs(1024)
|
||||||
|
@ -772,14 +842,14 @@ func badPrefix(fpath string) error {
|
||||||
badPrefixes := []string{"/usr"}
|
badPrefixes := []string{"/usr"}
|
||||||
for _, prefix := range badPrefixes {
|
for _, prefix := range badPrefixes {
|
||||||
if strings.HasPrefix(fpath, prefix) {
|
if strings.HasPrefix(fpath, prefix) {
|
||||||
return fmt.Errorf("relabeling content in %s is not allowed", prefix)
|
return errors.Errorf("relabeling content in %s is not allowed", prefix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chcon changes the `fpath` file object to the SELinux label `label`.
|
// Chcon changes the fpath file object to the SELinux label label.
|
||||||
// If `fpath` is a directory and `recurse`` is true, Chcon will walk the
|
// If fpath is a directory and recurse is true, Chcon will walk the
|
||||||
// directory tree setting the label.
|
// directory tree setting the label.
|
||||||
func Chcon(fpath string, label string, recurse bool) error {
|
func Chcon(fpath string, label string, recurse bool) error {
|
||||||
if fpath == "" {
|
if fpath == "" {
|
||||||
|
@ -791,19 +861,19 @@ func Chcon(fpath string, label string, recurse bool) error {
|
||||||
if err := badPrefix(fpath); err != nil {
|
if err := badPrefix(fpath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
callback := func(p string, info os.FileInfo, err error) error {
|
|
||||||
|
if !recurse {
|
||||||
|
return SetFileLabel(fpath, label)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pwalk.Walk(fpath, func(p string, info os.FileInfo, err error) error {
|
||||||
e := SetFileLabel(p, label)
|
e := SetFileLabel(p, label)
|
||||||
if os.IsNotExist(e) {
|
// Walk a file tree can race with removal, so ignore ENOENT
|
||||||
|
if os.IsNotExist(errors.Cause(e)) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
}
|
})
|
||||||
|
|
||||||
if recurse {
|
|
||||||
return filepath.Walk(fpath, callback)
|
|
||||||
}
|
|
||||||
|
|
||||||
return SetFileLabel(fpath, label)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DupSecOpt takes an SELinux process label and returns security options that
|
// DupSecOpt takes an SELinux process label and returns security options that
|
||||||
|
|
28
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
28
vendor/github.com/opencontainers/selinux/go-selinux/selinux_stub.go
generated
vendored
|
@ -1,4 +1,4 @@
|
||||||
// +build !selinux
|
// +build !selinux !linux
|
||||||
|
|
||||||
package selinux
|
package selinux
|
||||||
|
|
||||||
|
@ -35,6 +35,11 @@ func GetEnabled() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClassIndex returns the int index for an object class in the loaded policy, or -1 and an error
|
||||||
|
func ClassIndex(class string) (int, error) {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
|
||||||
// SetFileLabel sets the SELinux label for this path or returns an error.
|
// SetFileLabel sets the SELinux label for this path or returns an error.
|
||||||
func SetFileLabel(fpath string, label string) error {
|
func SetFileLabel(fpath string, label string) error {
|
||||||
return nil
|
return nil
|
||||||
|
@ -88,6 +93,13 @@ func CanonicalizeContext(val string) (string, error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ComputeCreateContext requests the type transition from source to target for class from the kernel.
|
||||||
|
*/
|
||||||
|
func ComputeCreateContext(source string, target string, class string) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SetExecLabel sets the SELinux label that the kernel will use for any programs
|
SetExecLabel sets the SELinux label that the kernel will use for any programs
|
||||||
that are executed by the current process thread, or an error.
|
that are executed by the current process thread, or an error.
|
||||||
|
@ -101,7 +113,7 @@ SetTaskLabel sets the SELinux label for the current thread, or an error.
|
||||||
This requires the dyntransition permission.
|
This requires the dyntransition permission.
|
||||||
*/
|
*/
|
||||||
func SetTaskLabel(label string) error {
|
func SetTaskLabel(label string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -189,6 +201,18 @@ func ROFileLabel() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// KVMContainerLabels returns the default processLabel and mountLabel to be used
|
||||||
|
// for kvm containers by the calling process.
|
||||||
|
func KVMContainerLabels() (string, string) {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitContainerLabels returns the default processLabel and file labels to be
|
||||||
|
// used for containers running an init system like systemd by the calling
|
||||||
|
func InitContainerLabels() (string, string) {
|
||||||
|
return "", ""
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
ContainerLabels returns an allocated processLabel and fileLabel to be used for
|
||||||
container labeling by the calling process.
|
container labeling by the calling process.
|
||||||
|
|
8
vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
generated
vendored
8
vendor/github.com/opencontainers/selinux/go-selinux/xattrs.go
generated
vendored
|
@ -12,8 +12,8 @@ func lgetxattr(path string, attr string) ([]byte, error) {
|
||||||
// Start with a 128 length byte array
|
// Start with a 128 length byte array
|
||||||
dest := make([]byte, 128)
|
dest := make([]byte, 128)
|
||||||
sz, errno := unix.Lgetxattr(path, attr, dest)
|
sz, errno := unix.Lgetxattr(path, attr, dest)
|
||||||
if errno == unix.ERANGE {
|
for errno == unix.ERANGE {
|
||||||
// Buffer too small, get the real size first
|
// Buffer too small, use zero-sized buffer to get the actual size
|
||||||
sz, errno = unix.Lgetxattr(path, attr, []byte{})
|
sz, errno = unix.Lgetxattr(path, attr, []byte{})
|
||||||
if errno != nil {
|
if errno != nil {
|
||||||
return nil, errno
|
return nil, errno
|
||||||
|
@ -28,7 +28,3 @@ func lgetxattr(path string, attr string) ([]byte, error) {
|
||||||
|
|
||||||
return dest[:sz], nil
|
return dest[:sz], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func lsetxattr(path string, attr string, data []byte, flags int) error {
|
|
||||||
return unix.Lsetxattr(path, attr, data, flags)
|
|
||||||
}
|
|
||||||
|
|
42
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
Normal file
42
vendor/github.com/opencontainers/selinux/pkg/pwalk/README.md
generated
vendored
Normal 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.
|
99
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
Normal file
99
vendor/github.com/opencontainers/selinux/pkg/pwalk/pwalk.go
generated
vendored
Normal 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
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue