mirror of
https://github.com/containers/podman.git
synced 2025-10-17 19:24:04 +08:00

Non-Linux systems, such as BSD kernels, constrain xatter updates according to file permissions. This is in contrast to Linux selinux attr writes, which are governed by an selinux policy. By dafault this policy apllows users to relabel files owned by themselves even if file perms would otherwise disallow write. This results in robust container relabeling results on Linux, and fragile results everywhere else. Therefore, change the mac policy to force the nfs_t context on all files, and ignore all relabel events. As a side-effect, this will disallow any ability to store custom selinux constants on files. However, this is of limited use in a machine context, since files in these volumes are externally managed on systems which do not support SELinux. Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
176 lines
5.9 KiB
Go
176 lines
5.9 KiB
Go
//go:build darwin
|
|
|
|
package applehv
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"syscall"
|
|
|
|
"github.com/containers/common/pkg/strongunits"
|
|
"github.com/containers/podman/v5/pkg/machine"
|
|
"github.com/containers/podman/v5/pkg/machine/define"
|
|
"github.com/containers/podman/v5/pkg/machine/ignition"
|
|
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
|
"github.com/containers/podman/v5/pkg/systemd/parser"
|
|
vfRest "github.com/crc-org/vfkit/pkg/rest"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
func (a *AppleHVStubber) Remove(mc *vmconfigs.MachineConfig) ([]string, func() error, error) {
|
|
return []string{}, func() error { return nil }, nil
|
|
}
|
|
|
|
// getIgnitionVsockDeviceAsCLI retrieves the ignition vsock device and converts
|
|
// it to a cmdline format
|
|
func getIgnitionVsockDeviceAsCLI(ignitionSocketPath string) ([]string, error) {
|
|
ignitionVsockDevice, err := getIgnitionVsockDevice(ignitionSocketPath)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Convert the device into cli args
|
|
ignitionVsockDeviceCLI, err := ignitionVsockDevice.ToCmdLine()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ignitionVsockDeviceCLI, nil
|
|
}
|
|
|
|
// getDebugDevicesCMDArgs retrieves the debug devices and converts them to a
|
|
// cmdline format
|
|
func getDebugDevicesCMDArgs() ([]string, error) {
|
|
args := []string{}
|
|
debugDevices, err := getDebugDevices()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, debugDevice := range debugDevices {
|
|
debugCli, err := debugDevice.ToCmdLine()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
args = append(args, debugCli...)
|
|
}
|
|
return args, nil
|
|
}
|
|
|
|
// getVfKitEndpointCMDArgs converts the vfkit endpoint to a cmdline format
|
|
func getVfKitEndpointCMDArgs(endpoint string) ([]string, error) {
|
|
restEndpoint, err := vfRest.NewEndpoint(endpoint)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return restEndpoint.ToCmdLine()
|
|
}
|
|
|
|
func (a *AppleHVStubber) State(mc *vmconfigs.MachineConfig, _ bool) (define.Status, error) {
|
|
vmStatus, err := mc.AppleHypervisor.Vfkit.State()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return vmStatus, nil
|
|
}
|
|
|
|
func (a *AppleHVStubber) StopVM(mc *vmconfigs.MachineConfig, _ bool) error {
|
|
return mc.AppleHypervisor.Vfkit.Stop(false, true)
|
|
}
|
|
|
|
// checkProcessRunning checks non blocking if the pid exited
|
|
// returns nil if process is running otherwise an error if not
|
|
func checkProcessRunning(processName string, pid int) error {
|
|
var status syscall.WaitStatus
|
|
pid, err := syscall.Wait4(pid, &status, syscall.WNOHANG, nil)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to read %s process status: %w", processName, err)
|
|
}
|
|
if pid > 0 {
|
|
// child exited
|
|
return fmt.Errorf("%s exited unexpectedly with exit code %d", processName, status.ExitStatus())
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// resizeDisk uses os truncate to resize (only larger) a raw disk. the input size
|
|
// is assumed GiB
|
|
func resizeDisk(mc *vmconfigs.MachineConfig, newSize strongunits.GiB) error {
|
|
logrus.Debugf("resizing %s to %d bytes", mc.ImagePath.GetPath(), newSize.ToBytes())
|
|
return os.Truncate(mc.ImagePath.GetPath(), int64(newSize.ToBytes()))
|
|
}
|
|
|
|
func generateSystemDFilesForVirtiofsMounts(mounts []machine.VirtIoFs) []ignition.Unit {
|
|
// mounting in fcos with virtiofs is a bit of a dance. we need a unit file for the mount, a unit file
|
|
// for automatic mounting on boot, and a "preparatory" service file that disables FCOS security, performs
|
|
// the mkdir of the mount point, and then re-enables security. This must be done for each mount.
|
|
|
|
unitFiles := make([]ignition.Unit, 0, len(mounts))
|
|
for _, mnt := range mounts {
|
|
// Here we are looping the mounts and for each mount, we are adding two unit files
|
|
// for virtiofs. One unit file is the mount itself and the second is to automount it
|
|
// on boot.
|
|
autoMountUnit := parser.NewUnitFile()
|
|
autoMountUnit.Add("Automount", "Where", "%s")
|
|
autoMountUnit.Add("Install", "WantedBy", "multi-user.target")
|
|
autoMountUnit.Add("Unit", "Description", "Mount virtiofs volume %s")
|
|
autoMountUnitFile, err := autoMountUnit.ToString()
|
|
if err != nil {
|
|
logrus.Warnf(err.Error())
|
|
}
|
|
|
|
mountUnit := parser.NewUnitFile()
|
|
mountUnit.Add("Mount", "What", "%s")
|
|
mountUnit.Add("Mount", "Where", "%s")
|
|
mountUnit.Add("Mount", "Type", "virtiofs")
|
|
mountUnit.Add("Mount", "Options", "context=\"system_u:object_r:nfs_t:s0\"")
|
|
mountUnit.Add("Install", "WantedBy", "multi-user.target")
|
|
mountUnitFile, err := mountUnit.ToString()
|
|
if err != nil {
|
|
logrus.Warnf(err.Error())
|
|
}
|
|
|
|
virtiofsAutomount := ignition.Unit{
|
|
Enabled: ignition.BoolToPtr(true),
|
|
Name: fmt.Sprintf("%s.automount", mnt.Tag),
|
|
Contents: ignition.StrToPtr(fmt.Sprintf(autoMountUnitFile, mnt.Target, mnt.Target)),
|
|
}
|
|
virtiofsMount := ignition.Unit{
|
|
Enabled: ignition.BoolToPtr(true),
|
|
Name: fmt.Sprintf("%s.mount", mnt.Tag),
|
|
Contents: ignition.StrToPtr(fmt.Sprintf(mountUnitFile, mnt.Tag, mnt.Target)),
|
|
}
|
|
|
|
// This "unit" simulates something like systemctl enable virtiofs-mount-prepare@
|
|
enablePrep := ignition.Unit{
|
|
Enabled: ignition.BoolToPtr(true),
|
|
Name: fmt.Sprintf("virtiofs-mount-prepare@%s.service", mnt.Tag),
|
|
}
|
|
|
|
unitFiles = append(unitFiles, virtiofsAutomount, virtiofsMount, enablePrep)
|
|
}
|
|
|
|
// mount prep is a way to workaround the FCOS limitation of creating directories
|
|
// at the rootfs / and then mounting to them.
|
|
mountPrep := parser.NewUnitFile()
|
|
mountPrep.Add("Unit", "Description", "Allow virtios to mount to /")
|
|
mountPrep.Add("Unit", "DefaultDependencies", "no")
|
|
mountPrep.Add("Unit", "ConditionPathExists", "!%f")
|
|
|
|
mountPrep.Add("Service", "Type", "oneshot")
|
|
mountPrep.Add("Service", "ExecStartPre", "chattr -i /")
|
|
mountPrep.Add("Service", "ExecStart", "mkdir -p '%f'")
|
|
mountPrep.Add("Service", "ExecStopPost", "chattr +i /")
|
|
|
|
mountPrep.Add("Install", "WantedBy", "remote-fs.target")
|
|
mountPrepFile, err := mountPrep.ToString()
|
|
if err != nil {
|
|
logrus.Warnf(err.Error())
|
|
}
|
|
|
|
virtioFSChattr := ignition.Unit{
|
|
Contents: ignition.StrToPtr(mountPrepFile),
|
|
Name: "virtiofs-mount-prepare@.service",
|
|
}
|
|
unitFiles = append(unitFiles, virtioFSChattr)
|
|
|
|
return unitFiles
|
|
}
|