Use a native library for SELinux in wwclient
This removes the dependency on shelling out to commands in the image. Signed-off-by: Jonathon Anderson <janderson@ciq.com>
This commit is contained in:
committed by
Christian Goll
parent
81a970bbd5
commit
685fd0338e
@@ -19,6 +19,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
- Manage SELinux context of TFTP directory. #1997
|
- Manage SELinux context of TFTP directory. #1997
|
||||||
- Dynamically write `$tftpdir/warewulf/grub.cfg` to the configured value from `warewulf.conf`
|
- Dynamically write `$tftpdir/warewulf/grub.cfg` to the configured value from `warewulf.conf`
|
||||||
- Absolute paths specified with `{{ file }}` in an overlay now write to that absolute path.
|
- Absolute paths specified with `{{ file }}` in an overlay now write to that absolute path.
|
||||||
|
- Use opencontainers/selinux to manage SELinux in wwclient.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -17,10 +17,12 @@ import (
|
|||||||
|
|
||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/talos-systems/go-smbios/smbios"
|
"github.com/talos-systems/go-smbios/smbios"
|
||||||
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
||||||
"github.com/warewulf/warewulf/internal/pkg/pidfile"
|
"github.com/warewulf/warewulf/internal/pkg/pidfile"
|
||||||
|
"github.com/warewulf/warewulf/internal/pkg/version"
|
||||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -82,6 +84,8 @@ func CobraRunE(cmd *cobra.Command, args []string) (err error) {
|
|||||||
}
|
}
|
||||||
defer cleanUp()
|
defer cleanUp()
|
||||||
|
|
||||||
|
wwlog.Debug("Version: %s", version.GetVersion())
|
||||||
|
|
||||||
target := "/"
|
target := "/"
|
||||||
if os.Args[0] == path.Join(conf.Paths.WWClientdir, "wwclient") {
|
if os.Args[0] == path.Join(conf.Paths.WWClientdir, "wwclient") {
|
||||||
wwlog.Warn("updating live file system: cancel now if this is in error")
|
wwlog.Warn("updating live file system: cancel now if this is in error")
|
||||||
@@ -537,56 +541,43 @@ func cleanUp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// isSELinuxEnabled checks if SELinux is present and enabled on the system
|
|
||||||
func isSELinuxEnabled() bool {
|
|
||||||
// Check if SELinux filesystem is mounted
|
|
||||||
if _, err := os.Stat("/sys/fs/selinux"); os.IsNotExist(err) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if SELinux is enabled (enforcing or permissive)
|
|
||||||
_, err := os.ReadFile("/sys/fs/selinux/enforce")
|
|
||||||
return err == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setSELinuxContextForDestination sets the SELinux context on a temporary file or symlink
|
// setSELinuxContextForDestination sets the SELinux context on a temporary file or symlink
|
||||||
// to match what the destination path should have
|
// to match what the destination path should have
|
||||||
func setSELinuxContextForDestination(tempPath, destPath string) error {
|
func setSELinuxContextForDestination(tempPath, destPath string) error {
|
||||||
if !isSELinuxEnabled() {
|
if !selinux.GetEnabled() {
|
||||||
|
wwlog.Debug("SELinux not enabled, skipping context setting for %s", tempPath)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
wwlog.Debug("setting SELinux context for temp file %s based on destination %s", tempPath, destPath)
|
// Try to get the existing destination's context to preserve it.
|
||||||
|
//
|
||||||
// Use matchpathcon to get the expected context for the destination
|
// We prefer the existing context if the file already exists, because the
|
||||||
cmd := exec.Command("matchpathcon", "-n", destPath)
|
// context is not defined by the overlay itself.
|
||||||
output, err := cmd.Output()
|
refPath := destPath
|
||||||
if err != nil {
|
expectedContext, err := selinux.LfileLabel(refPath)
|
||||||
// If matchpathcon fails, fall back to restorecon on the temp file
|
if err != nil || expectedContext == "" {
|
||||||
wwlog.Debug("matchpathcon failed for %s, using restorecon: %s", destPath, err)
|
// If destination doesn't exist, compute what context it should have based on parent directory
|
||||||
cmd = exec.Command("restorecon", "-F", tempPath)
|
wwlog.Debug("unable to get context from destination %s", refPath)
|
||||||
if err := cmd.Run(); err != nil {
|
refPath = filepath.Dir(destPath)
|
||||||
wwlog.Warn("failed to restore SELinux context for temp file %s: %s", tempPath, err)
|
parentContext, err := selinux.FileLabel(refPath)
|
||||||
|
if err != nil || parentContext == "" {
|
||||||
|
wwlog.Debug("unable to get context from parent %s", refPath)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedContext := strings.TrimSpace(string(output))
|
// Compute what the kernel would assign for a file created in this
|
||||||
if expectedContext == "" {
|
// parent directory
|
||||||
wwlog.Debug("empty context from matchpathcon for %s, using restorecon", destPath)
|
expectedContext, err = selinux.ComputeCreateContext(parentContext, parentContext, "file")
|
||||||
cmd = exec.Command("restorecon", "-F", tempPath)
|
if err != nil || expectedContext == "" {
|
||||||
if err := cmd.Run(); err != nil {
|
wwlog.Debug("could not compute context from parent %s", refPath)
|
||||||
wwlog.Warn("failed to restore SELinux context for temp file %s: %s", tempPath, err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the context on the temp file/symlink
|
// Use LsetFileLabel for symlinks (it's safe for regular files too)
|
||||||
cmd = exec.Command("chcon", "-h", expectedContext, tempPath)
|
wwlog.Debug("setting context %s on temp file %s from %s", expectedContext, tempPath, refPath)
|
||||||
if err := cmd.Run(); err != nil {
|
if err := selinux.LsetFileLabel(tempPath, expectedContext); err != nil {
|
||||||
wwlog.Warn("failed to set SELinux context %s for temp file %s: %s", expectedContext, tempPath, err)
|
wwlog.Warn("failed to set context %s for temp file %s: %s", expectedContext, tempPath, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user