Skip to content

Commit

Permalink
Merge pull request #338 from dfr/freebsd
Browse files Browse the repository at this point in the history
Port conmon to FreeBSD
  • Loading branch information
rhatdan authored Jul 25, 2022
2 parents b1ca51f + 1750b2d commit daeaf97
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 51 deletions.
6 changes: 6 additions & 0 deletions src/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
#include <fcntl.h>
#include <glib.h>
#include <stdio.h>
#ifdef __linux__
#include <linux/limits.h>
#include <sys/eventfd.h>
#include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/statfs.h>
#endif

#ifndef CGROUP2_SUPER_MAGIC
#define CGROUP2_SUPER_MAGIC 0x63677270
Expand All @@ -24,6 +26,8 @@
int oom_event_fd = -1;
int oom_cgroup_fd = -1;

#ifdef __linux__

static char *process_cgroup_subsystem_path(int pid, bool cgroup2, const char *subsystem);
static void setup_oom_handling_cgroup_v2(int pid);
static void setup_oom_handling_cgroup_v1(int pid);
Expand Down Expand Up @@ -314,3 +318,5 @@ static int write_oom_files()
}
return oom_fd >= 0 ? 0 : -1;
}

#endif
2 changes: 2 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include <glib-unix.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __linux__
#include <linux/limits.h>
#endif

gboolean opt_version = FALSE;
gboolean opt_terminal = FALSE;
Expand Down
1 change: 0 additions & 1 deletion src/close_fds.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "close_fds.h"
#include "runtime_args.h"

#include <sys/prctl.h>
#include <sys/stat.h>

static int open_files_max_fd;
Expand Down
4 changes: 4 additions & 0 deletions src/cmsg.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
#error cmsg.c requires C99 or later
#endif

#ifdef __FreeBSD__
#define ECOMM EINVAL
#endif

#define error(s) \
do { \
fprintf(stderr, "nsenter: %s %s\n", s, strerror(errno)); \
Expand Down
22 changes: 10 additions & 12 deletions src/conmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
#include "seccomp_notify.h"
#include "runtime_args.h"

#include <sys/prctl.h>
#include <sys/signalfd.h>
#include <sys/stat.h>
#include <locale.h>

Expand Down Expand Up @@ -134,7 +132,7 @@ int main(int argc, char *argv[])
* Set self as subreaper so we can wait for container process
* and return its exit code.
*/
int ret = prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
int ret = set_subreaper(true);
if (ret != 0) {
pexit("Failed to set as subreaper");
}
Expand Down Expand Up @@ -228,7 +226,7 @@ int main(int argc, char *argv[])
if (create_pid < 0) {
pexit("Failed to fork the create command");
} else if (!create_pid) {
if (prctl(PR_SET_PDEATHSIG, SIGKILL) < 0)
if (set_pdeathsig(SIGKILL) < 0)
_pexit("Failed to set PDEATHSIG");
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
_pexit("Failed to unblock signals");
Expand All @@ -238,21 +236,21 @@ int main(int argc, char *argv[])
workerfd_stdin = dev_null_r;
if (dup2(workerfd_stdin, STDIN_FILENO) < 0)
_pexit("Failed to dup over stdin");
if (workerfd_stdin != dev_null_r && fchmod(STDIN_FILENO, 0777) < 0)
if (workerfd_stdin != dev_null_r && isatty(workerfd_stdin) && fchmod(STDIN_FILENO, 0777) < 0)
nwarn("Failed to chmod stdin");

if (workerfd_stdout < 0)
workerfd_stdout = dev_null_w;
if (dup2(workerfd_stdout, STDOUT_FILENO) < 0)
_pexit("Failed to dup over stdout");
if (workerfd_stdout != dev_null_w && fchmod(STDOUT_FILENO, 0777) < 0)
if (workerfd_stdout != dev_null_w && isatty(workerfd_stdout) && fchmod(STDOUT_FILENO, 0777) < 0)
nwarn("Failed to chmod stdout");

if (workerfd_stderr < 0)
workerfd_stderr = workerfd_stdout;
if (dup2(workerfd_stderr, STDERR_FILENO) < 0)
_pexit("Failed to dup over stderr");
if (workerfd_stderr != dev_null_w && fchmod(STDERR_FILENO, 0777) < 0)
if (workerfd_stderr != dev_null_w && isatty(workerfd_stderr) && fchmod(STDERR_FILENO, 0777) < 0)
nwarn("Failed to chmod stderr");
}
/* If LISTEN_PID env is set, we need to set the LISTEN_PID
Expand Down Expand Up @@ -314,11 +312,7 @@ int main(int argc, char *argv[])
.pid_to_handler = pid_to_handler,
.exit_status_cache = NULL,
};
sigset_t set;
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, NULL);
int signal_fd = signalfd(-1, &set, SFD_CLOEXEC);
int signal_fd = get_signal_descriptor(SIGCHLD);
if (signal_fd < 0)
pexit("Failed to create signalfd for SIGCHLD");
int signal_fd_tag = g_unix_fd_add(signal_fd, G_IO_IN, on_signalfd_cb, &data);
Expand Down Expand Up @@ -407,7 +401,9 @@ int main(int argc, char *argv[])
if ((opt_api_version >= 1 || !opt_exec) && sync_pipe_fd >= 0)
write_sync_fd(sync_pipe_fd, container_pid, NULL);

#ifdef __linux__
setup_oom_handling(container_pid);
#endif

if (mainfd_stdout >= 0) {
g_unix_fd_add(mainfd_stdout, G_IO_IN, stdio_cb, GINT_TO_POINTER(STDOUT_PIPE));
Expand Down Expand Up @@ -457,7 +453,9 @@ int main(int argc, char *argv[])
g_main_loop_run(main_loop);
}

#ifdef __linux__
check_cgroup2_oom();
#endif

/* Drain stdout and stderr only if a timeout doesn't occur */
if (!timed_out)
Expand Down
86 changes: 62 additions & 24 deletions src/conn_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,61 @@ char *setup_seccomp_socket(const char *socket)
return setup_socket(&seccomp_socket_fd, socket);
}

#ifdef __linux__
static void bind_relative_to_dir(int dir_fd, int sock_fd, const char *path)
{
struct sockaddr_un addr;

/*
* To be able to access the location of the attach socket, without first creating the attach socket
* but also be able to handle arbitrary length paths, we open the parent dir (base_path), and then use
* the corresponding entry in `/proc/self/fd` to act as the path to base_path, then we use the socket_relative_name
* to actually refer to the file where the socket will be created below.
*/
addr.sun_family = AF_UNIX;
if (dir_fd == -1) {
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
} else {
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "/proc/self/fd/%d/%s", dir_fd, path);
}
ndebugf("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path);

if (fchmod(sock_fd, 0700))
pexit("Failed to change console-socket permissions");
if (bind(sock_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
pexit("Failed to bind to console-socket");
}
#endif

#ifdef __FreeBSD__

// FreeBSD earlier than 13.1-RELEASE doesn't have O_PATH
#ifndef O_PATH
#define O_PATH 0
#endif

static void bind_relative_to_dir(int dir_fd, int sock_fd, const char *path)
{
struct sockaddr_un addr;

if (dir_fd == -1) {
dir_fd = AT_FDCWD;
}

addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
ndebugf("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path);
if (bindat(dir_fd, sock_fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
pexit("Failed to bind to console-socket");
if (fchmodat(dir_fd, addr.sun_path, 0700, AT_SYMLINK_NOFOLLOW))
pexit("Failed to change console-socket permissions");
}
#endif

static char *setup_socket(int *fd, const char *path)
{
struct sockaddr_un addr = {0};
char *csname = NULL;
char *bname = NULL;
_cleanup_close_ int sfd = -1;

if (path != NULL) {
Expand All @@ -114,8 +165,6 @@ static char *setup_socket(int *fd, const char *path)
bname = basename(bname_buf);
if (bname == NULL)
pexitf("Cannot get basename for %s", csname);

snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "/proc/self/fd/%d/%s", sfd, bname);
} else {
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();

Expand All @@ -132,20 +181,14 @@ static char *setup_socket(int *fd, const char *path)
if (unlink(csname) < 0)
pexit("Failed to unlink temporary random path");

strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);
bname = csname;
}

addr.sun_family = AF_UNIX;
ndebugf("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path);

/* Bind to the console socket path. */
*fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (*fd < 0)
pexit("Failed to create socket");
if (fchmod(*fd, 0700))
pexit("Failed to change console-socket permissions");
if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
pexit("Failed to bind to console-socket");
bind_relative_to_dir(sfd, *fd, bname);
if (listen(*fd, 128) < 0)
pexit("Failed to listen on console-socket");

Expand Down Expand Up @@ -186,16 +229,20 @@ void setup_notify_socket(char *socket_path)
g_free(symlink_dir_path);
}

static size_t max_socket_path_len()
{
struct sockaddr_un addr;
return sizeof(addr.sun_path);
}

/* REMEMBER to g_free() the return value! */
static char *bind_unix_socket(char *socket_relative_name, int sock_type, mode_t perms, struct remote_sock_s *remote_sock,
gboolean use_full_attach_path)
{
int socket_fd = -1;
struct sockaddr_un socket_addr = {0};
socket_addr.sun_family = AF_UNIX;

/* get the parent_dir of the socket. We'll use this to get the location of the socket. */
char *parent_dir = socket_parent_dir(use_full_attach_path, sizeof(socket_addr.sun_path));
char *parent_dir = socket_parent_dir(use_full_attach_path, max_socket_path_len());

/*
* To be able to access the location of the attach socket, without first creating the attach socket
Expand All @@ -207,11 +254,6 @@ static char *bind_unix_socket(char *socket_relative_name, int sock_type, mode_t
if (parent_dir_fd < 0)
pexitf("failed to open socket path parent dir %s", parent_dir);

_cleanup_free_ char *sock_proc_entry = g_strdup_printf("/proc/self/fd/%d/%s", parent_dir_fd, socket_relative_name);
strncpy(socket_addr.sun_path, sock_proc_entry, sizeof(socket_addr.sun_path) - 1);
ndebugf("addr{sun_family=AF_UNIX, sun_path=%s}", socket_addr.sun_path);


/*
* We use the fullpath for operations that aren't as limited in length as socket_addr.sun_path
* Cleanup of this variable is up to the caller
Expand All @@ -227,14 +269,10 @@ static char *bind_unix_socket(char *socket_relative_name, int sock_type, mode_t
if (socket_fd == -1)
pexitf("Failed to create socket %s", sock_fullpath);

if (fchmod(socket_fd, perms))
pexitf("Failed to change socket permissions %s", sock_fullpath);

if (unlink(sock_fullpath) == -1 && errno != ENOENT)
pexitf("Failed to remove existing socket: %s", sock_fullpath);

if (bind(socket_fd, (struct sockaddr *)&socket_addr, sizeof(struct sockaddr_un)) == -1)
pexitf("Failed to bind socket: %s", sock_fullpath);
bind_relative_to_dir(parent_dir_fd, socket_fd, socket_relative_name);

if (chmod(sock_fullpath, perms))
pexitf("Failed to change socket permissions %s", sock_fullpath);
Expand Down
10 changes: 3 additions & 7 deletions src/ctr_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
#include <glib-unix.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/signalfd.h>
#include <sys/prctl.h>
#include <unistd.h>

volatile pid_t container_pid = -1;
Expand Down Expand Up @@ -84,10 +82,8 @@ gboolean on_signalfd_cb(gint fd, G_GNUC_UNUSED GIOCondition condition, gpointer
struct pid_check_data *data = (struct pid_check_data *)user_data;

/* dequeue the signal from the signalfd */
struct signalfd_siginfo siginfo;
ssize_t s = read(fd, &siginfo, sizeof siginfo);
g_assert_cmpint(s, ==, sizeof siginfo);
g_assert_cmpint(siginfo.ssi_signo, ==, SIGCHLD);
int sig = dequeue_signal_event(fd);
g_assert_cmpint(sig, ==, SIGCHLD);

check_child_processes(data->pid_to_handler, data->exit_status_cache);
return G_SOURCE_CONTINUE;
Expand Down Expand Up @@ -154,7 +150,7 @@ void do_exit_command()
* Unfortunately, that also means that any new subchildren from
* still running processes could also get lost
*/
if (prctl(PR_SET_CHILD_SUBREAPER, 0) != 0) {
if (set_subreaper(false) != 0) {
nwarn("Failed to disable self subreaper attribute - might wait for indirect children a long time");
}

Expand Down
4 changes: 4 additions & 0 deletions src/oom.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

void attempt_oom_adjust(const char *const oom_score)
{
#ifdef __linux__
int oom_score_fd = open("/proc/self/oom_score_adj", O_WRONLY);
if (oom_score_fd < 0) {
ndebugf("failed to open /proc/self/oom_score_adj: %s\n", strerror(errno));
Expand All @@ -16,4 +17,7 @@ void attempt_oom_adjust(const char *const oom_score)
ndebugf("failed to write to /proc/self/oom_score_adj: %s\n", strerror(errno));
}
close(oom_score_fd);
#else
(void)oom_score;
#endif
}
11 changes: 7 additions & 4 deletions src/seccomp_notify.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@
#endif

#include <errno.h>
#include <seccomp.h>
#include <sys/ioctl.h>
#include <linux/seccomp.h>
#include <sys/sysmacros.h>
#include <dlfcn.h>
#include <sys/wait.h>
#include <sys/mount.h>
Expand All @@ -19,10 +16,16 @@
#include "cli.h" // opt_bundle_path
#include "utils.h"
#include "cmsg.h"
#include "seccomp_notify.h"

#ifdef USE_SECCOMP

#include <sys/sysmacros.h>
#include <linux/seccomp.h>
#include <seccomp.h>

#include "seccomp_notify.h"


#ifndef SECCOMP_USER_NOTIF_FLAG_CONTINUE
#define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0)
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/seccomp_notify_plugin.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#ifndef SECCOMP_NOTIFY_PLUGIN_H

#include <linux/seccomp.h>

#ifdef USE_SECCOMP

#include <linux/seccomp.h>

struct seccomp_notify_conf_s {
const char *runtime_root_path;
const char *name;
Expand Down
Loading

0 comments on commit daeaf97

Please sign in to comment.