summaryrefslogtreecommitdiff
path: root/libpod/container_internal_freebsd.go
diff options
context:
space:
mode:
Diffstat (limited to 'libpod/container_internal_freebsd.go')
-rw-r--r--libpod/container_internal_freebsd.go285
1 files changed, 285 insertions, 0 deletions
diff --git a/libpod/container_internal_freebsd.go b/libpod/container_internal_freebsd.go
new file mode 100644
index 000000000..40c6c5ebf
--- /dev/null
+++ b/libpod/container_internal_freebsd.go
@@ -0,0 +1,285 @@
+//go:build freebsd
+// +build freebsd
+
+package libpod
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "strings"
+ "sync"
+ "syscall"
+ "time"
+
+ "github.com/containers/common/libnetwork/types"
+ "github.com/containers/podman/v4/pkg/rootless"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/opencontainers/runtime-tools/generate"
+ "github.com/sirupsen/logrus"
+ "golang.org/x/sys/unix"
+)
+
+var (
+ bindOptions = []string{}
+)
+
+// Network stubs to decouple container_internal_freebsd.go from
+// networking_freebsd.go so they can be reviewed separately.
+func (r *Runtime) createNetNS(ctr *Container) (netJail string, q map[string]types.StatusBlock, retErr error) {
+ return "", nil, errors.New("not implemented (*Runtime) createNetNS")
+}
+
+func (r *Runtime) teardownNetNS(ctr *Container) error {
+ return errors.New("not implemented (*Runtime) teardownNetNS")
+}
+
+func (r *Runtime) reloadContainerNetwork(ctr *Container) (map[string]types.StatusBlock, error) {
+ return nil, errors.New("not implemented (*Runtime) reloadContainerNetwork")
+}
+
+func (c *Container) mountSHM(shmOptions string) error {
+ return nil
+}
+
+func (c *Container) unmountSHM(path string) error {
+ return nil
+}
+
+// prepare mounts the container and sets up other required resources like net
+// namespaces
+func (c *Container) prepare() error {
+ var (
+ wg sync.WaitGroup
+ jailName string
+ networkStatus map[string]types.StatusBlock
+ createNetNSErr, mountStorageErr error
+ mountPoint string
+ tmpStateLock sync.Mutex
+ )
+
+ wg.Add(2)
+
+ go func() {
+ defer wg.Done()
+ // Set up network namespace if not already set up
+ noNetNS := c.state.NetworkJail == ""
+ if c.config.CreateNetNS && noNetNS && !c.config.PostConfigureNetNS {
+ jailName, networkStatus, createNetNSErr = c.runtime.createNetNS(c)
+ if createNetNSErr != nil {
+ return
+ }
+
+ tmpStateLock.Lock()
+ defer tmpStateLock.Unlock()
+
+ // Assign NetNS attributes to container
+ c.state.NetworkJail = jailName
+ c.state.NetworkStatus = networkStatus
+ }
+ }()
+ // Mount storage if not mounted
+ go func() {
+ defer wg.Done()
+ mountPoint, mountStorageErr = c.mountStorage()
+
+ if mountStorageErr != nil {
+ return
+ }
+
+ tmpStateLock.Lock()
+ defer tmpStateLock.Unlock()
+
+ // Finish up mountStorage
+ c.state.Mounted = true
+ c.state.Mountpoint = mountPoint
+
+ logrus.Debugf("Created root filesystem for container %s at %s", c.ID(), c.state.Mountpoint)
+ }()
+
+ wg.Wait()
+
+ var createErr error
+ if mountStorageErr != nil {
+ if createErr != nil {
+ logrus.Errorf("Preparing container %s: %v", c.ID(), createErr)
+ }
+ createErr = mountStorageErr
+ }
+
+ if createErr != nil {
+ return createErr
+ }
+
+ // Save changes to container state
+ if err := c.save(); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// cleanupNetwork unmounts and cleans up the container's network
+func (c *Container) cleanupNetwork() error {
+ if c.config.NetNsCtr != "" {
+ return nil
+ }
+ netDisabled, err := c.NetworkDisabled()
+ if err != nil {
+ return err
+ }
+ if netDisabled {
+ return nil
+ }
+
+ // Stop the container's network namespace (if it has one)
+ if err := c.runtime.teardownNetNS(c); err != nil {
+ logrus.Errorf("Unable to cleanup network for container %s: %q", c.ID(), err)
+ }
+
+ if c.valid {
+ return c.save()
+ }
+
+ return nil
+}
+
+// reloadNetwork reloads the network for the given container, recreating
+// firewall rules.
+func (c *Container) reloadNetwork() error {
+ result, err := c.runtime.reloadContainerNetwork(c)
+ if err != nil {
+ return err
+ }
+
+ c.state.NetworkStatus = result
+
+ return c.save()
+}
+
+// Add an existing container's network jail
+func (c *Container) addNetworkContainer(g *generate.Generator, ctr string) error {
+ nsCtr, err := c.runtime.state.Container(ctr)
+ c.runtime.state.UpdateContainer(nsCtr)
+ if err != nil {
+ return fmt.Errorf("error retrieving dependency %s of container %s from state: %w", ctr, c.ID(), err)
+ }
+ g.AddAnnotation("org.freebsd.parentJail", nsCtr.state.NetworkJail)
+ return nil
+}
+
+func isRootlessCgroupSet(cgroup string) bool {
+ return false
+}
+
+func (c *Container) expectPodCgroup() (bool, error) {
+ return false, nil
+}
+
+func (c *Container) getOCICgroupPath() (string, error) {
+ return "", nil
+}
+
+func openDirectory(path string) (fd int, err error) {
+ const O_PATH = 0x00400000
+ return unix.Open(path, unix.O_RDONLY|O_PATH, 0)
+}
+
+func (c *Container) addNetworkNamespace(g *generate.Generator) error {
+ if c.config.CreateNetNS {
+ g.AddAnnotation("org.freebsd.parentJail", c.state.NetworkJail)
+ }
+ return nil
+}
+
+func (c *Container) addSystemdMounts(g *generate.Generator) error {
+ return nil
+}
+
+func (c *Container) addSharedNamespaces(g *generate.Generator) error {
+ if c.config.NetNsCtr != "" {
+ if err := c.addNetworkContainer(g, c.config.NetNsCtr); err != nil {
+ return err
+ }
+ }
+
+ availableUIDs, availableGIDs, err := rootless.GetAvailableIDMaps()
+ if err != nil {
+ if os.IsNotExist(err) {
+ // The kernel-provided files only exist if user namespaces are supported
+ logrus.Debugf("User or group ID mappings not available: %s", err)
+ } else {
+ return err
+ }
+ } else {
+ g.Config.Linux.UIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.UIDMappings, availableUIDs)
+ g.Config.Linux.GIDMappings = rootless.MaybeSplitMappings(g.Config.Linux.GIDMappings, availableGIDs)
+ }
+
+ // Hostname handling:
+ // If we have a UTS namespace, set Hostname in the OCI spec.
+ // Set the HOSTNAME environment variable unless explicitly overridden by
+ // the user (already present in OCI spec). If we don't have a UTS ns,
+ // set it to the host's hostname instead.
+ hostname := c.Hostname()
+ foundUTS := false
+
+ // TODO: make this optional, needs progress on adding FreeBSD section to the spec
+ foundUTS = true
+ g.SetHostname(hostname)
+
+ if !foundUTS {
+ tmpHostname, err := os.Hostname()
+ if err != nil {
+ return err
+ }
+ hostname = tmpHostname
+ }
+ needEnv := true
+ for _, checkEnv := range g.Config.Process.Env {
+ if strings.SplitN(checkEnv, "=", 2)[0] == "HOSTNAME" {
+ needEnv = false
+ break
+ }
+ }
+ if needEnv {
+ g.AddProcessEnv("HOSTNAME", hostname)
+ }
+ return nil
+}
+
+func (c *Container) addRootPropagation(g *generate.Generator, mounts []spec.Mount) error {
+ return nil
+}
+
+func (c *Container) setProcessLabel(g *generate.Generator) {
+}
+
+func (c *Container) setMountLabel(g *generate.Generator) {
+}
+
+func (c *Container) setCgroupsPath(g *generate.Generator) error {
+ return nil
+}
+
+func (c *Container) addSlirp4netnsDNS(nameservers []string) []string {
+ return nameservers
+}
+
+func (c *Container) isSlirp4netnsIPv6() (bool, error) {
+ return false, nil
+}
+
+// check for net=none
+func (c *Container) hasNetNone() bool {
+ return c.state.NetworkJail == ""
+}
+
+func setVolumeAtime(mountPoint string, st os.FileInfo) error {
+ stat := st.Sys().(*syscall.Stat_t)
+ atime := time.Unix(int64(stat.Atimespec.Sec), int64(stat.Atimespec.Nsec)) //nolint: unconvert
+ if err := os.Chtimes(mountPoint, atime, st.ModTime()); err != nil {
+ return err
+ }
+ return nil
+}