Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for --preserve-fds on FreeBSD for run and exec #16512

Merged
merged 2 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/domain/infra/abi/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -870,7 +870,7 @@ func makeExecConfig(options entities.ExecOptions, rt *libpod.Runtime) (*libpod.E

func checkExecPreserveFDs(options entities.ExecOptions) error {
if options.PreserveFDs > 0 {
entries, err := os.ReadDir("/proc/self/fd")
entries, err := os.ReadDir(processFileDescriptorsPath)
if err != nil {
return err
}
Expand All @@ -879,7 +879,7 @@ func checkExecPreserveFDs(options entities.ExecOptions) error {
for _, e := range entries {
i, err := strconv.Atoi(e.Name())
if err != nil {
return fmt.Errorf("cannot parse %s in /proc/self/fd: %w", e.Name(), err)
return fmt.Errorf("cannot parse %s in %s: %w", e.Name(), processFileDescriptorsPath, err)
}
m[i] = true
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/domain/infra/abi/containers_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package abi

const processFileDescriptorsPath = "/dev/fd"
3 changes: 3 additions & 0 deletions pkg/domain/infra/abi/containers_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package abi

const processFileDescriptorsPath = "/proc/self/fd"
63 changes: 63 additions & 0 deletions pkg/rootless/rootless_freebsd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/select.h>

static int open_files_max_fd;
static fd_set *open_files_set;

int
is_fd_inherited(int fd)
{
if (open_files_set == NULL || fd > open_files_max_fd || fd < 0)
return 0;

return FD_ISSET(fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE])) ? 1 : 0;
}

static void __attribute__((constructor)) init()
{
/* Store how many FDs were open before the Go runtime kicked in. */
DIR* d = opendir ("/dev/fd");
if (d)
{
struct dirent *ent;
size_t size = 0;

for (ent = readdir (d); ent; ent = readdir (d))
{
int fd;

if (ent->d_name[0] == '.')
continue;

fd = atoi (ent->d_name);
if (fd == dirfd (d)) {
continue;
}

if (fd >= size * FD_SETSIZE)
{
int i;
size_t new_size;

new_size = (fd / FD_SETSIZE) + 1;
open_files_set = realloc (open_files_set, new_size * sizeof (fd_set));
if (open_files_set == NULL)
_exit (EXIT_FAILURE);

for (i = size; i < new_size; i++)
FD_ZERO (&(open_files_set[i]));

size = new_size;
}

if (fd > open_files_max_fd) {
open_files_max_fd = fd;
}

FD_SET (fd % FD_SETSIZE, &(open_files_set[fd / FD_SETSIZE]));
}
}
}
69 changes: 69 additions & 0 deletions pkg/rootless/rootless_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//go:build freebsd && cgo
// +build freebsd,cgo

package rootless

import (
"errors"

"github.com/containers/storage/pkg/idtools"
)

// extern int is_fd_inherited(int fd);
import "C"

// IsRootless returns whether the user is rootless
func IsRootless() bool {
return false
}

// BecomeRootInUserNS re-exec podman in a new userNS. It returns whether podman was re-executed
// into a new user namespace and the return code from the re-executed podman process.
// If podman was re-executed the caller needs to propagate the error code returned by the child
// process. It is a convenience function for BecomeRootInUserNSWithOpts with a default configuration.
func BecomeRootInUserNS(pausePid string) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}

// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
return -1
}

// GetRootlessGID returns the GID of the user in the parent userNS
func GetRootlessGID() int {
return -1
}

// TryJoinFromFilePaths attempts to join the namespaces of the pid files in paths.
// This is useful when there are already running containers and we
// don't have a pause process yet. We can use the paths to the conmon
// processes to attempt joining their namespaces.
// If needNewNamespace is set, the file is read from a temporary user
// namespace, this is useful for containers that are running with a
// different uidmap and the unprivileged user has no way to read the
// file owned by the root in the container.
func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []string) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}

// ConfigurationMatches checks whether the additional uids/gids configured for the user
// match the current user namespace.
func ConfigurationMatches() (bool, error) {
return true, nil
}

// GetConfiguredMappings returns the additional IDs configured for the current user.
func GetConfiguredMappings(quiet bool) ([]idtools.IDMap, []idtools.IDMap, error) {
return nil, nil, errors.New("this function is not supported on this os")
}

// ReadMappingsProc returns the uid_map and gid_map
func ReadMappingsProc(path string) ([]idtools.IDMap, error) {
return nil, nil
}

// IsFdInherited checks whether the fd is opened and valid to use
func IsFdInherited(fd int) bool {
return int(C.is_fd_inherited(C.int(fd))) > 0
}
4 changes: 2 additions & 2 deletions pkg/rootless/rootless_unsupported.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//go:build !linux || !cgo
// +build !linux !cgo
//go:build !(linux || freebsd) || !cgo
// +build !linux,!freebsd !cgo

package rootless

Expand Down