mirror of
https://github.com/siderolabs/talos.git
synced 2025-09-28 17:21:24 +02:00
Do not do string lookups in repetitive calls. We do not support changing SELinux status during runtime, so once we read this we can assume status does not change. Also avoid unneeded FS writes when appropriate label is already set on file. Signed-off-by: Dmitry Sharshakov <dmitry.sharshakov@siderolabs.com>
100 lines
2.5 KiB
Go
100 lines
2.5 KiB
Go
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
// Package selinux provides generic code for managing SELinux.
|
|
package selinux
|
|
|
|
import (
|
|
"bytes"
|
|
_ "embed"
|
|
"log"
|
|
"os"
|
|
"sync"
|
|
|
|
"github.com/pkg/xattr"
|
|
"github.com/siderolabs/go-procfs/procfs"
|
|
|
|
"github.com/siderolabs/talos/pkg/machinery/constants"
|
|
)
|
|
|
|
//go:embed policy/policy.33
|
|
var policy []byte
|
|
|
|
// IsEnabled checks if SELinux is enabled on the system by reading
|
|
// the kernel command line. It returns true if SELinux is enabled,
|
|
// otherwise it returns false. It also ensures we're not in a container.
|
|
// By default SELinux is disabled.
|
|
var IsEnabled = sync.OnceValue(func() bool {
|
|
if _, err := os.Stat("/usr/etc/in-container"); err == nil {
|
|
return false
|
|
}
|
|
|
|
val := procfs.ProcCmdline().Get(constants.KernelParamSELinux).First()
|
|
|
|
return val != nil && *val == "1"
|
|
})
|
|
|
|
// IsEnforcing checks if SELinux is enabled and the mode should be enforcing.
|
|
// By default if SELinux is enabled we consider it to be permissive.
|
|
var IsEnforcing = sync.OnceValue(func() bool {
|
|
if !IsEnabled() {
|
|
return false
|
|
}
|
|
|
|
val := procfs.ProcCmdline().Get(constants.KernelParamSELinuxEnforcing).First()
|
|
|
|
return val != nil && *val == "1"
|
|
})
|
|
|
|
// SetLabel sets label for file, directory or symlink (not following symlinks)
|
|
// It does not perform the operation in case SELinux is disabled, provided label is empty or already set.
|
|
func SetLabel(filename string, label string) error {
|
|
if label == "" {
|
|
return nil
|
|
}
|
|
|
|
if IsEnabled() {
|
|
// We use LGet/LSet so that we manipulate label on the exact path, not the symlink target.
|
|
currentLabel, err := xattr.LGet(filename, "security.selinux")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Skip extra FS transactions when labels are okay.
|
|
if string(bytes.Trim(currentLabel, "\x00\n")) == label {
|
|
return nil
|
|
}
|
|
|
|
if err := xattr.LSet(filename, "security.selinux", []byte(label)); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Init initializes SELinux based on the configured mode.
|
|
// It loads the policy and enforces it if necessary.
|
|
func Init() error {
|
|
if !IsEnabled() {
|
|
log.Println("selinux: disabled, not loading policy")
|
|
|
|
return nil
|
|
}
|
|
|
|
if IsEnforcing() {
|
|
log.Println("selinux: running in enforcing mode, policy will be applied as soon as it's loaded")
|
|
}
|
|
|
|
log.Println("selinux: loading policy")
|
|
|
|
if err := os.WriteFile("/sys/fs/selinux/load", policy, 0o777); err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Println("selinux: policy loaded")
|
|
|
|
return nil
|
|
}
|