Skip to content

Commit

Permalink
seccomp: add support for seccomp notify
Browse files Browse the repository at this point in the history
add support for seccomp notify and add a basic support for emulating
mknod and mknodat.  The handler implementation is likely going to
change, for now it is just a PoC to show how it would work.

Requires: containers/crun#438
Requires: libseccomp-2.5

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Sep 28, 2020
1 parent 59c2817 commit 8dc536c
Show file tree
Hide file tree
Showing 17 changed files with 404 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ fedora_packaging_task:
memory: 12

script:
- dnf install -y make glib2-devel git gcc rpm-build
- dnf install -y make libseccomp-devel glib2-devel git gcc rpm-build
- cd $CIRRUS_WORKING_DIR
- make
- make -f .rpmbuild/Makefile
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ GO ?= go
PROJECT := github.com/containers/conmon
PKG_CONFIG ?= pkg-config
HEADERS := $(wildcard src/*.h)
OBJS := src/conmon.o src/cmsg.o src/ctr_logging.o src/utils.o src/cli.o src/globals.o src/cgroup.o src/conn_sock.o src/oom.o src/ctrl.o src/ctr_stdio.o src/parent_pipe_fd.o src/ctr_exit.o src/runtime_args.o
OBJS := src/conmon.o src/cmsg.o src/ctr_logging.o src/utils.o src/cli.o src/globals.o src/cgroup.o src/conn_sock.o src/oom.o src/ctrl.o src/ctr_stdio.o src/parent_pipe_fd.o src/ctr_exit.o src/runtime_args.o src/seccomp_notify.o
DEBUGTAG ?=
ifneq (,$(findstring enable_debug,$(DEBUGTAG)))
DEBUGFLAG=-g
Expand All @@ -30,7 +30,7 @@ else
$(eval GIT_BRANCH_CLEAN := unknown)
endif

override LIBS += $(shell $(PKG_CONFIG) --libs glib-2.0)
override LIBS += $(shell $(PKG_CONFIG) --libs glib-2.0) -ldl

CFLAGS ?= -std=c99 -Os -Wall -Wextra -Werror
override CFLAGS += $(shell $(PKG_CONFIG) --cflags glib-2.0) -DVERSION=\"$(VERSION)\" -DGIT_COMMIT=\"$(GIT_COMMIT)\"
Expand Down
1 change: 1 addition & 0 deletions contrib/spec/conmon.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64
BuildRequires: gcc
BuildRequires: glib2-devel
BuildRequires: glibc-devel
BuildRequires: libseccomp-devel
BuildRequires: git
BuildRequires: pkgconfig

Expand Down
7 changes: 5 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ add_project_arguments('-Os', '-Wall', '-Werror',
language : 'c')

glib = dependency('glib-2.0')
libdl = cc.find_library('dl')

executable('conmon',
['src/conmon.c',
Expand Down Expand Up @@ -65,8 +66,10 @@ executable('conmon',
'src/runtime_args.c',
'src/runtime_args.h',
'src/utils.c',
'src/utils.h'],
dependencies : [glib],
'src/utils.h',
'src/seccomp_notify.c',
'src/seccomp_notify.h'],
dependencies : [glib, libdl],
install : true,
install_dir : join_paths(get_option('libexecdir'), 'podman'),
)
Expand Down
3 changes: 2 additions & 1 deletion nix/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ let
autogen = (static pkg.autogen);
e2fsprogs = (static pkg.e2fsprogs);
libuv = (static pkg.libuv);
libseccomp = (static pkg.libseccomp);
glib = (static pkg.glib).overrideAttrs(x: {
outputs = [ "bin" "out" "dev" ];
mesonFlags = [
Expand Down Expand Up @@ -60,7 +61,7 @@ let
enableParallelBuilding = true;
outputs = [ "out" ];
nativeBuildInputs = [ bash git pcre pkg-config which ];
buildInputs = [ glibc glibc.static glib ];
buildInputs = [ glibc glibc.static glib libseccomp ];
prePatch = ''
export CFLAGS='-static'
export LDFLAGS='-s -w -static-libgcc -static'
Expand Down
6 changes: 6 additions & 0 deletions src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ char *opt_log_tag = NULL;
gboolean opt_sync = FALSE;
gboolean opt_no_sync_log = FALSE;
char *opt_sdnotify_socket = NULL;
char *opt_seccomp_notify_plugins = NULL;
GOptionEntry opt_entries[] = {
{"terminal", 't', 0, G_OPTION_ARG_NONE, &opt_terminal, "Terminal", NULL},
{"stdin", 'i', 0, G_OPTION_ARG_NONE, &opt_stdin, "Stdin", NULL},
Expand Down Expand Up @@ -97,6 +98,8 @@ GOptionEntry opt_entries[] = {
NULL},
{"sdnotify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_sdnotify_socket, "Path to the host's sd-notify socket to relay messages to",
NULL},
{"seccomp-notify-plugins", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_plugins,
"Plugins to use for managing the seccomp notifications", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL}};


Expand Down Expand Up @@ -143,6 +146,9 @@ void process_cli()
if (opt_cuuid == NULL && (!opt_exec || opt_api_version >= 1))
nexit("Container UUID not provided. Use --cuuid");

if (opt_seccomp_notify_plugins == NULL)
opt_seccomp_notify_plugins = getenv("CONMON_SECCOMP_NOTIFY_PLUGINS");

if (opt_runtime_path == NULL)
nexit("Runtime path not provided. Use --runtime");
if (access(opt_runtime_path, X_OK) < 0)
Expand Down
1 change: 1 addition & 0 deletions src/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ extern char *opt_log_tag;
extern gboolean opt_no_sync_log;
extern gboolean opt_sync;
extern char *opt_sdnotify_socket;
extern char *opt_seccomp_notify_plugins;
extern GOptionEntry opt_entries[];

int initialize_cli(int argc, char *argv[]);
Expand Down
9 changes: 9 additions & 0 deletions src/conmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ int main(int argc, char *argv[])
}

_cleanup_free_ char *csname = NULL;
_cleanup_free_ char *seccomp_listener = NULL;
int workerfd_stdin = -1;
int workerfd_stdout = -1;
int workerfd_stderr = -1;
Expand Down Expand Up @@ -170,6 +171,11 @@ int main(int argc, char *argv[])
g_unix_fd_add(winsz_fd_r, G_IO_IN, ctrl_winsz_cb, NULL);
}

if (opt_seccomp_notify_plugins != NULL) {
seccomp_listener = setup_seccomp_socket();
setenv("RUN_OCI_SECCOMP_RECEIVER", seccomp_listener, 1);
}

/* We always create a stderr pipe, because that way we can capture
runc stderr messages before the tty is created */
if (pipe2(fds, O_CLOEXEC) < 0)
Expand Down Expand Up @@ -312,6 +318,9 @@ int main(int argc, char *argv[])
if (workerfd_stderr > -1)
close(workerfd_stderr);

if (seccomp_listener != NULL)
g_unix_fd_add(seccomp_socket_fd, G_IO_IN, seccomp_accept_cb, csname);

if (csname != NULL) {
g_unix_fd_add(console_socket_fd, G_IO_IN, terminal_accept_cb, csname);
/* Process any SIGCHLD we may have missed before the signal handler was in place. */
Expand Down
32 changes: 24 additions & 8 deletions src/conn_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ static void sock_try_write_to_local_sock(struct remote_sock_s *sock);
static gboolean local_sock_write_cb(G_GNUC_UNUSED int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
static char *bind_unix_socket(char *socket_relative_name, int sock_type, mode_t perms, struct remote_sock_s *remote_sock,
gboolean do_chdir);
static char *setup_socket(int *fd);

/*
Since our socket handling is abstract now, handling is based on sock_type, so we can pass around a structure
that contains everything we need to handle I/O. Callbacks used to handle IO, for example, and whether this
Expand Down Expand Up @@ -71,11 +73,25 @@ struct remote_sock_s remote_notify_sock = {
};

/* External */

char *setup_console_socket(void)
{
return setup_socket(&console_socket_fd);
}

char *setup_seccomp_socket(void)
{
return setup_socket(&seccomp_socket_fd);
}

static char *setup_socket(int *fd)
{
struct sockaddr_un addr = {0};
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();
_cleanup_free_ char *csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL);
const char *tmpdir = NULL;
_cleanup_free_ char *csname = NULL;

tmpdir = g_get_tmp_dir();
csname = g_build_filename(tmpdir, "conmon.XXXXXX", NULL);
/*
* Generate a temporary name. Is this unsafe? Probably, but we can
* replace it with a rename(2) setup if necessary.
Expand All @@ -92,17 +108,17 @@ char *setup_console_socket(void)
ninfof("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path);

/* Bind to the console socket path. */
console_socket_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (console_socket_fd < 0)
pexit("Failed to create console-socket");
if (fchmod(console_socket_fd, 0700))
*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");
/* XXX: This should be handled with a rename(2). */
if (unlink(csname) < 0)
pexit("Failed to unlink temporary random path");
if (bind(console_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
pexit("Failed to bind to console-socket");
if (listen(console_socket_fd, 128) < 0)
if (listen(*fd, 128) < 0)
pexit("Failed to listen on console-socket");

return g_strdup(csname);
Expand Down
1 change: 1 addition & 0 deletions src/conn_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct local_sock_s {
};

char *setup_console_socket(void);
char *setup_seccomp_socket(void);
char *setup_attach_socket(void);
void setup_notify_socket(char *);
void schedule_main_stdin_write();
Expand Down
67 changes: 67 additions & 0 deletions src/ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,85 @@
#include "conn_sock.h"
#include "cmsg.h"
#include "cli.h" // opt_bundle_path
#include "seccomp_notify.h"

#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <termios.h>

#include <seccomp.h>
#include <linux/seccomp.h>
#include <sys/sysmacros.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <signal.h>

static struct seccomp_notify_context_s *seccomp_notify_ctx;

static void resize_winsz(int height, int width);
static gboolean read_from_ctrl_buffer(int fd, gboolean (*line_process_func)(char *));
static gboolean process_terminal_ctrl_line(char *line);
static gboolean process_winsz_ctrl_line(char *line);
static void setup_fifo(int *fifo_r, int *fifo_w, char *filename, char *error_var_name);

static void cleanup_seccomp_plugins()
{
if (seccomp_notify_ctx) {
seccomp_notify_plugins_free(seccomp_notify_ctx);
seccomp_notify_ctx = NULL;
}
}

gboolean seccomp_accept_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data)
{
ninfof("about to accept from seccomp_socket_fd: %d", fd);
int connfd = accept4(fd, NULL, NULL, SOCK_CLOEXEC);
if (connfd < 0) {
nwarn("Failed to accept console-socket connection");
return G_SOURCE_CONTINUE;
}

struct file_t listener = recvfd(connfd);
close(connfd);

_cleanup_free_ char *oci_config_path = g_strdup_printf("%s/config.json", opt_bundle_path);
if (oci_config_path == NULL) {
nwarn("Failed to strdup");
return G_SOURCE_CONTINUE;
}

struct seccomp_notify_conf_s conf = {
.runtime_root_path = NULL,
.name = opt_name,
.bundle_path = opt_bundle_path,
.oci_config_path = oci_config_path,
};
int ret = seccomp_notify_plugins_load(&seccomp_notify_ctx, opt_seccomp_notify_plugins, &conf);
if (ret < 0) {
nwarn("Failed to initialize seccomp notify plugins");
return G_SOURCE_CONTINUE;
}


g_unix_fd_add(listener.fd, G_IO_IN | G_IO_HUP, seccomp_cb, NULL);
atexit(cleanup_seccomp_plugins);

return G_SOURCE_CONTINUE;
}

gboolean seccomp_cb(int fd, GIOCondition condition, G_GNUC_UNUSED gpointer user_data)
{
if (condition & G_IO_IN) {
if (seccomp_notify_ctx == NULL)
return G_SOURCE_REMOVE;

int ret = seccomp_notify_plugins_event(seccomp_notify_ctx, fd);
return ret == 0 ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE;
}
return G_SOURCE_CONTINUE;
}

gboolean terminal_accept_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data)
{

Expand Down
2 changes: 2 additions & 0 deletions src/ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

#include <glib.h> /* gpointer */

gboolean seccomp_accept_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
gboolean terminal_accept_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
gboolean ctrl_winsz_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
gboolean seccomp_cb(int fd, GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
gboolean ctrl_cb(int fd, G_GNUC_UNUSED GIOCondition condition, G_GNUC_UNUSED gpointer user_data);
void setup_console_fifo();
int setup_terminal_control_fifo();
Expand Down
1 change: 1 addition & 0 deletions src/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ int mainfd_stderr = -1;

int attach_socket_fd = -1;
int console_socket_fd = -1;
int seccomp_socket_fd = -1;
int terminal_ctrl_fd = -1;
int inotify_fd = -1;
int winsz_fd_w = -1;
Expand Down
1 change: 1 addition & 0 deletions src/globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ extern int mainfd_stderr;

extern int attach_socket_fd;
extern int console_socket_fd;
extern int seccomp_socket_fd;
extern int terminal_ctrl_fd;
extern int inotify_fd;
extern int winsz_fd_w;
Expand Down
Loading

0 comments on commit 8dc536c

Please sign in to comment.