Skip to content
9 changes: 9 additions & 0 deletions internal/config/node/node_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package node

// ValidateConfig initializes and validates all of the singleton variables
// that store the node's configuration. Nothing here for FreeBSD yet.
// We check the error at server configuration validation, and if we error, shutdown
// cri-o early, instead of when we're already trying to run containers.
func ValidateConfig() error {
return nil
}
11 changes: 7 additions & 4 deletions internal/config/node/node_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
//go:build !linux
// +build !linux
//go:build !linux && !freebsd
// +build !linux,!freebsd

package node

import "fmt"
import (
"fmt"
"runtime"
)

func ValidateConfig() error {
return fmt.Errorf("CRI-O is only supported on linux")
return fmt.Errorf("CRI-O is not supported on %s", runtime.GOOS)
}
59 changes: 59 additions & 0 deletions internal/config/nsmgr/nsmgr_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package nsmgr

import (
"errors"
"fmt"
"runtime"
)

// NamespaceManager manages the server's namespaces.
// Specifically, it is an interface for how the server is creating namespaces,
// and can be requested to create namespaces for a pod.
type NamespaceManager struct {
}

// New creates a new NamespaceManager.
func New(namespacesDir, pinnsPath string) *NamespaceManager {
return &NamespaceManager{}
}

func (mgr *NamespaceManager) Initialize() error {
return nil
}

// NewPodNamespaces creates new namespaces for a pod. For FreeBSD, there is only
// the vnet network namespace which is implemented as a parent jail for each
// container in the pod. The caller is responsible for cleaning up the
// namespaces by calling Namespace.Remove().
func (mgr *NamespaceManager) NewPodNamespaces(cfg *PodNamespacesConfig) ([]Namespace, error) {
if cfg == nil {
return nil, errors.New("PodNamespacesConfig cannot be nil")
}
if len(cfg.Namespaces) == 0 {
return []Namespace{}, nil
}

returnedNamespaces := make([]Namespace, 0, len(cfg.Namespaces))
for _, cns := range cfg.Namespaces {
if cns.Type != NETNS {
return nil, fmt.Errorf("invalid namespace type: %s", cns.Type)
}
if cns.Host == false {
ns, err := GetNamespace(cns.Path, cns.Type)
if err != nil {
return nil, err
}
returnedNamespaces = append(returnedNamespaces, ns)
}
}
return returnedNamespaces, nil
}

// NamespacePathFromProc returns the namespace path of type nsType for a given pid and type.
func NamespacePathFromProc(nsType NSType, pid int) string {
return ""
}

func (mgr *NamespaceManager) NamespaceFromProcEntry(pid int, nsType NSType) (_ Namespace, retErr error) {
return nil, fmt.Errorf("(*NamespaceManager).NamespaceFromProcEntry unsupported on %s", runtime.GOOS)
}
4 changes: 2 additions & 2 deletions internal/config/nsmgr/nsmgr_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build !linux
// +build !linux
//go:build !linux && !freebsd
// +build !linux,!freebsd

package nsmgr

Expand Down
67 changes: 67 additions & 0 deletions internal/config/nsmgr/types_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//go:build freebsd
// +build freebsd

package nsmgr

import (
"sync"
)

// supportedNamespacesForPinning returns a slice of
// the names of namespaces that CRI-O supports
// pinning.
func supportedNamespacesForPinning() []NSType {
return []NSType{NETNS}
}

type PodNamespacesConfig struct {
Namespaces []*PodNamespaceConfig
}

type PodNamespaceConfig struct {
Type NSType
Host bool
Path string
}

// namespace is the internal implementation of the Namespace interface.
type namespace struct {
sync.Mutex
closed bool
nsType NSType
jailName string
}

// Path returns the bind mount path of the namespace.
func (n *namespace) Path() string {
if n == nil {
return ""
}
return n.jailName
}

// Type returns the namespace type (net, ipc, user, pid or uts).
func (n *namespace) Type() NSType {
return n.nsType
}

// Remove ensures this namespace is closed and removed.
func (n *namespace) Remove() error {
n.Lock()
defer n.Unlock()

if n.closed {
// Remove() can be called multiple
// times without returning an error.
return nil
}

n.closed = true
return nil
}

// GetNamespace takes a path and type, checks if it is a namespace, and if so
// returns an instance of the Namespace interface.
func GetNamespace(jailName string, nsType NSType) (Namespace, error) {
return &namespace{nsType: nsType, jailName: jailName}, nil
}
6 changes: 4 additions & 2 deletions internal/factory/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"path/filepath"
"runtime"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -144,7 +145,8 @@ type container struct {

// New creates a new, empty Sandbox instance
func New() (Container, error) {
spec, err := generate.New("linux")
// TODO: use image os
spec, err := generate.New(runtime.GOOS)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -483,7 +485,7 @@ func (c *container) UserRequestedImage() (string, error) {
// be readonly, which it defaults to if the container wasn't
// specifically asked to be read only
func (c *container) ReadOnly(serverIsReadOnly bool) bool {
if c.config.Linux.SecurityContext.ReadonlyRootfs {
if c.config.Linux != nil && c.config.Linux.SecurityContext.ReadonlyRootfs {
return true
}
return serverIsReadOnly
Expand Down
20 changes: 0 additions & 20 deletions internal/factory/sandbox/infra.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import (
"fmt"
"io"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/cri-o/cri-o/internal/factory/container"
Expand Down Expand Up @@ -59,24 +57,6 @@ func (s *sandbox) InitInfraContainer(serverConfig *libconfig.Config, podContaine
return nil
}

// SetupShim mounts a path to pod sandbox's shared memory
func SetupShm(podSandboxRunDir, mountLabel string, shmSize int64) (shmPath string, _ error) {
if shmSize <= 0 {
return "", fmt.Errorf("shm size %d must be greater than 0", shmSize)
}

shmPath = filepath.Join(podSandboxRunDir, "shm")
if err := os.Mkdir(shmPath, 0o700); err != nil {
return "", err
}
shmOptions := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
if err := unix.Mount("shm", shmPath, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV,
label.FormatMountLabel(shmOptions, mountLabel)); err != nil {
return "", fmt.Errorf("failed to mount shm tmpfs for pod: %v", err)
}
return shmPath, nil
}

// Spec can only be called after a successful call to InitInfraContainer
func (s *sandbox) Spec() *generate.Generator {
return s.infra.Spec()
Expand Down
29 changes: 29 additions & 0 deletions internal/factory/sandbox/infra_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package sandbox

import (
"fmt"
"os"
"path/filepath"
"strconv"

"github.com/opencontainers/selinux/go-selinux/label"
"golang.org/x/sys/unix"
)

// SetupShim mounts a path to pod sandbox's shared memory
func SetupShm(podSandboxRunDir, mountLabel string, shmSize int64) (shmPath string, _ error) {
if shmSize <= 0 {
return "", fmt.Errorf("shm size %d must be greater than 0", shmSize)
}

shmPath = filepath.Join(podSandboxRunDir, "shm")
if err := os.Mkdir(shmPath, 0o700); err != nil {
return "", err
}
shmOptions := "mode=1777,size=" + strconv.FormatInt(shmSize, 10)
if err := unix.Mount("shm", shmPath, "tmpfs", unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV,
label.FormatMountLabel(shmOptions, mountLabel)); err != nil {
return "", fmt.Errorf("failed to mount shm tmpfs for pod: %v", err)
}
return shmPath, nil
}
16 changes: 0 additions & 16 deletions internal/lib/container_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,22 +371,6 @@ func (c *ContainerServer) LoadSandbox(ctx context.Context, id string) (sb *sandb
return sb, nil
}

func configNsPath(spec *rspec.Spec, nsType rspec.LinuxNamespaceType) (string, error) {
for _, ns := range spec.Linux.Namespaces {
if ns.Type != nsType {
continue
}

if ns.Path == "" {
return "", fmt.Errorf("empty networking namespace")
}

return ns.Path, nil
}

return "", fmt.Errorf("missing networking namespace")
}

var ErrIsNonCrioContainer = errors.New("non CRI-O container")

// LoadContainer loads a container from the disk into the container store
Expand Down
20 changes: 20 additions & 0 deletions internal/lib/container_server_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package lib

import (
"fmt"

"github.com/containers/podman/v4/pkg/annotations"
rspec "github.com/opencontainers/runtime-spec/specs-go"
)

func configNsPath(spec *rspec.Spec, nsType rspec.LinuxNamespaceType) (string, error) {
if nsType == rspec.NetworkNamespace {
// On FreeBSD, if we are not using HostNetwork, the namespace
// 'path' is the sandbox ID which is used as the name for the
// infra container jail which owns the pod vnet.
if !isTrue(spec.Annotations[annotations.HostNetwork]) {
return spec.Annotations[annotations.SandboxID], nil
}
}
return "", fmt.Errorf("missing networking namespace")
}
19 changes: 19 additions & 0 deletions internal/lib/container_server_linux.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package lib

import (
"fmt"

"github.com/cri-o/cri-o/internal/lib/sandbox"
rspec "github.com/opencontainers/runtime-spec/specs-go"
selinux "github.com/opencontainers/selinux/go-selinux"
"github.com/opencontainers/selinux/go-selinux/label"
)
Expand Down Expand Up @@ -34,3 +37,19 @@ func (c *ContainerServer) removeSandboxPlatform(sb *sandbox.Sandbox) error {
}
return nil
}

func configNsPath(spec *rspec.Spec, nsType rspec.LinuxNamespaceType) (string, error) {
for _, ns := range spec.Linux.Namespaces {
if ns.Type != nsType {
continue
}

if ns.Path == "" {
return "", fmt.Errorf("empty networking namespace")
}

return ns.Path, nil
}

return "", fmt.Errorf("missing networking namespace")
}
7 changes: 0 additions & 7 deletions internal/lib/sandbox/sandbox.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,3 @@ func (s *Sandbox) Ready(takeLock bool) bool {

return cState.Status == oci.ContainerStateRunning
}

// NeedsInfra is a function that returns whether the sandbox will need an infra container.
// If the server manages the namespace lifecycles, and the Pid option on the sandbox
// is node or container level, the infra container is not needed
func (s *Sandbox) NeedsInfra(serverDropsInfra bool) bool {
return !serverDropsInfra || s.nsOpts.Pid == types.NamespaceMode_POD
}
Loading