From e28d52bb2c06bd4e9e27e2bfddcdd29c73f60728 Mon Sep 17 00:00:00 2001 From: zzzzzzzzzy9 Date: Thu, 4 Dec 2025 11:09:15 +0800 Subject: [PATCH] When mcs are exhausted, uniqMcs should return an error Signed-off-by: zzzzzzzzzy9 --- go-selinux/label/label_linux.go | 5 ++++- go-selinux/selinux.go | 6 +++--- go-selinux/selinux_linux.go | 35 ++++++++++++++++++++------------ go-selinux/selinux_linux_test.go | 30 +++++++++++++++++++++------ 4 files changed, 53 insertions(+), 23 deletions(-) diff --git a/go-selinux/label/label_linux.go b/go-selinux/label/label_linux.go index 95f29e2..e019907 100644 --- a/go-selinux/label/label_linux.go +++ b/go-selinux/label/label_linux.go @@ -30,7 +30,10 @@ func InitLabels(options []string) (plabel string, mlabel string, retErr error) { if !selinux.GetEnabled() { return "", "", nil } - processLabel, mountLabel := selinux.ContainerLabels() + processLabel, mountLabel, err := selinux.ContainerLabels() + if err != nil { + return "", "", err + } if processLabel != "" { defer func() { if retErr != nil { diff --git a/go-selinux/selinux.go b/go-selinux/selinux.go index 15150d4..0c3976e 100644 --- a/go-selinux/selinux.go +++ b/go-selinux/selinux.go @@ -257,19 +257,19 @@ func ROFileLabel() string { // KVMContainerLabels returns the default processLabel and mountLabel to be used // for kvm containers by the calling process. -func KVMContainerLabels() (string, string) { +func KVMContainerLabels() (string, string, error) { return kvmContainerLabels() } // InitContainerLabels returns the default processLabel and file labels to be // used for containers running an init system like systemd by the calling process. -func InitContainerLabels() (string, string) { +func InitContainerLabels() (string, string, error) { return initContainerLabels() } // ContainerLabels returns an allocated processLabel and fileLabel to be used for // container labeling by the calling process. -func ContainerLabels() (processLabel string, fileLabel string) { +func ContainerLabels() (processLabel string, fileLabel string, err error) { return containerLabels() } diff --git a/go-selinux/selinux_linux.go b/go-selinux/selinux_linux.go index 6d7f8e2..37614d2 100644 --- a/go-selinux/selinux_linux.go +++ b/go-selinux/selinux_linux.go @@ -43,7 +43,7 @@ type selinuxState struct { selinuxfsOnce sync.Once enabledSet bool enabled bool - sync.Mutex + sync.RWMutex } type level struct { @@ -951,7 +951,7 @@ func mcsDelete(mcs string) { } state.Lock() defer state.Unlock() - state.mcsList[mcs] = false + delete(state.mcsList, mcs) } func intToMcs(id int, catRange uint32) string { @@ -974,14 +974,20 @@ func intToMcs(id int, catRange uint32) string { return fmt.Sprintf("s0:c%d,c%d", TIER, ORD) } -func uniqMcs(catRange uint32) string { +func uniqMcs(catRange uint32) (string, error) { var ( n uint32 c1, c2 uint32 mcs string ) - + maxMcsLen := int(catRange*(catRange-1)) / 2 for { + state.RLock() + if len(state.mcsList) == maxMcsLen { + state.Unlock() + return "", fmt.Errorf("mcsList is full, failed to create mcs") + } + state.Unlock() _ = binary.Read(rand.Reader, binary.LittleEndian, &n) c1 = n % catRange _ = binary.Read(rand.Reader, binary.LittleEndian, &n) @@ -997,7 +1003,7 @@ func uniqMcs(catRange uint32) string { } break } - return mcs + return mcs, nil } // releaseLabel un-reserves the MLS/MCS Level field of the specified label, @@ -1066,7 +1072,7 @@ func label(key string) string { // kvmContainerLabels returns the default processLabel and mountLabel to be used // for kvm containers by the calling process. -func kvmContainerLabels() (string, string) { +func kvmContainerLabels() (string, string, error) { processLabel := label("kvm_process") if processLabel == "" { processLabel = label("process") @@ -1077,7 +1083,7 @@ func kvmContainerLabels() (string, string) { // initContainerLabels returns the default processLabel and file labels to be // used for containers running an init system like systemd by the calling process. -func initContainerLabels() (string, string) { +func initContainerLabels() (string, string, error) { processLabel := label("init_process") if processLabel == "" { processLabel = label("process") @@ -1088,9 +1094,9 @@ func initContainerLabels() (string, string) { // containerLabels returns an allocated processLabel and fileLabel to be used for // container labeling by the calling process. -func containerLabels() (processLabel string, fileLabel string) { +func containerLabels() (processLabel string, fileLabel string, err error) { if !getEnabled() { - return "", "" + return "", "", nil } processLabel = label("process") @@ -1098,7 +1104,7 @@ func containerLabels() (processLabel string, fileLabel string) { readOnlyFileLabel = label("ro_file") if processLabel == "" || fileLabel == "" { - return "", fileLabel + return "", fileLabel, nil } if readOnlyFileLabel == "" { @@ -1108,17 +1114,20 @@ func containerLabels() (processLabel string, fileLabel string) { return addMcs(processLabel, fileLabel) } -func addMcs(processLabel, fileLabel string) (string, string) { +func addMcs(processLabel, fileLabel string) (string, string, error) { scon, _ := NewContext(processLabel) if scon["level"] != "" { - mcs := uniqMcs(CategoryRange) + mcs, err := uniqMcs(CategoryRange) + if err != nil { + return "", "", err + } scon["level"] = mcs processLabel = scon.Get() scon, _ = NewContext(fileLabel) scon["level"] = mcs fileLabel = scon.Get() } - return processLabel, fileLabel + return processLabel, fileLabel, nil } // securityCheckContext validates that the SELinux label is understood by the kernel diff --git a/go-selinux/selinux_linux_test.go b/go-selinux/selinux_linux_test.go index 71aa0b8..29f5a42 100644 --- a/go-selinux/selinux_linux_test.go +++ b/go-selinux/selinux_linux_test.go @@ -87,7 +87,10 @@ func TestKVMLabels(t *testing.T) { t.Skip("SELinux not enabled, skipping.") } - plabel, flabel := KVMContainerLabels() + plabel, flabel, err := KVMContainerLabels() + if err != nil { + t.Fatal(err) + } if plabel == "" { t.Log("Failed to read kvm label") } @@ -108,7 +111,10 @@ func TestInitLabels(t *testing.T) { t.Skip("SELinux not enabled, skipping.") } - plabel, flabel := InitContainerLabels() + plabel, flabel, err := InitContainerLabels() + if err != nil { + t.Fatal(err) + } if plabel == "" { t.Log("Failed to read init label") } @@ -265,20 +271,32 @@ func TestSELinux(t *testing.T) { plabel, flabel string ) - plabel, flabel = ContainerLabels() + plabel, flabel, err = ContainerLabels() + if err != nil { + t.Fatal(err) + } t.Log(plabel) t.Log(flabel) - plabel, flabel = ContainerLabels() + plabel, flabel, err = ContainerLabels() + if err != nil { + t.Fatal(err) + } t.Log(plabel) t.Log(flabel) ReleaseLabel(plabel) - plabel, flabel = ContainerLabels() + plabel, flabel, err = ContainerLabels() + if err != nil { + t.Fatal(err) + } t.Log(plabel) t.Log(flabel) ClearLabels() t.Log("ClearLabels") - plabel, flabel = ContainerLabels() + plabel, flabel, err = ContainerLabels() + if err != nil { + t.Fatal("err") + } t.Log(plabel) t.Log(flabel) ReleaseLabel(plabel)