Skip to content

Commit

Permalink
Merge pull request #64 from kolyshkin/fs-fix
Browse files Browse the repository at this point in the history
Fix EnforceMode, SetEnforceMode, and SecurityCheckContext
  • Loading branch information
rhatdan authored Feb 20, 2020
2 parents d08248b + 0d4b6a2 commit b3ef866
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 29 deletions.
36 changes: 19 additions & 17 deletions go-selinux/selinux_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ const (
selinuxTag = "SELINUX"
xattrNameSelinux = "security.selinux"
stRdOnly = 0x01
selinuxfsMagic = 0xf97cff8c
)

type selinuxState struct {
Expand Down Expand Up @@ -115,7 +114,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 @@ -247,10 +247,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 @@ -264,10 +271,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 @@ -339,7 +344,7 @@ func ExecLabel() (string, error) {
return readAttr("exec")
}

func writeCon(fpath string, val string) error {
func writeCon(fpath, val string) error {
if fpath == "" {
return ErrEmptyPath
}
Expand All @@ -355,10 +360,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 @@ -524,19 +527,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 @@ -548,7 +550,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 @@ -730,7 +732,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)
}
}

0 comments on commit b3ef866

Please sign in to comment.