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 <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Apr 26, 2021
1 parent 372fa19 commit e577f9f
Show file tree
Hide file tree
Showing 16 changed files with 463 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .cirrus.yml
Expand Up @@ -68,7 +68,7 @@ fedora_packaging_task:
memory: 4

script:
- dnf install -y make glib2-devel git gcc rpm-build golang
- dnf install -y make glib2-devel git gcc rpm-build golang libseccomp-devel
- cd $CIRRUS_WORKING_DIR
- make
- make -f .rpmbuild/Makefile
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Expand Up @@ -6,7 +6,8 @@ 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 src/close_fds.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/close_fds.o src/seccomp_notify.o

MAKEFILE_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))

Expand Down Expand Up @@ -45,6 +46,11 @@ else ifeq ($(shell $(PKG_CONFIG) --exists libsystemd && echo "0" || echo "1"), 0
override CFLAGS += $(shell $(PKG_CONFIG) --cflags libsystemd) -D USE_JOURNALD=0
endif

ifeq ($(shell $(PKG_CONFIG) --exists libseccomp && echo "0" || echo "1"), 0)
override LIBS += $(shell $(PKG_CONFIG) --libs libseccomp) -ldl
override CFLAGS += $(shell $(PKG_CONFIG) --cflags libseccomp)
endif

# Update nix/nixpkgs.json its latest stable commit
.PHONY: nixpkgs
nixpkgs:
Expand Down
1 change: 1 addition & 0 deletions contrib/spec/conmon.spec.in
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
# If go_compiler is not set to 1, there is no virtual provide. Use golang instead.
BuildRequires: golang
Expand Down
7 changes: 5 additions & 2 deletions meson.build
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 @@ -67,8 +68,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
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 gitMinimal pcre pkg-config which ];
buildInputs = [ glibc glibc.static glib ];
buildInputs = [ glibc glibc.static glib libseccomp ];
prePatch = ''
export CFLAGS='-static -pthread'
export LDFLAGS='-s -w -static-libgcc -static'
Expand Down
9 changes: 9 additions & 0 deletions src/cli.c
Expand Up @@ -50,6 +50,8 @@ gboolean opt_sync = FALSE;
gboolean opt_no_sync_log = FALSE;
char *opt_sdnotify_socket = NULL;
gboolean opt_full_attach_path = FALSE;
char *opt_seccomp_notify_socket = NULL;
char *opt_seccomp_notify_plugins = NULL;
GOptionEntry opt_entries[] = {
{"api-version", 0, 0, G_OPTION_ARG_NONE, &opt_api_version, "Conmon API version to use", NULL},
{"bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Location of the OCI Bundle path", NULL},
Expand Down Expand Up @@ -100,6 +102,10 @@ GOptionEntry opt_entries[] = {
{"version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print the version and exit", NULL},
{"full-attach", 0, 0, G_OPTION_ARG_NONE, &opt_full_attach_path,
"Don't truncate the path to the attach socket. This option causes conmon to ignore --socket-dir-path", NULL},
{"seccomp-notify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_socket,
"Path to the socket where the seccomp notification fd is received", 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 @@ -150,6 +156,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
2 changes: 2 additions & 0 deletions src/cli.h
Expand Up @@ -43,6 +43,8 @@ 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_socket;
extern char *opt_seccomp_notify_plugins;
extern GOptionEntry opt_entries[];
extern gboolean opt_full_attach_path;

Expand Down
13 changes: 13 additions & 0 deletions src/conmon.c
Expand Up @@ -18,6 +18,7 @@
#include "parent_pipe_fd.h"
#include "ctr_exit.h"
#include "close_fds.h"
#include "seccomp_notify.h"
#include "runtime_args.h"

#include <sys/prctl.h>
Expand Down Expand Up @@ -131,6 +132,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 @@ -173,6 +175,12 @@ int main(int argc, char *argv[])
g_unix_fd_add(winsz_fd_r, G_IO_IN, ctrl_winsz_cb, NULL);
}

if (opt_seccomp_notify_socket != NULL) {
if (opt_seccomp_notify_plugins == NULL)
pexit("seccomp notify socket specified without any plugin");
seccomp_listener = setup_seccomp_socket(opt_seccomp_notify_socket);
}

/* 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 @@ -315,6 +323,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 Expand Up @@ -488,6 +499,8 @@ int main(int argc, char *argv[])
if (!g_file_set_contents(exit_file_path, status_str, -1, &err))
nexitf("Failed to write %s to exit file: %s", status_str, err->message);
}
if (seccomp_listener != NULL)
unlink(seccomp_listener);

/* Send the command exec exit code back to the parent */
if (opt_exec && sync_pipe_fd >= 0)
Expand Down
82 changes: 62 additions & 20 deletions src/conn_sock.c
Expand Up @@ -25,6 +25,7 @@ static gboolean local_sock_write_cb(G_GNUC_UNUSED int fd, G_GNUC_UNUSED GIOCondi
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);
static char *socket_parent_dir(gboolean use_full_attach_path, size_t desired_len);
static char *setup_socket(int *fd, const char *path);
/*
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 @@ -72,38 +73,79 @@ struct remote_sock_s remote_notify_sock = {
};

/* External */

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

char *setup_seccomp_socket(const char *socket)
{
return setup_socket(&seccomp_socket_fd, socket);
}
#include <libgen.h>

static char *setup_socket(int *fd, const char *path)
{
struct sockaddr_un addr = {0};
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();
char *csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL);
/*
* Generate a temporary name. Is this unsafe? Probably, but we can
* replace it with a rename(2) setup if necessary.
*/
char *csname = NULL;
_cleanup_close_ int sfd = -1;
_cleanup_free_ char *dname_buf = NULL;
_cleanup_free_ char *bname_buf = NULL;
char *dname = NULL, *bname = NULL;

if (path != NULL) {
csname = strdup(path);
dname_buf = strdup(path);
bname_buf = strdup(path);
if (csname == NULL || dname_buf == NULL || bname_buf == NULL) {
pexit("Failed to allocate memory");
return NULL;
}
dname = dirname(dname_buf);
if (dname == NULL)
pexitf("Cannot get dirname for %s", csname);

int unusedfd = g_mkstemp(csname);
if (unusedfd < 0)
pexit("Failed to generate random path for console-socket");
close(unusedfd);
sfd = open(dname, O_CREAT|O_PATH, 0600);
if (sfd < 0)
pexit("Failed to create file for console-socket");

bname = basename(bname_buf);
if (bname == NULL)
pexitf("Cannot get basename for %s", csname);
} else {
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();

csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL);
/*
* Generate a temporary name. Is this unsafe? Probably, but we can
* replace it with a rename(2) setup if necessary.
*/
sfd = g_mkstemp(csname);
if (sfd < 0)
pexit("Failed to generate random path for console-socket");
/* XXX: This should be handled with a rename(2). */
if (unlink(csname) < 0)
pexit("Failed to unlink temporary random path");
}

addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);
if (bname)
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "/proc/self/fd/%d/%s", sfd, bname);
else
strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);

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 csname;
Expand Down
1 change: 1 addition & 0 deletions src/conn_sock.h
Expand Up @@ -48,6 +48,7 @@ struct local_sock_s {
};

char *setup_console_socket(void);
char *setup_seccomp_socket(const char *socket);
char *setup_attach_socket(void);
void setup_notify_socket(char *);
void schedule_main_stdin_write();
Expand Down
1 change: 1 addition & 0 deletions src/ctrl.c
Expand Up @@ -8,6 +8,7 @@
#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>
Expand Down
1 change: 1 addition & 0 deletions src/globals.c
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
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

0 comments on commit e577f9f

Please sign in to comment.