From b42207dd6dc521b2f074c73910b2af22b34ad554 Mon Sep 17 00:00:00 2001 From: Shahriyar Jalayeri Date: Mon, 6 Nov 2023 16:14:30 +0100 Subject: [PATCH] security : check /proc is mounted with secure options Signed-off-by: Shahriyar Jalayeri --- tests/sec/remote.go | 36 ++++++++++++++++++++++++++++++++++++ tests/sec/sec_test.go | 31 ++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/sec/remote.go b/tests/sec/remote.go index c259a3af9..26a319617 100644 --- a/tests/sec/remote.go +++ b/tests/sec/remote.go @@ -1,6 +1,7 @@ package sec_test import ( + "encoding/json" "fmt" "io" "os" @@ -11,6 +12,12 @@ import ( "github.com/lf-edge/eden/pkg/utils" ) +type mount struct { + Point string `json:"point"` + Type string `json:"type"` + Options string `json:"options"` +} + type remoteNode struct { openEVEC *openevec.OpenEVEC } @@ -86,3 +93,32 @@ func (node *remoteNode) readFile(fileName string) ([]byte, error) { command := fmt.Sprintf("cat %s", fileName) return node.runCommand(command) } + +func (node *remoteNode) getMountPoints(mtype string) ([]mount, error) { + mount_command := "mount -l" + if mtype != "" { + mount_command = fmt.Sprintf("mount -l -t %s", mtype) + } + + command := mount_command + ` | awk ' + BEGIN { print " [ "} + { + printf " %s {\"point\": \"%s\", \"type\": \"%s\", \"options\": \"%s\"}", separator, $3, $5, $6; + separator = ","; + } + END { print " ] " } + '` + + out, err := node.runCommand(command) + if err != nil { + return nil, err + } + + var mounts []mount + if err := json.Unmarshal(out, &mounts); err != nil { + return nil, err + + } + + return mounts, nil +} diff --git a/tests/sec/sec_test.go b/tests/sec/sec_test.go index 537606930..3d6d3c0ce 100644 --- a/tests/sec/sec_test.go +++ b/tests/sec/sec_test.go @@ -93,7 +93,6 @@ func TestMain(m *testing.M) { func TestAppArmorEnabled(t *testing.T) { log.Println("TestAppArmorEnabled started") defer log.Println("TestAppArmorEnabled finished") - t.Parallel() edgeNode := tc.GetEdgeNode(tc.WithTest(t)) tc.WaitForState(edgeNode, 60) @@ -108,3 +107,33 @@ func TestAppArmorEnabled(t *testing.T) { t.Fatal("AppArmor is not enabled") } } + +func TestCheckProcMountOptions(t *testing.T) { + log.Println("TestCheckProcMountOptions started") + defer log.Println("TestCheckProcMountOptions finished") + + edgeNode := tc.GetEdgeNode(tc.WithTest(t)) + tc.WaitForState(edgeNode, 60) + + procMounts, err := rnode.getMountPoints("proc") + if err != nil { + t.Fatal(err) + } + + for _, mount := range procMounts { + // check if mount options contains nosuid, nodev and noexec, hidepid=2 + if !strings.Contains(mount.Options, "nosuid") { + t.Fatalf("Mount options for /proc on %s doesn't contain nosuid", mount.Point) + } + if !strings.Contains(mount.Options, "nodev") { + t.Fatalf("Mount options for /proc on %s doesn't contain nodev", mount.Point) + } + if !strings.Contains(mount.Options, "noexec") { + t.Fatalf("Mount options for /proc on %s doesn't contain noexec", mount.Point) + } + if !strings.Contains(mount.Options, "hidepid=2") { + // TODO: set hidepid=2 and make this a fatal error + t.Logf("[!!!WARNING!!!] Mount options for /proc on %s doesn't contain hidepid=2", mount.Point) + } + } +}