New Upstream Release - golang-github-opencontainers-selinux
Ready changes
Summary
Merged new upstream version: 1.11.0+ds1 (was: 1.10.2+ds1).
Resulting package
Built on 2023-05-26T11:38 (took 4m33s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases golang-github-opencontainers-selinux-dev
Lintian Result
Diff
diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml
index cd1e6a8..7331776 100644
--- a/.github/workflows/validate.yml
+++ b/.github/workflows/validate.yml
@@ -30,40 +30,52 @@ jobs:
lint:
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - uses: golangci/golangci-lint-action@v2
+ - uses: actions/checkout@v3
+ - uses: actions/setup-go@v3
with:
- # must be specified without patch version
- version: v1.36
- # Only show new issues for a pull request.
- only-new-issues: true
+ go-version: 1.20.x
+ - uses: golangci/golangci-lint-action@v3
+ with:
+ version: v1.51
cross:
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
- - name: cross
- run: make build-cross
+ - uses: actions/checkout@v3
+ - name: cross
+ run: make build-cross
+ test-stubs:
+ runs-on: macos-latest
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-go@v3
+ with:
+ go-version: 1.20.x
+ - uses: golangci/golangci-lint-action@v3
+ with:
+ version: v1.51
+ - name: test-stubs
+ run: make test
test:
strategy:
fail-fast: false
matrix:
- go-version: [1.15.x, 1.16.x, 1.17.x]
+ go-version: [1.19.x, 1.20.x]
race: ["-race", ""]
runs-on: ubuntu-20.04
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- - name: install go ${{ matrix.go-version }}
- uses: actions/setup-go@v2
- with:
- stable: '!contains(${{ matrix.go-version }}, "beta") && !contains(${{ matrix.go-version }}, "rc")'
- go-version: ${{ matrix.go-version }}
+ - name: install go ${{ matrix.go-version }}
+ uses: actions/setup-go@v3
+ with:
+ stable: '!contains(${{ matrix.go-version }}, "beta") && !contains(${{ matrix.go-version }}, "rc")'
+ go-version: ${{ matrix.go-version }}
- - name: build
- run: make BUILDFLAGS="${{ matrix.race }}" build
+ - name: build
+ run: make BUILDFLAGS="${{ matrix.race }}" build
- - name: test
- run: make TESTFLAGS="${{ matrix.race }}" test
+ - name: test
+ run: make TESTFLAGS="${{ matrix.race }}" test
diff --git a/.golangci.yml b/.golangci.yml
index b7bec81..a570a2e 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -4,7 +4,33 @@ run:
deadline: 5m
linters:
enable:
- - whitespace
- - gocritic
- - errorlint
- - gofumpt
+ - dupword # Detects duplicate words.
+ - errorlint # Detects code that may cause problems with Go 1.13 error wrapping.
+ - exportloopref # Detects pointers to enclosing loop variables.
+ - gocritic # Metalinter; detects bugs, performance, and styling issues.
+ - gofumpt # Detects whether code was gofumpt-ed.
+ - gosec # Detects security problems.
+ - misspell # Detects commonly misspelled English words in comments.
+ - nilerr # Detects code that returns nil even if it checks that the error is not nil.
+ - nolintlint # Detects ill-formed or insufficient nolint directives.
+ - prealloc # Detects slice declarations that could potentially be pre-allocated.
+ - predeclared # Detects code that shadows one of Go's predeclared identifiers
+ - revive # Metalinter; drop-in replacement for golint.
+ - tenv # Detects using os.Setenv instead of t.Setenv.
+ - thelper # Detects test helpers without t.Helper().
+ - tparallel # Detects inappropriate usage of t.Parallel().
+ - unconvert # Detects unnecessary type conversions.
+linters-settings:
+ govet:
+ check-shadowing: true
+ enable-all: true
+ settings:
+ shadow:
+ strict: true
+issues:
+ max-issues-per-linter: 0
+ max-same-issues: 0
+ exclude-rules:
+ - text: '^shadow: declaration of "err" shadows declaration'
+ linters:
+ - govet
diff --git a/Makefile b/Makefile
index c19a9e6..c39d6e0 100644
--- a/Makefile
+++ b/Makefile
@@ -33,5 +33,4 @@ lint:
.PHONY: vendor
vendor:
$(GO) mod tidy
- $(GO) mod vendor
$(GO) mod verify
diff --git a/VERSION b/VERSION
index 81c871d..1cac385 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.10.0
+1.11.0
diff --git a/debian/changelog b/debian/changelog
index c3089b9..5455be0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+golang-github-opencontainers-selinux (1.11.0+ds1-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 26 May 2023 11:34:47 -0000
+
golang-github-opencontainers-selinux (1.10.0+ds1-1) unstable; urgency=medium
* Team upload
diff --git a/go-selinux/doc.go b/go-selinux/doc.go
index 0ac7d81..57a15c9 100644
--- a/go-selinux/doc.go
+++ b/go-selinux/doc.go
@@ -9,6 +9,5 @@ Usage:
if selinux.EnforceMode() != selinux.Enforcing {
selinux.SetEnforceMode(selinux.Enforcing)
}
-
*/
package selinux
diff --git a/go-selinux/label/label.go b/go-selinux/label/label.go
index fea096c..07e0f77 100644
--- a/go-selinux/label/label.go
+++ b/go-selinux/label/label.go
@@ -78,6 +78,9 @@ func ReleaseLabel(label string) error {
// Deprecated: use selinux.DupSecOpt
var DupSecOpt = selinux.DupSecOpt
+// FormatMountLabel returns a string to be used by the mount command. Using
+// the SELinux `context` mount option. Changing labels of files on mount
+// points with this option can never be changed.
// FormatMountLabel returns a string to be used by the mount command.
// The format of this string will be used to alter the labeling of the mountpoint.
// The string returned is suitable to be used as the options field of the mount command.
@@ -85,12 +88,27 @@ var DupSecOpt = selinux.DupSecOpt
// the first parameter. Second parameter is the label that you wish to apply
// to all content in the mount point.
func FormatMountLabel(src, mountLabel string) string {
+ return FormatMountLabelByType(src, mountLabel, "context")
+}
+
+// FormatMountLabelByType returns a string to be used by the mount command.
+// Allow caller to specify the mount options. For example using the SELinux
+// `fscontext` mount option would allow certain container processes to change
+// labels of files created on the mount points, where as `context` option does
+// not.
+// FormatMountLabelByType returns a string to be used by the mount command.
+// The format of this string will be used to alter the labeling of the mountpoint.
+// The string returned is suitable to be used as the options field of the mount command.
+// If you need to have additional mount point options, you can pass them in as
+// the first parameter. Second parameter is the label that you wish to apply
+// to all content in the mount point.
+func FormatMountLabelByType(src, mountLabel, contextType string) string {
if mountLabel != "" {
switch src {
case "":
- src = fmt.Sprintf("context=%q", mountLabel)
+ src = fmt.Sprintf("%s=%q", contextType, mountLabel)
default:
- src = fmt.Sprintf("%s,context=%q", src, mountLabel)
+ src = fmt.Sprintf("%s,%s=%q", src, contextType, mountLabel)
}
}
return src
diff --git a/go-selinux/label/label_linux.go b/go-selinux/label/label_linux.go
index 12de0ae..f61a560 100644
--- a/go-selinux/label/label_linux.go
+++ b/go-selinux/label/label_linux.go
@@ -3,8 +3,6 @@ package label
import (
"errors"
"fmt"
- "os"
- "os/user"
"strings"
"github.com/opencontainers/selinux/go-selinux"
@@ -113,50 +111,6 @@ func Relabel(path string, fileLabel string, shared bool) error {
return nil
}
- exclude_paths := map[string]bool{
- "/": true,
- "/bin": true,
- "/boot": true,
- "/dev": true,
- "/etc": true,
- "/etc/passwd": true,
- "/etc/pki": true,
- "/etc/shadow": true,
- "/home": true,
- "/lib": true,
- "/lib64": true,
- "/media": true,
- "/opt": true,
- "/proc": true,
- "/root": true,
- "/run": true,
- "/sbin": true,
- "/srv": true,
- "/sys": true,
- "/tmp": true,
- "/usr": true,
- "/var": true,
- "/var/lib": true,
- "/var/log": true,
- }
-
- if home := os.Getenv("HOME"); home != "" {
- exclude_paths[home] = true
- }
-
- if sudoUser := os.Getenv("SUDO_USER"); sudoUser != "" {
- if usr, err := user.Lookup(sudoUser); err == nil {
- exclude_paths[usr.HomeDir] = true
- }
- }
-
- if path != "/" {
- path = strings.TrimSuffix(path, "/")
- }
- if exclude_paths[path] {
- return fmt.Errorf("SELinux relabeling of %s is not allowed", path)
- }
-
if shared {
c, err := selinux.NewContext(fileLabel)
if err != nil {
diff --git a/go-selinux/label/label_linux_test.go b/go-selinux/label/label_linux_test.go
index f36469d..0200810 100644
--- a/go-selinux/label/label_linux_test.go
+++ b/go-selinux/label/label_linux_test.go
@@ -2,7 +2,6 @@ package label
import (
"errors"
- "io/ioutil"
"os"
"strings"
"testing"
@@ -98,11 +97,7 @@ func TestDuplicateLabel(t *testing.T) {
func TestRelabel(t *testing.T) {
needSELinux(t)
- testdir, err := ioutil.TempDir("/tmp", "")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testdir)
+ testdir := t.TempDir()
label := "system_u:object_r:container_file_t:s0:c1,c2"
if err := Relabel(testdir, "", true); err != nil {
t.Fatalf("Relabel with no label failed: %v", err)
diff --git a/go-selinux/label/label_stub.go b/go-selinux/label/label_stub.go
index 02d2062..f21c80c 100644
--- a/go-selinux/label/label_stub.go
+++ b/go-selinux/label/label_stub.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package label
diff --git a/go-selinux/label/label_stub_test.go b/go-selinux/label/label_stub_test.go
index 08137dd..9742e6e 100644
--- a/go-selinux/label/label_stub_test.go
+++ b/go-selinux/label/label_stub_test.go
@@ -1,12 +1,9 @@
+//go:build !linux
// +build !linux
package label
-import (
- "io/ioutil"
- "os"
- "testing"
-)
+import "testing"
const testLabel = "system_u:object_r:container_file_t:s0:c1,c2"
@@ -42,13 +39,7 @@ func TestInit(t *testing.T) {
}
func TestRelabel(t *testing.T) {
- testdir, err := ioutil.TempDir("/tmp", "")
- if err != nil {
- t.Fatal(err)
- }
- defer os.RemoveAll(testdir)
- label := testLabel
- if err := Relabel("/etc", label, false); err != nil {
+ if err := Relabel("/etc", testLabel, false); err != nil {
t.Fatalf("Relabel /etc succeeded")
}
}
@@ -88,11 +79,12 @@ func TestCheckLabelCompile(t *testing.T) {
t.Fatal(err)
}
- if _, err := FileLabel("/etc"); err != nil {
+ tmpDir := t.TempDir()
+ if _, err := FileLabel(tmpDir); err != nil {
t.Fatal(err)
}
- if err := SetFileLabel("/etc", "foobar"); err != nil {
+ if err := SetFileLabel(tmpDir, "foobar"); err != nil {
t.Fatal(err)
}
diff --git a/go-selinux/label/label_test.go b/go-selinux/label/label_test.go
index ae5c048..fb172f3 100644
--- a/go-selinux/label/label_test.go
+++ b/go-selinux/label/label_test.go
@@ -17,4 +17,19 @@ func TestFormatMountLabel(t *testing.T) {
if test := FormatMountLabel("src", ""); test != expected {
t.Fatalf("Format failed. Expected %s, got %s", expected, test)
}
+
+ expected = `fscontext="foobar"`
+ if test := FormatMountLabelByType("", "foobar", "fscontext"); test != expected {
+ t.Fatalf("Format failed. Expected %s, got %s", expected, test)
+ }
+
+ expected = `src,fscontext="foobar"`
+ if test := FormatMountLabelByType("src", "foobar", "fscontext"); test != expected {
+ t.Fatalf("Format failed. Expected %s, got %s", expected, test)
+ }
+
+ expected = `src`
+ if test := FormatMountLabelByType("src", "", "rootcontext"); test != expected {
+ t.Fatalf("Format failed. Expected %s, got %s", expected, test)
+ }
}
diff --git a/go-selinux/rchcon.go b/go-selinux/rchcon.go
deleted file mode 100644
index 897ecba..0000000
--- a/go-selinux/rchcon.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// +build linux,go1.16
-
-package selinux
-
-import (
- "errors"
- "io/fs"
- "os"
-
- "github.com/opencontainers/selinux/pkg/pwalkdir"
-)
-
-func rchcon(fpath, label string) error {
- return pwalkdir.Walk(fpath, func(p string, _ fs.DirEntry, _ error) error {
- e := setFileLabel(p, label)
- // Walk a file tree can race with removal, so ignore ENOENT.
- if errors.Is(e, os.ErrNotExist) {
- return nil
- }
- return e
- })
-}
diff --git a/go-selinux/rchcon_go115.go b/go-selinux/rchcon_go115.go
deleted file mode 100644
index 2c8b033..0000000
--- a/go-selinux/rchcon_go115.go
+++ /dev/null
@@ -1,21 +0,0 @@
-// +build linux,!go1.16
-
-package selinux
-
-import (
- "errors"
- "os"
-
- "github.com/opencontainers/selinux/pkg/pwalk"
-)
-
-func rchcon(fpath, label string) error {
- return pwalk.Walk(fpath, func(p string, _ os.FileInfo, _ error) error {
- e := setFileLabel(p, label)
- // Walk a file tree can race with removal, so ignore ENOENT.
- if errors.Is(e, os.ErrNotExist) {
- return nil
- }
- return e
- })
-}
diff --git a/go-selinux/selinux.go b/go-selinux/selinux.go
index 5a59d15..af058b8 100644
--- a/go-selinux/selinux.go
+++ b/go-selinux/selinux.go
@@ -23,8 +23,13 @@ var (
// ErrEmptyPath is returned when an empty path has been specified.
ErrEmptyPath = errors.New("empty path")
+ // ErrInvalidLabel is returned when an invalid label is specified.
+ ErrInvalidLabel = errors.New("invalid Label")
+
// InvalidLabel is returned when an invalid label is specified.
- InvalidLabel = errors.New("Invalid Label")
+ //
+ // Deprecated: use [ErrInvalidLabel].
+ InvalidLabel = ErrInvalidLabel
// ErrIncomparable is returned two levels are not comparable
ErrIncomparable = errors.New("incomparable levels")
@@ -144,7 +149,7 @@ func CalculateGlbLub(sourceRange, targetRange string) (string, error) {
// of the program is finished to guarantee another goroutine does not migrate to the current
// thread before execution is complete.
func SetExecLabel(label string) error {
- return setExecLabel(label)
+ return writeCon(attrPath("exec"), label)
}
// SetTaskLabel sets the SELinux label for the current thread, or an error.
@@ -152,21 +157,21 @@ func SetExecLabel(label string) error {
// be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() to guarantee
// the current thread does not run in a new mislabeled thread.
func SetTaskLabel(label string) error {
- return setTaskLabel(label)
+ return writeCon(attrPath("current"), label)
}
// SetSocketLabel takes a process label and tells the kernel to assign the
// label to the next socket that gets created. Calls to SetSocketLabel
// should be wrapped in runtime.LockOSThread()/runtime.UnlockOSThread() until
-// the the socket is created to guarantee another goroutine does not migrate
+// the socket is created to guarantee another goroutine does not migrate
// to the current thread before execution is complete.
func SetSocketLabel(label string) error {
- return setSocketLabel(label)
+ return writeCon(attrPath("sockcreate"), label)
}
// SocketLabel retrieves the current socket label setting
func SocketLabel() (string, error) {
- return socketLabel()
+ return readCon(attrPath("sockcreate"))
}
// PeerLabel retrieves the label of the client on the other side of a socket
@@ -185,7 +190,7 @@ func SetKeyLabel(label string) error {
// KeyLabel retrieves the current kernel keyring label setting
func KeyLabel() (string, error) {
- return keyLabel()
+ return readCon("/proc/self/attr/keycreate")
}
// Get returns the Context as a string
@@ -208,6 +213,11 @@ func ReserveLabel(label string) {
reserveLabel(label)
}
+// MLSEnabled checks if MLS is enabled.
+func MLSEnabled() bool {
+ return isMLSEnabled()
+}
+
// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
return enforceMode()
@@ -220,7 +230,7 @@ func SetEnforceMode(mode int) error {
}
// DefaultEnforceMode returns the systems default SELinux mode Enforcing,
-// Permissive or Disabled. Note this is is just the default at boot time.
+// Permissive or Disabled. Note this is just the default at boot time.
// EnforceMode tells you the systems current mode.
func DefaultEnforceMode() int {
return defaultEnforceMode()
@@ -266,7 +276,7 @@ func CopyLevel(src, dest string) (string, error) {
return copyLevel(src, dest)
}
-// Chcon changes the fpath file object to the SELinux label label.
+// Chcon changes the fpath file object to the SELinux label.
// If fpath is a directory and recurse is true, then Chcon walks the
// directory tree setting the label.
//
@@ -284,7 +294,7 @@ func DupSecOpt(src string) ([]string, error) {
// DisableSecOpt returns a security opt that can be used to disable SELinux
// labeling support for future container processes.
func DisableSecOpt() []string {
- return disableSecOpt()
+ return []string{"disable"}
}
// GetDefaultContextWithLevel gets a single context for the specified SELinux user
diff --git a/go-selinux/selinux_linux.go b/go-selinux/selinux_linux.go
index ee602ab..f1e9597 100644
--- a/go-selinux/selinux_linux.go
+++ b/go-selinux/selinux_linux.go
@@ -8,15 +8,16 @@ import (
"errors"
"fmt"
"io"
- "io/ioutil"
+ "io/fs"
"math/big"
"os"
- "path"
+ "os/user"
"path/filepath"
"strconv"
"strings"
"sync"
+ "github.com/opencontainers/selinux/pkg/pwalkdir"
"golang.org/x/sys/unix"
)
@@ -34,17 +35,17 @@ const (
)
type selinuxState struct {
+ mcsList map[string]bool
+ selinuxfs string
+ selinuxfsOnce sync.Once
enabledSet bool
enabled bool
- selinuxfsOnce sync.Once
- selinuxfs string
- mcsList map[string]bool
sync.Mutex
}
type level struct {
- sens uint
cats *big.Int
+ sens uint
}
type mlsRange struct {
@@ -53,10 +54,10 @@ type mlsRange struct {
}
type defaultSECtx struct {
- user, level, scon string
- userRdr, defaultRdr io.Reader
-
- verifier func(string) error
+ userRdr io.Reader
+ verifier func(string) error
+ defaultRdr io.Reader
+ user, level, scon string
}
type levelItem byte
@@ -154,7 +155,7 @@ func findSELinuxfs() string {
}
// check if selinuxfs is available before going the slow path
- fs, err := ioutil.ReadFile("/proc/filesystems")
+ fs, err := os.ReadFile("/proc/filesystems")
if err != nil {
return ""
}
@@ -291,7 +292,7 @@ func readCon(fpath string) (string, error) {
}
func readConFd(in *os.File) (string, error) {
- data, err := ioutil.ReadAll(in)
+ data, err := io.ReadAll(in)
if err != nil {
return "", err
}
@@ -304,7 +305,7 @@ func classIndex(class string) (int, error) {
permpath := fmt.Sprintf("class/%s/index", class)
indexpath := filepath.Join(getSelinuxMountPoint(), permpath)
- indexB, err := ioutil.ReadFile(indexpath)
+ indexB, err := os.ReadFile(indexpath)
if err != nil {
return -1, err
}
@@ -390,21 +391,19 @@ func lFileLabel(fpath string) (string, error) {
return string(label), nil
}
-// setFSCreateLabel tells kernel the label to create all file system objects
-// created by this task. Setting label="" to return to default.
func setFSCreateLabel(label string) error {
- return writeAttr("fscreate", label)
+ return writeCon(attrPath("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 readAttr("fscreate")
+ return readCon(attrPath("fscreate"))
}
// currentLabel returns the SELinux label of the current process thread, or an error.
func currentLabel() (string, error) {
- return readAttr("current")
+ return readCon(attrPath("current"))
}
// pidLabel returns the SELinux label of the given pid, or an error.
@@ -415,7 +414,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 readAttr("exec")
+ return readCon(attrPath("exec"))
}
func writeCon(fpath, val string) error {
@@ -461,18 +460,10 @@ func attrPath(attr string) string {
})
if haveThreadSelf {
- return path.Join(threadSelfPrefix, attr)
+ return filepath.Join(threadSelfPrefix, attr)
}
- return path.Join("/proc/self/task/", strconv.Itoa(unix.Gettid()), "/attr/", attr)
-}
-
-func readAttr(attr string) (string, error) {
- return readCon(attrPath(attr))
-}
-
-func writeAttr(attr, val string) error {
- return writeCon(attrPath(attr), val)
+ return filepath.Join("/proc/self/task", strconv.Itoa(unix.Gettid()), "attr", attr)
}
// canonicalizeContext takes a context string and writes it to the kernel
@@ -559,30 +550,30 @@ func (l *level) parseLevel(levelStr string) error {
// rangeStrToMLSRange marshals a string representation of a range.
func rangeStrToMLSRange(rangeStr string) (*mlsRange, error) {
- mlsRange := &mlsRange{}
- levelSlice := strings.SplitN(rangeStr, "-", 2)
+ r := &mlsRange{}
+ l := strings.SplitN(rangeStr, "-", 2)
- switch len(levelSlice) {
+ switch len(l) {
// rangeStr that has a low and a high level, e.g. s4:c0.c1023-s6:c0.c1023
case 2:
- mlsRange.high = &level{}
- if err := mlsRange.high.parseLevel(levelSlice[1]); err != nil {
- return nil, fmt.Errorf("failed to parse high level %q: %w", levelSlice[1], err)
+ 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:
- mlsRange.low = &level{}
- if err := mlsRange.low.parseLevel(levelSlice[0]); err != nil {
- return nil, fmt.Errorf("failed to parse low level %q: %w", levelSlice[0], err)
+ 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)
}
}
- if mlsRange.high == nil {
- mlsRange.high = mlsRange.low
+ if r.high == nil {
+ r.high = r.low
}
- return mlsRange, nil
+ return r, nil
}
// bitsetToStr takes a category bitset and returns it in the
@@ -616,17 +607,17 @@ func bitsetToStr(c *big.Int) string {
return str
}
-func (l1 *level) equal(l2 *level) bool {
- if l2 == nil || l1 == nil {
- return l1 == l2
+func (l *level) equal(l2 *level) bool {
+ if l2 == nil || l == nil {
+ return l == l2
}
- if l1.sens != l2.sens {
+ if l2.sens != l.sens {
return false
}
- if l2.cats == nil || l1.cats == nil {
- return l2.cats == l1.cats
+ if l2.cats == nil || l.cats == nil {
+ return l2.cats == l.cats
}
- return l1.cats.Cmp(l2.cats) == 0
+ return l.cats.Cmp(l2.cats) == 0
}
// String returns an mlsRange as a string.
@@ -720,36 +711,13 @@ func readWriteCon(fpath string, val string) (string, error) {
return readConFd(f)
}
-// setExecLabel sets the SELinux label that the kernel will use for any programs
-// that are executed by the current process thread, or an error.
-func setExecLabel(label string) error {
- return writeAttr("exec", label)
-}
-
-// setTaskLabel sets the SELinux label for the current thread, or an error.
-// This requires the dyntransition permission.
-func setTaskLabel(label string) error {
- return writeAttr("current", label)
-}
-
-// setSocketLabel takes a process label and tells the kernel to assign the
-// label to the next socket that gets created
-func setSocketLabel(label string) error {
- return writeAttr("sockcreate", label)
-}
-
-// socketLabel retrieves the current socket label setting
-func socketLabel() (string, error) {
- return readAttr("sockcreate")
-}
-
// peerLabel retrieves the label of the client on the other side of a socket
func peerLabel(fd uintptr) (string, error) {
- label, err := unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
+ l, err := unix.GetsockoptString(int(fd), unix.SOL_SOCKET, unix.SO_PEERSEC)
if err != nil {
return "", &os.PathError{Op: "getsockopt", Path: "fd " + strconv.Itoa(int(fd)), Err: err}
}
- return label, nil
+ return l, nil
}
// setKeyLabel takes a process label and tells the kernel to assign the
@@ -765,15 +733,10 @@ func setKeyLabel(label string) error {
return err
}
-// keyLabel retrieves the current kernel keyring label setting
-func keyLabel() (string, error) {
- return readCon("/proc/self/attr/keycreate")
-}
-
// get returns the Context as a string
func (c Context) get() string {
- if level := c["level"]; level != "" {
- return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + level
+ if l := c["level"]; l != "" {
+ return c["user"] + ":" + c["role"] + ":" + c["type"] + ":" + l
}
return c["user"] + ":" + c["role"] + ":" + c["type"]
}
@@ -785,7 +748,7 @@ func newContext(label string) (Context, error) {
if len(label) != 0 {
con := strings.SplitN(label, ":", 4)
if len(con) < 3 {
- return c, InvalidLabel
+ return c, ErrInvalidLabel
}
c["user"] = con[0]
c["role"] = con[1]
@@ -815,14 +778,23 @@ func reserveLabel(label string) {
}
func selinuxEnforcePath() string {
- return path.Join(getSelinuxMountPoint(), "enforce")
+ return filepath.Join(getSelinuxMountPoint(), "enforce")
+}
+
+// isMLSEnabled checks if MLS is enabled.
+func isMLSEnabled() bool {
+ enabledB, err := os.ReadFile(filepath.Join(getSelinuxMountPoint(), "mls"))
+ if err != nil {
+ return false
+ }
+ return bytes.Equal(enabledB, []byte{'1'})
}
// enforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func enforceMode() int {
var enforce int
- enforceB, err := ioutil.ReadFile(selinuxEnforcePath())
+ enforceB, err := os.ReadFile(selinuxEnforcePath())
if err != nil {
return -1
}
@@ -836,11 +808,12 @@ func enforceMode() int {
// setEnforceMode sets the current SELinux mode Enforcing, Permissive.
// Disabled is not valid, since this needs to be set at boot time.
func setEnforceMode(mode int) error {
- return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0o644)
+ //nolint:gosec // ignore G306: permissions to be 0600 or less.
+ return os.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0o644)
}
// defaultEnforceMode returns the systems default SELinux mode Enforcing,
-// Permissive or Disabled. Note this is is just the default at boot time.
+// Permissive or Disabled. Note this is just the default at boot time.
// EnforceMode tells you the systems current mode.
func defaultEnforceMode() int {
switch readConfig(selinuxTag) {
@@ -940,7 +913,7 @@ func openContextFile() (*os.File, error) {
if f, err := os.Open(contextFile); err == nil {
return f, nil
}
- return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts"))
+ return os.Open(filepath.Join(policyRoot(), "contexts", "lxc_contexts"))
}
func loadLabels() {
@@ -1043,7 +1016,8 @@ func addMcs(processLabel, fileLabel string) (string, string) {
// securityCheckContext validates that the SELinux label is understood by the kernel
func securityCheckContext(val string) error {
- return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0o644)
+ //nolint:gosec // ignore G306: permissions to be 0600 or less.
+ return os.WriteFile(filepath.Join(getSelinuxMountPoint(), "context"), []byte(val), 0o644)
}
// copyLevel returns a label with the MLS/MCS level from src label replaced on
@@ -1072,22 +1046,7 @@ func copyLevel(src, dest string) (string, error) {
return tcon.Get(), nil
}
-// Prevent users from relabeling system files
-func badPrefix(fpath string) error {
- if fpath == "" {
- return ErrEmptyPath
- }
-
- badPrefixes := []string{"/usr"}
- for _, prefix := range badPrefixes {
- if strings.HasPrefix(fpath, prefix) {
- return fmt.Errorf("relabeling content in %s is not allowed", prefix)
- }
- }
- return nil
-}
-
-// chcon changes the fpath file object to the SELinux label label.
+// chcon changes the fpath file object to the SELinux label.
// If fpath is a directory and recurse is true, then chcon walks the
// directory tree setting the label.
func chcon(fpath string, label string, recurse bool) error {
@@ -1097,17 +1056,97 @@ func chcon(fpath string, label string, recurse bool) error {
if label == "" {
return nil
}
- if err := badPrefix(fpath); err != nil {
- return err
+
+ excludePaths := map[string]bool{
+ "/": true,
+ "/bin": true,
+ "/boot": true,
+ "/dev": true,
+ "/etc": true,
+ "/etc/passwd": true,
+ "/etc/pki": true,
+ "/etc/shadow": true,
+ "/home": true,
+ "/lib": true,
+ "/lib64": true,
+ "/media": true,
+ "/opt": true,
+ "/proc": true,
+ "/root": true,
+ "/run": true,
+ "/sbin": true,
+ "/srv": true,
+ "/sys": true,
+ "/tmp": true,
+ "/usr": true,
+ "/var": true,
+ "/var/lib": true,
+ "/var/log": true,
+ }
+
+ if home := os.Getenv("HOME"); home != "" {
+ excludePaths[home] = true
+ }
+
+ if sudoUser := os.Getenv("SUDO_USER"); sudoUser != "" {
+ if usr, err := user.Lookup(sudoUser); err == nil {
+ excludePaths[usr.HomeDir] = true
+ }
+ }
+
+ if fpath != "/" {
+ fpath = strings.TrimSuffix(fpath, "/")
+ }
+ if excludePaths[fpath] {
+ return fmt.Errorf("SELinux relabeling of %s is not allowed", fpath)
}
if !recurse {
- return setFileLabel(fpath, label)
+ err := lSetFileLabel(fpath, label)
+ if err != nil {
+ // Check if file doesn't exist, must have been removed
+ if errors.Is(err, os.ErrNotExist) {
+ return nil
+ }
+ // Check if current label is correct on disk
+ flabel, nerr := lFileLabel(fpath)
+ if nerr == nil && flabel == label {
+ return nil
+ }
+ // Check if file doesn't exist, must have been removed
+ if errors.Is(nerr, os.ErrNotExist) {
+ return nil
+ }
+ return err
+ }
+ return nil
}
return rchcon(fpath, label)
}
+func rchcon(fpath, label string) error { //revive:disable:cognitive-complexity
+ fastMode := false
+ // If the current label matches the new label, assume
+ // other labels are correct.
+ if cLabel, err := lFileLabel(fpath); err == nil && cLabel == label {
+ fastMode = true
+ }
+ return pwalkdir.Walk(fpath, func(p string, _ fs.DirEntry, _ error) error {
+ if fastMode {
+ if cLabel, err := lFileLabel(fpath); err == nil && cLabel == label {
+ return nil
+ }
+ }
+ err := lSetFileLabel(p, label)
+ // Walk a file tree can race with removal, so ignore ENOENT.
+ if errors.Is(err, os.ErrNotExist) {
+ return nil
+ }
+ return err
+ })
+}
+
// dupSecOpt takes an SELinux process label and returns security options that
// can be used to set the SELinux Type and Level for future container processes.
func dupSecOpt(src string) ([]string, error) {
@@ -1136,12 +1175,6 @@ func dupSecOpt(src string) ([]string, error) {
return dup, nil
}
-// disableSecOpt returns a security opt that can be used to disable SELinux
-// labeling support for future container processes.
-func disableSecOpt() []string {
- return []string{"disable"}
-}
-
// 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
diff --git a/go-selinux/selinux_linux_test.go b/go-selinux/selinux_linux_test.go
index 7dc1fe6..c49e2bf 100644
--- a/go-selinux/selinux_linux_test.go
+++ b/go-selinux/selinux_linux_test.go
@@ -16,25 +16,66 @@ func TestSetFileLabel(t *testing.T) {
t.Skip("SELinux not enabled, skipping.")
}
- tmp := "selinux_test"
- con := "system_u:object_r:bin_t:s0"
- out, err := os.OpenFile(tmp, os.O_WRONLY|os.O_CREATE, 0)
+ const (
+ tmpFile = "selinux_test"
+ tmpLink = "selinux_test_link"
+ con = "system_u:object_r:bin_t:s0:c1,c2"
+ con2 = "system_u:object_r:bin_t:s0:c3,c4"
+ )
+
+ _ = os.Remove(tmpFile)
+ out, err := os.OpenFile(tmpFile, os.O_WRONLY|os.O_CREATE, 0)
if err != nil {
- t.Fatalf("unable to open %s: %s", tmp, err)
+ t.Fatal(err)
}
out.Close()
- defer os.Remove(tmp)
+ defer os.Remove(tmpFile)
+
+ _ = os.Remove(tmpLink)
+ if err := os.Symlink(tmpFile, tmpLink); err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpLink)
- if err := SetFileLabel(tmp, con); err != nil {
+ if err := SetFileLabel(tmpLink, con); err != nil {
t.Fatalf("SetFileLabel failed: %s", err)
}
- filelabel, err := FileLabel(tmp)
+ filelabel, err := FileLabel(tmpLink)
if err != nil {
t.Fatalf("FileLabel failed: %s", err)
}
- if con != filelabel {
+ if filelabel != con {
t.Fatalf("FileLabel failed, returned %s expected %s", filelabel, con)
}
+
+ // Using LfileLabel to verify that the symlink itself is not labeled.
+ linkLabel, err := LfileLabel(tmpLink)
+ if err != nil {
+ t.Fatalf("LfileLabel failed: %s", err)
+ }
+ if linkLabel == con {
+ t.Fatalf("Label on symlink should not be set, got: %q", linkLabel)
+ }
+
+ // Use LsetFileLabel to set a label on the symlink itself.
+ if err := LsetFileLabel(tmpLink, con2); err != nil {
+ t.Fatalf("LsetFileLabel failed: %s", err)
+ }
+ filelabel, err = FileLabel(tmpFile)
+ if err != nil {
+ t.Fatalf("FileLabel failed: %s", err)
+ }
+ if filelabel != con {
+ t.Fatalf("FileLabel was updated, returned %s expected %s", filelabel, con)
+ }
+
+ linkLabel, err = LfileLabel(tmpLink)
+ if err != nil {
+ t.Fatalf("LfileLabel failed: %s", err)
+ }
+ if linkLabel != con2 {
+ t.Fatalf("LfileLabel failed: returned %s expected %s", linkLabel, con2)
+ }
}
func TestKVMLabels(t *testing.T) {
@@ -186,6 +227,7 @@ func TestCanonicalizeContext(t *testing.T) {
}
func TestFindSELinuxfsInMountinfo(t *testing.T) {
+ //nolint:dupword // ignore duplicate words (sysfs sysfs)
const mountinfo = `18 62 0:17 / /sys rw,nosuid,nodev,noexec,relatime shared:6 - sysfs sysfs rw,seclabel
19 62 0:3 / /proc rw,nosuid,nodev,noexec,relatime shared:5 - proc proc rw
20 62 0:5 / /dev rw,nosuid shared:2 - devtmpfs devtmpfs rw,seclabel,size=3995472k,nr_inodes=998868,mode=755
@@ -307,10 +349,10 @@ func TestComputeCreateContext(t *testing.T) {
func TestGlbLub(t *testing.T) {
tests := []struct {
+ expectedErr error
sourceRange string
targetRange string
expectedRange string
- expectedErr error
}{
{
sourceRange: "s0:c0.c100-s10:c0.c150",
diff --git a/go-selinux/selinux_stub.go b/go-selinux/selinux_stub.go
index 78743b0..bc3fd3b 100644
--- a/go-selinux/selinux_stub.go
+++ b/go-selinux/selinux_stub.go
@@ -1,10 +1,22 @@
+//go:build !linux
// +build !linux
package selinux
-func setDisabled() {
+func attrPath(string) string {
+ return ""
+}
+
+func readCon(fpath string) (string, error) {
+ return "", nil
+}
+
+func writeCon(string, string) error {
+ return nil
}
+func setDisabled() {}
+
func getEnabled() bool {
return false
}
@@ -61,22 +73,6 @@ func calculateGlbLub(sourceRange, targetRange string) (string, error) {
return "", nil
}
-func setExecLabel(label string) error {
- return nil
-}
-
-func setTaskLabel(label string) error {
- return nil
-}
-
-func setSocketLabel(label string) error {
- return nil
-}
-
-func socketLabel() (string, error) {
- return "", nil
-}
-
func peerLabel(fd uintptr) (string, error) {
return "", nil
}
@@ -85,17 +81,12 @@ func setKeyLabel(label string) error {
return nil
}
-func keyLabel() (string, error) {
- return "", nil
-}
-
func (c Context) get() string {
return ""
}
func newContext(label string) (Context, error) {
- c := make(Context)
- return c, nil
+ return Context{}, nil
}
func clearLabels() {
@@ -104,6 +95,10 @@ func clearLabels() {
func reserveLabel(label string) {
}
+func isMLSEnabled() bool {
+ return false
+}
+
func enforceMode() int {
return Disabled
}
@@ -151,10 +146,6 @@ func dupSecOpt(src string) ([]string, error) {
return nil, nil
}
-func disableSecOpt() []string {
- return []string{"disable"}
-}
-
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
return "", nil
}
diff --git a/go-selinux/selinux_stub_test.go b/go-selinux/selinux_stub_test.go
index 20b5b21..19ea636 100644
--- a/go-selinux/selinux_stub_test.go
+++ b/go-selinux/selinux_stub_test.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package selinux
@@ -6,93 +7,121 @@ import (
"testing"
)
-func TestSELinux(t *testing.T) {
+const testLabel = "foobar"
+
+func TestSELinuxStubs(t *testing.T) {
if GetEnabled() {
- t.Fatal("SELinux enabled on non-linux.")
+ t.Error("SELinux enabled on non-linux.")
+ }
+
+ tmpDir := t.TempDir()
+ if _, err := FileLabel(tmpDir); err != nil {
+ t.Error(err)
}
- if _, err := FileLabel("/etc"); err != nil {
- t.Fatal(err)
+ if err := SetFileLabel(tmpDir, testLabel); err != nil {
+ t.Error(err)
}
- if err := SetFileLabel("/etc", "foobar"); err != nil {
- t.Fatal(err)
+ if _, err := LfileLabel(tmpDir); err != nil {
+ t.Error(err)
+ }
+ if err := LsetFileLabel(tmpDir, testLabel); err != nil {
+ t.Error(err)
}
- if err := SetFSCreateLabel("foobar"); err != nil {
- t.Fatal(err)
+ if err := SetFSCreateLabel(testLabel); err != nil {
+ t.Error(err)
}
if _, err := FSCreateLabel(); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
if _, err := CurrentLabel(); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
if _, err := PidLabel(0); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
ClearLabels()
- ReserveLabel("foobar")
- ReleaseLabel("foobar")
- _, _ = DupSecOpt("foobar")
- DisableSecOpt()
+ ReserveLabel(testLabel)
+ ReleaseLabel(testLabel)
+ if _, err := DupSecOpt(testLabel); err != nil {
+ t.Error(err)
+ }
+ if v := DisableSecOpt(); len(v) != 1 || v[0] != "disable" {
+ t.Errorf(`expected "disabled", got %v`, v)
+ }
SetDisabled()
if enabled := GetEnabled(); enabled {
- t.Fatal("Should not be enabled")
+ t.Error("Should not be enabled")
}
- if err := SetExecLabel("foobar"); err != nil {
- t.Fatal(err)
+ if err := SetExecLabel(testLabel); err != nil {
+ t.Error(err)
}
- if err := SetTaskLabel("foobar"); err != nil {
- t.Fatal(err)
+ if err := SetTaskLabel(testLabel); err != nil {
+ t.Error(err)
}
if _, err := ExecLabel(); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
- if _, err := CanonicalizeContext("foobar"); err != nil {
- t.Fatal(err)
+ if _, err := CanonicalizeContext(testLabel); err != nil {
+ t.Error(err)
}
- if _, err := ComputeCreateContext("foo", "bar", "foobar"); err != nil {
- t.Fatal(err)
+ if _, err := ComputeCreateContext("foo", "bar", testLabel); err != nil {
+ t.Error(err)
}
- if err := SetSocketLabel("foobar"); err != nil {
- t.Fatal(err)
+ if err := SetSocketLabel(testLabel); err != nil {
+ t.Error(err)
}
- if _, err := ClassIndex("foobar"); err != nil {
- t.Fatal(err)
+ if _, err := ClassIndex(testLabel); err != nil {
+ t.Error(err)
}
if _, err := SocketLabel(); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
if _, err := PeerLabel(0); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
- if err := SetKeyLabel("foobar"); err != nil {
- t.Fatal(err)
+ if err := SetKeyLabel(testLabel); err != nil {
+ t.Error(err)
}
if _, err := KeyLabel(); err != nil {
- t.Fatal(err)
+ t.Error(err)
}
- con, err := NewContext("foobar")
+ if err := SetExecLabel(testLabel); err != nil {
+ t.Error(err)
+ }
+ if _, err := ExecLabel(); err != nil {
+ t.Error(err)
+ }
+ con, err := NewContext(testLabel)
if err != nil {
- t.Fatal(err)
+ t.Error(err)
}
con.Get()
- if err := SetEnforceMode(1); err != nil {
- t.Fatal(err)
- }
- DefaultEnforceMode()
- EnforceMode()
- ROFileLabel()
- ContainerLabels()
- if err := SecurityCheckContext("foobar"); err != nil {
- t.Fatal(err)
- }
- if _, err := CopyLevel("foo", "bar"); err != nil {
- t.Fatal(err)
+ if err = SetEnforceMode(1); err != nil {
+ t.Error(err)
+ }
+ if v := DefaultEnforceMode(); v != Disabled {
+ t.Errorf("expected %d, got %d", Disabled, v)
+ }
+ if v := EnforceMode(); v != Disabled {
+ t.Errorf("expected %d, got %d", Disabled, v)
+ }
+ if v := ROFileLabel(); v != "" {
+ t.Errorf(`expected "", got %q`, v)
+ }
+ if processLbl, fileLbl := ContainerLabels(); processLbl != "" || fileLbl != "" {
+ t.Errorf(`expected fileLbl="", fileLbl="" got processLbl=%q, fileLbl=%q`, processLbl, fileLbl)
+ }
+ if err = SecurityCheckContext(testLabel); err != nil {
+ t.Error(err)
+ }
+ if _, err = CopyLevel("foo", "bar"); err != nil {
+ t.Error(err)
}
}
diff --git a/go.mod b/go.mod
index 93ee78e..56328f1 100644
--- a/go.mod
+++ b/go.mod
@@ -1,5 +1,5 @@
module github.com/opencontainers/selinux
-go 1.13
+go 1.19
-require golang.org/x/sys v0.0.0-20191115151921-52ab43148777
+require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8
diff --git a/go.sum b/go.sum
index 9a749d7..28ab7f7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,2 +1,2 @@
-golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4=
-golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/pkg/pwalk/pwalk.go b/pkg/pwalk/pwalk.go
index 202c80d..a28b4c4 100644
--- a/pkg/pwalk/pwalk.go
+++ b/pkg/pwalk/pwalk.go
@@ -8,6 +8,10 @@ import (
"sync"
)
+// WalkFunc is the type of the function called by Walk to visit each
+// file or directory. It is an alias for [filepath.WalkFunc].
+//
+// Deprecated: use [github.com/opencontainers/selinux/pkg/pwalkdir] and [fs.WalkDirFunc].
type WalkFunc = filepath.WalkFunc
// Walk is a wrapper for filepath.Walk which can call multiple walkFn
@@ -29,6 +33,8 @@ type WalkFunc = filepath.WalkFunc
// - 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.
+//
+// Deprecated: use [github.com/opencontainers/selinux/pkg/pwalkdir.Walk]
func Walk(root string, walkFn WalkFunc) error {
return WalkN(root, walkFn, runtime.NumCPU()*2)
}
@@ -38,6 +44,8 @@ func Walk(root string, walkFn WalkFunc) error {
// num walkFn will be called at any one time.
//
// Please see Walk documentation for caveats of using this function.
+//
+// Deprecated: use [github.com/opencontainers/selinux/pkg/pwalkdir.WalkN]
func WalkN(root string, walkFn WalkFunc, num int) error {
// make sure limit is sensible
if num < 1 {
@@ -110,6 +118,6 @@ func WalkN(root string, walkFn WalkFunc, num int) error {
// walkArgs holds the arguments that were passed to the Walk or WalkN
// functions.
type walkArgs struct {
- path string
info *os.FileInfo
+ path string
}
diff --git a/pkg/pwalk/pwalk_test.go b/pkg/pwalk/pwalk_test.go
index 374df73..bf50613 100644
--- a/pkg/pwalk/pwalk_test.go
+++ b/pkg/pwalk/pwalk_test.go
@@ -2,7 +2,6 @@ package pwalk
import (
"errors"
- "io/ioutil"
"math/rand"
"os"
"path/filepath"
@@ -70,17 +69,18 @@ func TestWalkManyErrors(t *testing.T) {
func makeManyDirs(prefix string, levels, dirs, files int) (count int, err error) {
for d := 0; d < dirs; d++ {
var dir string
- dir, err = ioutil.TempDir(prefix, "d-")
+ dir, err = os.MkdirTemp(prefix, "d-")
if err != nil {
return
}
count++
for f := 0; f < files; f++ {
- fi, err := ioutil.TempFile(dir, "f-")
+ var fi *os.File
+ fi, err = os.CreateTemp(dir, "f-")
if err != nil {
return count, err
}
- fi.Close()
+ _ = fi.Close()
count++
}
if levels == 0 {
@@ -102,7 +102,7 @@ func makeManyDirs(prefix string, levels, dirs, files int) (count int, err error)
// Total dirs: dirs^levels + dirs^(levels-1) + ... + dirs^1
// Total files: total_dirs * files
func prepareTestSet(levels, dirs, files int) (dir string, total int, err error) {
- dir, err = ioutil.TempDir(".", "pwalk-test-")
+ dir, err = os.MkdirTemp(".", "pwalk-test-")
if err != nil {
return
}
@@ -134,31 +134,31 @@ func BenchmarkWalk(b *testing.B) {
)
benchmarks := []struct {
- name string
walk filepath.WalkFunc
+ name string
}{
- {"Empty", cbEmpty},
- {"ReadFile", cbReadFile},
- {"ChownChmod", cbChownChmod},
- {"RandomSleep", cbRandomSleep},
+ {name: "Empty", walk: cbEmpty},
+ {name: "ReadFile", walk: cbReadFile},
+ {name: "ChownChmod", walk: cbChownChmod},
+ {name: "RandomSleep", walk: cbRandomSleep},
}
walkers := []struct {
- name string
walker walkerFunc
+ name string
}{
- {"filepath.Walk", filepath.Walk},
- {"pwalk.Walk", Walk},
+ {name: "filepath.Walk", walker: filepath.Walk},
+ {name: "pwalk.Walk", walker: Walk},
// test WalkN with various values of N
- {"pwalk.Walk1", genWalkN(1)},
- {"pwalk.Walk2", genWalkN(2)},
- {"pwalk.Walk4", genWalkN(4)},
- {"pwalk.Walk8", genWalkN(8)},
- {"pwalk.Walk16", genWalkN(16)},
- {"pwalk.Walk32", genWalkN(32)},
- {"pwalk.Walk64", genWalkN(64)},
- {"pwalk.Walk128", genWalkN(128)},
- {"pwalk.Walk256", genWalkN(256)},
+ {name: "pwalk.Walk1", walker: genWalkN(1)},
+ {name: "pwalk.Walk2", walker: genWalkN(2)},
+ {name: "pwalk.Walk4", walker: genWalkN(4)},
+ {name: "pwalk.Walk8", walker: genWalkN(8)},
+ {name: "pwalk.Walk16", walker: genWalkN(16)},
+ {name: "pwalk.Walk32", walker: genWalkN(32)},
+ {name: "pwalk.Walk64", walker: genWalkN(64)},
+ {name: "pwalk.Walk128", walker: genWalkN(128)},
+ {name: "pwalk.Walk256", walker: genWalkN(256)},
}
dir, total, err := prepareTestSet(levels, dirs, files)
@@ -173,15 +173,13 @@ func BenchmarkWalk(b *testing.B) {
walker := w.walker
walkFn := bm.walk
// preheat
- err := w.walker(dir, bm.walk)
- if err != nil {
+ if err := w.walker(dir, bm.walk); err != nil {
b.Errorf("walk failed: %v", err)
}
// benchmark
b.Run(bm.name+"/"+w.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
- err := walker(dir, walkFn)
- if err != nil {
+ if err := walker(dir, walkFn); err != nil {
b.Errorf("walk failed: %v", err)
}
}
@@ -208,12 +206,12 @@ func cbChownChmod(path string, info os.FileInfo, _ error) error {
func cbReadFile(path string, info os.FileInfo, _ error) error {
var err error
if info.Mode().IsRegular() {
- _, err = ioutil.ReadFile(path)
+ _, err = os.ReadFile(path)
}
return err
}
func cbRandomSleep(_ string, _ os.FileInfo, _ error) error {
- time.Sleep(time.Duration(rand.Intn(500)) * time.Microsecond)
+ time.Sleep(time.Duration(rand.Intn(500)) * time.Microsecond) //nolint:gosec // ignore G404: Use of weak random number generator
return nil
}
diff --git a/pkg/pwalkdir/pwalkdir.go b/pkg/pwalkdir/pwalkdir.go
index a5796b2..0f5d9f5 100644
--- a/pkg/pwalkdir/pwalkdir.go
+++ b/pkg/pwalkdir/pwalkdir.go
@@ -111,6 +111,6 @@ func WalkN(root string, walkFn fs.WalkDirFunc, num int) error {
// walkArgs holds the arguments that were passed to the Walk or WalkN
// functions.
type walkArgs struct {
- path string
entry fs.DirEntry
+ path string
}
diff --git a/pkg/pwalkdir/pwalkdir_test.go b/pkg/pwalkdir/pwalkdir_test.go
index 9204179..c173001 100644
--- a/pkg/pwalkdir/pwalkdir_test.go
+++ b/pkg/pwalkdir/pwalkdir_test.go
@@ -6,7 +6,6 @@ package pwalkdir
import (
"errors"
"io/fs"
- "io/ioutil"
"math/rand"
"os"
"path/filepath"
@@ -74,13 +73,14 @@ func TestWalkDirManyErrors(t *testing.T) {
func makeManyDirs(prefix string, levels, dirs, files int) (count int, err error) {
for d := 0; d < dirs; d++ {
var dir string
- dir, err = ioutil.TempDir(prefix, "d-")
+ dir, err = os.MkdirTemp(prefix, "d-")
if err != nil {
return
}
count++
for f := 0; f < files; f++ {
- fi, err := ioutil.TempFile(dir, "f-")
+ var fi *os.File
+ fi, err = os.CreateTemp(dir, "f-")
if err != nil {
return count, err
}
@@ -106,7 +106,7 @@ func makeManyDirs(prefix string, levels, dirs, files int) (count int, err error)
// Total dirs: dirs^levels + dirs^(levels-1) + ... + dirs^1
// Total files: total_dirs * files
func prepareTestSet(levels, dirs, files int) (dir string, total int, err error) {
- dir, err = ioutil.TempDir(".", "pwalk-test-")
+ dir, err = os.MkdirTemp(".", "pwalk-test-")
if err != nil {
return
}
@@ -138,31 +138,31 @@ func BenchmarkWalk(b *testing.B) {
)
benchmarks := []struct {
- name string
walk fs.WalkDirFunc
+ name string
}{
- {"Empty", cbEmpty},
- {"ReadFile", cbReadFile},
- {"ChownChmod", cbChownChmod},
- {"RandomSleep", cbRandomSleep},
+ {name: "Empty", walk: cbEmpty},
+ {name: "ReadFile", walk: cbReadFile},
+ {name: "ChownChmod", walk: cbChownChmod},
+ {name: "RandomSleep", walk: cbRandomSleep},
}
walkers := []struct {
- name string
walker walkerFunc
+ name string
}{
- {"filepath.WalkDir", filepath.WalkDir},
- {"pwalkdir.Walk", Walk},
+ {name: "filepath.WalkDir", walker: filepath.WalkDir},
+ {name: "pwalkdir.Walk", walker: Walk},
// test WalkN with various values of N
- {"pwalkdir.Walk1", genWalkN(1)},
- {"pwalkdir.Walk2", genWalkN(2)},
- {"pwalkdir.Walk4", genWalkN(4)},
- {"pwalkdir.Walk8", genWalkN(8)},
- {"pwalkdir.Walk16", genWalkN(16)},
- {"pwalkdir.Walk32", genWalkN(32)},
- {"pwalkdir.Walk64", genWalkN(64)},
- {"pwalkdir.Walk128", genWalkN(128)},
- {"pwalkdir.Walk256", genWalkN(256)},
+ {name: "pwalkdir.Walk1", walker: genWalkN(1)},
+ {name: "pwalkdir.Walk2", walker: genWalkN(2)},
+ {name: "pwalkdir.Walk4", walker: genWalkN(4)},
+ {name: "pwalkdir.Walk8", walker: genWalkN(8)},
+ {name: "pwalkdir.Walk16", walker: genWalkN(16)},
+ {name: "pwalkdir.Walk32", walker: genWalkN(32)},
+ {name: "pwalkdir.Walk64", walker: genWalkN(64)},
+ {name: "pwalkdir.Walk128", walker: genWalkN(128)},
+ {name: "pwalkdir.Walk256", walker: genWalkN(256)},
}
dir, total, err := prepareTestSet(levels, dirs, files)
@@ -177,15 +177,13 @@ func BenchmarkWalk(b *testing.B) {
walker := w.walker
walkFn := bm.walk
// preheat
- err := w.walker(dir, bm.walk)
- if err != nil {
+ if err := w.walker(dir, bm.walk); err != nil {
b.Errorf("walk failed: %v", err)
}
// benchmark
b.Run(bm.name+"/"+w.name, func(b *testing.B) {
for i := 0; i < b.N; i++ {
- err := walker(dir, walkFn)
- if err != nil {
+ if err := walker(dir, walkFn); err != nil {
b.Errorf("walk failed: %v", err)
}
}
@@ -212,12 +210,12 @@ func cbChownChmod(path string, e fs.DirEntry, _ error) error {
func cbReadFile(path string, e fs.DirEntry, _ error) error {
var err error
if e.Type().IsRegular() {
- _, err = ioutil.ReadFile(path)
+ _, err = os.ReadFile(path)
}
return err
}
func cbRandomSleep(_ string, _ fs.DirEntry, _ error) error {
- time.Sleep(time.Duration(rand.Intn(500)) * time.Microsecond)
+ time.Sleep(time.Duration(rand.Intn(500)) * time.Microsecond) //nolint:gosec // ignore G404: Use of weak random number generator
return nil
}
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/gocode/src/github.com/opencontainers/selinux/go-selinux/rchcon.go -rw-r--r-- root/root /usr/share/gocode/src/github.com/opencontainers/selinux/go-selinux/rchcon_go115.go
No differences were encountered in the control files