Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 20 additions & 17 deletions go-selinux/selinux_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"io"
"io/ioutil"
"os"
"path"
"path/filepath"
"regexp"
"strconv"
Expand All @@ -37,7 +38,6 @@ const (
selinuxTag = "SELINUX"
xattrNameSelinux = "security.selinux"
stRdOnly = 0x01
selinuxfsMagic = 0xf97cff8c
)

type selinuxState struct {
Expand Down Expand Up @@ -118,7 +118,8 @@ func verifySELinuxfsMount(mnt string) bool {
}
return false
}
if uint32(buf.Type) != uint32(selinuxfsMagic) {

if buf.Type != unix.SELINUX_MAGIC {
return false
}
if (buf.Flags & stRdOnly) != 0 {
Expand Down Expand Up @@ -254,10 +255,17 @@ func getSELinuxPolicyRoot() string {
return filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
}

func isProcHandle(fh *os.File) (bool, error) {
func isProcHandle(fh *os.File) error {
var buf unix.Statfs_t
err := unix.Fstatfs(int(fh.Fd()), &buf)
return buf.Type == unix.PROC_SUPER_MAGIC, err
if err != nil {
return fmt.Errorf("statfs(%q) failed: %v", fh.Name(), err)
}
if buf.Type != unix.PROC_SUPER_MAGIC {
return fmt.Errorf("file %q is not on procfs", fh.Name())
}

return nil
}

func readCon(fpath string) (string, error) {
Expand All @@ -271,10 +279,8 @@ func readCon(fpath string) (string, error) {
}
defer in.Close()

if ok, err := isProcHandle(in); err != nil {
if err := isProcHandle(in); err != nil {
return "", err
} else if !ok {
return "", fmt.Errorf("%s not on procfs", fpath)
}

var retval string
Expand Down Expand Up @@ -346,7 +352,7 @@ func ExecLabel() (string, error) {
return readCon(fmt.Sprintf("/proc/self/task/%d/attr/exec", syscall.Gettid()))
}

func writeCon(fpath string, val string) error {
func writeCon(fpath, val string) error {
if fpath == "" {
return ErrEmptyPath
}
Expand All @@ -362,10 +368,8 @@ func writeCon(fpath string, val string) error {
}
defer out.Close()

if ok, err := isProcHandle(out); err != nil {
if err := isProcHandle(out); err != nil {
return err
} else if !ok {
return fmt.Errorf("%s not on procfs", fpath)
}

if val != "" {
Expand Down Expand Up @@ -505,19 +509,18 @@ func ReserveLabel(label string) {
}

func selinuxEnforcePath() string {
return fmt.Sprintf("%s/enforce", getSelinuxMountPoint())
return path.Join(getSelinuxMountPoint(), "enforce")
}

// EnforceMode returns the current SELinux mode Enforcing, Permissive, Disabled
func EnforceMode() int {
var enforce int

enforceS, err := readCon(selinuxEnforcePath())
enforceB, err := ioutil.ReadFile(selinuxEnforcePath())
if err != nil {
return -1
}

enforce, err = strconv.Atoi(string(enforceS))
enforce, err = strconv.Atoi(string(enforceB))
if err != nil {
return -1
}
Expand All @@ -529,7 +532,7 @@ SetEnforceMode sets the current SELinux mode Enforcing, Permissive.
Disabled is not valid, since this needs to be set at boot time.
*/
func SetEnforceMode(mode int) error {
return writeCon(selinuxEnforcePath(), fmt.Sprintf("%d", mode))
return ioutil.WriteFile(selinuxEnforcePath(), []byte(strconv.Itoa(mode)), 0644)
}

/*
Expand Down Expand Up @@ -711,7 +714,7 @@ exit:

// SecurityCheckContext validates that the SELinux label is understood by the kernel
func SecurityCheckContext(val string) error {
return writeCon(fmt.Sprintf("%s/context", getSelinuxMountPoint()), val)
return ioutil.WriteFile(path.Join(getSelinuxMountPoint(), "context"), []byte(val), 0644)
}

/*
Expand Down
58 changes: 46 additions & 12 deletions go-selinux/selinux_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,6 @@ func TestSELinux(t *testing.T) {
t.Log(plabel)
t.Log(flabel)
ReleaseLabel(plabel)
t.Log("Enforcing Mode", EnforceMode())
mode := DefaultEnforceMode()
t.Log("Default Enforce Mode ", mode)

plabel, flabel = ContainerLabels()
t.Log(plabel)
Expand All @@ -67,15 +64,6 @@ func TestSELinux(t *testing.T) {
t.Log(flabel)
ReleaseLabel(plabel)

defer SetEnforceMode(mode)
if err := SetEnforceMode(Enforcing); err != nil {
t.Fatalf("enforcing selinux failed: %v", err)
}
if err := SetEnforceMode(Permissive); err != nil {
t.Fatalf("setting selinux mode to permissive failed: %v", err)
}
SetEnforceMode(mode)

pid := os.Getpid()
t.Logf("PID:%d MCS:%s\n", pid, intToMcs(pid, 1023))
err = SetFSCreateLabel("unconfined_u:unconfined_r:unconfined_t:s0")
Expand All @@ -95,6 +83,27 @@ func TestSELinux(t *testing.T) {
t.Log(PidLabel(1))
}

func TestSetEnforceMode(t *testing.T) {
if !GetEnabled() {
t.Skip("SELinux not enabled, skipping.")
}
if os.Geteuid() != 0 {
t.Skip("root required, skipping")
}

t.Log("Enforcing Mode:", EnforceMode())
mode := DefaultEnforceMode()
t.Log("Default Enforce Mode:", mode)
defer SetEnforceMode(mode)

if err := SetEnforceMode(Enforcing); err != nil {
t.Fatalf("setting selinux mode to enforcing failed: %v", err)
}
if err := SetEnforceMode(Permissive); err != nil {
t.Fatalf("setting selinux mode to permissive failed: %v", err)
}
}

func TestCanonicalizeContext(t *testing.T) {
if !GetEnabled() {
t.Skip("SELinux not enabled, skipping.")
Expand Down Expand Up @@ -166,3 +175,28 @@ func TestFindSELinuxfsInMountinfo(t *testing.T) {
}
}
}

func TestSecurityCheckContext(t *testing.T) {
if !GetEnabled() {
t.Skip("SELinux not enabled, skipping.")
}

// check with valid context
context, err := CurrentLabel()
if err != nil {
t.Fatalf("CurrentLabel() error: %v", err)
}
if context != "" {
t.Logf("SecurityCheckContext(%q)", context)
err = SecurityCheckContext(context)
if err != nil {
t.Errorf("SecurityCheckContext(%q) error: %v", context, err)
}
}

context = "not-syntactically-valid"
err = SecurityCheckContext(context)
if err == nil {
t.Errorf("SecurityCheckContext(%q) succeeded, expected to fail", context)
}
}