From 415727cd9f9bde7299269bd45b8fcad675041782 Mon Sep 17 00:00:00 2001 From: Yanqiang Miao Date: Wed, 8 Aug 2018 17:32:01 +0800 Subject: [PATCH] verify selinux level format Signed-off-by: Yanqiang Miao --- pkg/server/helpers.go | 15 ++++++ pkg/server/helpers_selinux_test.go | 86 ++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 3 deletions(-) diff --git a/pkg/server/helpers.go b/pkg/server/helpers.go index 29f2f9ba4..5dd65c458 100644 --- a/pkg/server/helpers.go +++ b/pkg/server/helpers.go @@ -21,6 +21,7 @@ import ( "fmt" "path" "path/filepath" + "regexp" "strconv" "strings" @@ -375,6 +376,12 @@ func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) return "", "", nil } + // make sure the format of "level" is correct. + ok, err := checkSelinuxLevel(selinuxOpt.GetLevel()) + if err != nil || !ok { + return "", "", err + } + labelOpts := fmt.Sprintf("%s:%s:%s:%s", selinuxOpt.GetUser(), selinuxOpt.GetRole(), @@ -383,6 +390,14 @@ func initSelinuxOpts(selinuxOpt *runtime.SELinuxOption) (string, string, error) return label.InitLabels(selinux.DupSecOpt(labelOpts)) } +func checkSelinuxLevel(level string) (bool, error) { + matched, err := regexp.MatchString(`^s\d(-s\d)??(:c\d{1,4}((.c\d{1,4})?,c\d{1,4})*(.c\d{1,4})?(,c\d{1,4}(.c\d{1,4})?)*)?$`, level) + if err != nil || !matched { + return false, fmt.Errorf("the format of 'level' %q is not correct: %v", level, err) + } + return true, nil +} + // isInCRIMounts checks whether a destination is in CRI mount list. func isInCRIMounts(dst string, mounts []*runtime.Mount) bool { for _, m := range mounts { diff --git a/pkg/server/helpers_selinux_test.go b/pkg/server/helpers_selinux_test.go index 235dcff9d..3b7593316 100644 --- a/pkg/server/helpers_selinux_test.go +++ b/pkg/server/helpers_selinux_test.go @@ -35,6 +35,7 @@ func TestInitSelinuxOpts(t *testing.T) { selinuxOpt *runtime.SELinuxOption processLabel string mountLabels []string + expectErr bool }{ "Should return empty strings for processLabel and mountLabel when selinuxOpt is nil": { selinuxOpt: nil, @@ -61,12 +62,91 @@ func TestInitSelinuxOpts(t *testing.T) { processLabel: "user_u:user_r:user_t:s0:c1,c2", mountLabels: []string{"user_u:object_r:container_file_t:s0:c1,c2", "user_u:object_r:svirt_sandbox_file_t:s0:c1,c2"}, }, + "Should return error when the format of 'level' is not correct": { + selinuxOpt: &runtime.SELinuxOption{ + User: "user_u", + Role: "user_r", + Type: "user_t", + Level: "s0,c1,c2", + }, + expectErr: true, + }, } { t.Run(desc, func(t *testing.T) { processLabel, mountLabel, err := initSelinuxOpts(test.selinuxOpt) - assert.NoError(t, err) - assert.Equal(t, test.processLabel, processLabel) - assert.Contains(t, test.mountLabels, mountLabel) + if test.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.processLabel, processLabel) + assert.Contains(t, test.mountLabels, mountLabel) + } + }) + } +} + +func TestCheckSelinuxLevel(t *testing.T) { + for desc, test := range map[string]struct { + level string + expectErr bool + }{ + "s0": { + level: "s0", + }, + "s0-s0": { + level: "s0-s0", + }, + "s0:c0": { + level: "s0:c0", + }, + "s0:c0.c3": { + level: "s0:c0.c3", + }, + "s0:c0,c3": { + level: "s0:c0,c3", + }, + "s0-s0:c0,c3": { + level: "s0-s0:c0,c3", + }, + "s0-s0:c0,c3.c6": { + level: "s0-s0:c0,c3.c6", + }, + "s0-s0:c0,c3.c6,c8.c10": { + level: "s0-s0:c0,c3.c6,c8.c10", + }, + "s0-s0:c0,c3.c6,c8,c10": { + level: "s0-s0:c0,c3.c6", + }, + "s0,c0,c3": { + level: "s0,c0,c3", + expectErr: true, + }, + "s0:c0.c3.c6": { + level: "s0:c0.c3.c6", + expectErr: true, + }, + "s0-s0,c0,c3": { + level: "s0-s0,c0,c3", + expectErr: true, + }, + "s0-s0:c0.c3.c6": { + level: "s0-s0:c0.c3.c6", + expectErr: true, + }, + "s0-s0:c0,c3.c6.c8": { + level: "s0-s0:c0,c3.c6.c8", + expectErr: true, + }, + } { + t.Run(desc, func(t *testing.T) { + ok, err := checkSelinuxLevel(test.level) + if test.expectErr { + assert.Error(t, err) + assert.False(t, ok) + } else { + assert.NoError(t, err) + assert.True(t, ok) + } }) } }