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

seccomp: add support for seccomp notify #190

Merged
merged 2 commits into from
Jun 2, 2021
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 .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ fedora_packaging_task:
image: "${PRIOR_FEDORA_CONTAINER_FQIN}"

script:
- dnf install -y rpm-build golang
- dnf install -y rpm-build golang libseccomp-devel
- cd $CIRRUS_WORKING_DIR
- make
- make -f .rpmbuild/Makefile
Expand Down Expand Up @@ -123,7 +123,7 @@ static_binary_task:
# the next line and file an issue with details about the failure.
# allow_failures: true

timeout_in: '20m'
timeout_in: '120m'

gce_instance:
image_name: "${FEDORA_CACHE_IMAGE_NAME}"
Expand Down
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
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,13 @@ 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) -D USE_SECCOMP=1
else
override CFLAGS += -D USE_SECCOMP=0
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
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
# 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
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 @@ -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-arm64.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,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 @@ -77,7 +78,7 @@ let
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
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 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
16 changes: 16 additions & 0 deletions src/conmon.c
Original file line number Diff line number Diff line change
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 @@ -133,6 +134,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 @@ -175,6 +177,15 @@ 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 !USE_SECCOMP
pexit("seccomp support not present");
#endif
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 @@ -317,6 +328,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 @@ -490,6 +504,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
85 changes: 64 additions & 21 deletions src/conn_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "config.h"
#include "cli.h" // opt_stdin

#include <libgen.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <unistd.h>
Expand All @@ -25,6 +26,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 +74,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);
}

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;

if (path != NULL) {
_cleanup_free_ char *dname_buf = NULL;
_cleanup_free_ char *bname_buf = NULL;
char *dname = NULL, *bname = 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");

addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);
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();

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.
*/
int unusedfd = g_mkstemp(csname);
if (unusedfd < 0)
pexit("Failed to generate random path for console-socket");
close(unusedfd);
/* XXX: This should be handled with a rename(2). */
if (unlink(csname) < 0)
pexit("Failed to unlink temporary random path");

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

addr.sun_family = AF_UNIX;
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
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(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
Original file line number Diff line number Diff line change
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
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