Skip to content

Commit

Permalink
Merge pull request #153 from kolyshkin/lazy-init
Browse files Browse the repository at this point in the history
Lazy init
  • Loading branch information
rhatdan committed Sep 9, 2021
2 parents 4a1acc5 + 335d2e2 commit 935cf7f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 39 deletions.
4 changes: 4 additions & 0 deletions go-selinux/selinux.go
Expand Up @@ -38,6 +38,8 @@ var (

// CategoryRange allows the upper bound on the category range to be adjusted
CategoryRange = DefaultCategoryRange

privContainerMountLabel string
)

// Context is a representation of the SELinux label broken into 4 parts
Expand Down Expand Up @@ -280,5 +282,7 @@ func GetDefaultContextWithLevel(user, level, scon string) (string, error) {

// PrivContainerMountLabel returns mount label for privileged containers
func PrivContainerMountLabel() string {
// Make sure label is initialized.
_ = label("")
return privContainerMountLabel
}
88 changes: 53 additions & 35 deletions go-selinux/selinux_linux.go
Expand Up @@ -12,7 +12,6 @@ import (
"os"
"path"
"path/filepath"
"regexp"
"strconv"
"strings"
"sync"
Expand All @@ -34,8 +33,6 @@ const (
xattrNameSelinux = "security.selinux"
)

var policyRoot = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))

type selinuxState struct {
enabledSet bool
enabled bool
Expand Down Expand Up @@ -70,7 +67,6 @@ const (
)

var (
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
readOnlyFileLabel string
state = selinuxState{
mcsList: make(map[string]bool),
Expand All @@ -79,8 +75,24 @@ var (
// for attrPath()
attrPathOnce sync.Once
haveThreadSelf bool

// for policyRoot()
policyRootOnce sync.Once
policyRootVal string

// for label()
loadLabelsOnce sync.Once
labels map[string]string
)

func policyRoot() string {
policyRootOnce.Do(func() {
policyRootVal = filepath.Join(selinuxDir, readConfig(selinuxTypeTag))
})

return policyRootVal
}

func (s *selinuxState) setEnable(enabled bool) bool {
s.Lock()
defer s.Unlock()
Expand Down Expand Up @@ -222,7 +234,7 @@ func readConfig(target string) string {
scanner := bufio.NewScanner(in)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
Expand All @@ -231,11 +243,12 @@ func readConfig(target string) string {
// Skip comments
continue
}
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
if key == target {
return strings.Trim(val, "\"")
}
fields := bytes.SplitN(line, []byte{'='}, 2)
if len(fields) != 2 {
continue
}
if bytes.Equal(fields[0], []byte(target)) {
return string(bytes.Trim(fields[1], `"`))
}
}
return ""
Expand Down Expand Up @@ -890,24 +903,21 @@ func openContextFile() (*os.File, error) {
if f, err := os.Open(contextFile); err == nil {
return f, nil
}
lxcPath := filepath.Join(policyRoot, "/contexts/lxc_contexts")
return os.Open(lxcPath)
return os.Open(filepath.Join(policyRoot(), "/contexts/lxc_contexts"))
}

var labels, privContainerMountLabel = loadLabels()

func loadLabels() (map[string]string, string) {
labels := make(map[string]string)
func loadLabels() {
labels = make(map[string]string)
in, err := openContextFile()
if err != nil {
return labels, ""
return
}
defer in.Close()

scanner := bufio.NewScanner(in)

for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
line := bytes.TrimSpace(scanner.Bytes())
if len(line) == 0 {
// Skip blank lines
continue
Expand All @@ -916,38 +926,47 @@ func loadLabels() (map[string]string, string) {
// Skip comments
continue
}
if groups := assignRegex.FindStringSubmatch(line); groups != nil {
key, val := strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2])
labels[key] = strings.Trim(val, "\"")
fields := bytes.SplitN(line, []byte{'='}, 2)
if len(fields) != 2 {
continue
}
key, val := bytes.TrimSpace(fields[0]), bytes.TrimSpace(fields[1])
labels[string(key)] = string(bytes.Trim(val, `"`))
}

con, _ := NewContext(labels["file"])
con["level"] = fmt.Sprintf("s0:c%d,c%d", maxCategory-2, maxCategory-1)
reserveLabel(con.get())
return labels, con.get()
privContainerMountLabel = con.get()
reserveLabel(privContainerMountLabel)
}

func label(key string) string {
loadLabelsOnce.Do(func() {
loadLabels()
})
return labels[key]
}

// kvmContainerLabels returns the default processLabel and mountLabel to be used
// for kvm containers by the calling process.
func kvmContainerLabels() (string, string) {
processLabel := labels["kvm_process"]
processLabel := label("kvm_process")
if processLabel == "" {
processLabel = labels["process"]
processLabel = label("process")
}

return addMcs(processLabel, labels["file"])
return addMcs(processLabel, label("file"))
}

// 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) {
processLabel := labels["init_process"]
processLabel := label("init_process")
if processLabel == "" {
processLabel = labels["process"]
processLabel = label("process")
}

return addMcs(processLabel, labels["file"])
return addMcs(processLabel, label("file"))
}

// containerLabels returns an allocated processLabel and fileLabel to be used for
Expand All @@ -957,9 +976,9 @@ func containerLabels() (processLabel string, fileLabel string) {
return "", ""
}

processLabel = labels["process"]
fileLabel = labels["file"]
readOnlyFileLabel = labels["ro_file"]
processLabel = label("process")
fileLabel = label("file")
readOnlyFileLabel = label("ro_file")

if processLabel == "" || fileLabel == "" {
return "", fileLabel
Expand Down Expand Up @@ -1179,15 +1198,14 @@ func getDefaultContextFromReaders(c *defaultSECtx) (string, error) {
}

func getDefaultContextWithLevel(user, level, scon string) (string, error) {
userPath := filepath.Join(policyRoot, selinuxUsersDir, user)
defaultPath := filepath.Join(policyRoot, defaultContexts)

userPath := filepath.Join(policyRoot(), selinuxUsersDir, user)
fu, err := os.Open(userPath)
if err != nil {
return "", err
}
defer fu.Close()

defaultPath := filepath.Join(policyRoot(), defaultContexts)
fd, err := os.Open(defaultPath)
if err != nil {
return "", err
Expand Down
16 changes: 14 additions & 2 deletions go-selinux/selinux_linux_test.go
Expand Up @@ -42,8 +42,6 @@ func TestKVMLabels(t *testing.T) {
t.Skip("SELinux not enabled, skipping.")
}

t.Log(labels)

plabel, flabel := KVMContainerLabels()
if plabel == "" {
t.Log("Failed to read kvm label")
Expand Down Expand Up @@ -535,3 +533,17 @@ func BenchmarkCurrentLabel(b *testing.B) {
}
b.Log(l)
}

func BenchmarkReadConfig(b *testing.B) {
str := ""
for n := 0; n < b.N; n++ {
str = readConfig(selinuxTypeTag)
}
b.Log(str)
}

func BenchmarkLoadLabels(b *testing.B) {
for n := 0; n < b.N; n++ {
loadLabels()
}
}
6 changes: 4 additions & 2 deletions go-selinux/selinux_stub.go
Expand Up @@ -2,8 +2,6 @@

package selinux

const privContainerMountLabel = ""

func setDisabled() {
}

Expand Down Expand Up @@ -152,3 +150,7 @@ func disableSecOpt() []string {
func getDefaultContextWithLevel(user, level, scon string) (string, error) {
return "", nil
}

func label(_ string) string {
return ""
}

0 comments on commit 935cf7f

Please sign in to comment.