Skip to content

Commit f48ddb5

Browse files
committed
seccomp: add support for seccomp notify
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]>
1 parent 77dfb4b commit f48ddb5

17 files changed

+501
-26
lines changed

.cirrus.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ fedora_packaging_task:
7373
image: "${PRIOR_FEDORA_CONTAINER_FQIN}"
7474

7575
script:
76-
- dnf install -y rpm-build golang
76+
- dnf install -y rpm-build golang libseccomp-devel
7777
- cd $CIRRUS_WORKING_DIR
7878
- make
7979
- make -f .rpmbuild/Makefile

Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ GO ?= go
66
PROJECT := github.com/containers/conmon
77
PKG_CONFIG ?= pkg-config
88
HEADERS := $(wildcard src/*.h)
9-
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
9+
10+
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
1011

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

@@ -45,6 +46,13 @@ else ifeq ($(shell $(PKG_CONFIG) --exists libsystemd && echo "0" || echo "1"), 0
4546
override CFLAGS += $(shell $(PKG_CONFIG) --cflags libsystemd) -D USE_JOURNALD=0
4647
endif
4748

49+
ifeq ($(shell $(PKG_CONFIG) --exists libseccomp && echo "0" || echo "1"), 0)
50+
override LIBS += $(shell $(PKG_CONFIG) --libs libseccomp) -ldl
51+
override CFLAGS += $(shell $(PKG_CONFIG) --cflags libseccomp) -D USE_SECCOMP=1
52+
else
53+
override CFLAGS += -D USE_SECCOMP=0
54+
endif
55+
4856
# Update nix/nixpkgs.json its latest stable commit
4957
.PHONY: nixpkgs
5058
nixpkgs:

contrib/spec/conmon.spec.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64
2222
BuildRequires: gcc
2323
BuildRequires: glib2-devel
2424
BuildRequires: glibc-devel
25+
BuildRequires: libseccomp-devel
2526
BuildRequires: git
2627
# If go_compiler is not set to 1, there is no virtual provide. Use golang instead.
2728
BuildRequires: golang

meson.build

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ add_project_arguments('-Os', '-Wall', '-Werror',
3434
language : 'c')
3535

3636
glib = dependency('glib-2.0')
37+
libdl = cc.find_library('dl')
3738

3839
executable('conmon',
3940
['src/conmon.c',
@@ -67,8 +68,10 @@ executable('conmon',
6768
'src/runtime_args.c',
6869
'src/runtime_args.h',
6970
'src/utils.c',
70-
'src/utils.h'],
71-
dependencies : [glib],
71+
'src/utils.h',
72+
'src/seccomp_notify.c',
73+
'src/seccomp_notify.h'],
74+
dependencies : [glib, libdl],
7275
install : true,
7376
install_dir : join_paths(get_option('libexecdir'), 'podman'),
7477
)

nix/default-arm64.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ let
1717
autogen = (static pkg.autogen);
1818
e2fsprogs = (static pkg.e2fsprogs);
1919
libuv = (static pkg.libuv);
20+
libseccomp = (static pkg.libseccomp);
2021
glib = (static pkg.glib).overrideAttrs (x: {
2122
outputs = [ "bin" "out" "dev" ];
2223
mesonFlags = [
@@ -77,7 +78,7 @@ let
7778
pkg-config
7879
which
7980
];
80-
buildInputs = [ glibc glibc.static glib ];
81+
buildInputs = [ glibc glibc.static glib libseccomp ];
8182
prePatch = ''
8283
export CFLAGS='-static -pthread'
8384
export LDFLAGS='-s -w -static-libgcc -static'

nix/default.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ let
1313
autogen = (static pkg.autogen);
1414
e2fsprogs = (static pkg.e2fsprogs);
1515
libuv = (static pkg.libuv);
16+
libseccomp = (static pkg.libseccomp);
1617
glib = (static pkg.glib).overrideAttrs(x: {
1718
outputs = [ "bin" "out" "dev" ];
1819
mesonFlags = [
@@ -60,7 +61,7 @@ let
6061
enableParallelBuilding = true;
6162
outputs = [ "out" ];
6263
nativeBuildInputs = [ bash gitMinimal pcre pkg-config which ];
63-
buildInputs = [ glibc glibc.static glib ];
64+
buildInputs = [ glibc glibc.static glib libseccomp ];
6465
prePatch = ''
6566
export CFLAGS='-static -pthread'
6667
export LDFLAGS='-s -w -static-libgcc -static'

src/cli.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ gboolean opt_sync = FALSE;
5050
gboolean opt_no_sync_log = FALSE;
5151
char *opt_sdnotify_socket = NULL;
5252
gboolean opt_full_attach_path = FALSE;
53+
char *opt_seccomp_notify_socket = NULL;
54+
char *opt_seccomp_notify_plugins = NULL;
5355
GOptionEntry opt_entries[] = {
5456
{"api-version", 0, 0, G_OPTION_ARG_NONE, &opt_api_version, "Conmon API version to use", NULL},
5557
{"bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Location of the OCI Bundle path", NULL},
@@ -100,6 +102,10 @@ GOptionEntry opt_entries[] = {
100102
{"version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print the version and exit", NULL},
101103
{"full-attach", 0, 0, G_OPTION_ARG_NONE, &opt_full_attach_path,
102104
"Don't truncate the path to the attach socket. This option causes conmon to ignore --socket-dir-path", NULL},
105+
{"seccomp-notify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_socket,
106+
"Path to the socket where the seccomp notification fd is received", NULL},
107+
{"seccomp-notify-plugins", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_plugins,
108+
"Plugins to use for managing the seccomp notifications", NULL},
103109
{NULL, 0, 0, 0, NULL, NULL, NULL}};
104110

105111

@@ -150,6 +156,9 @@ void process_cli()
150156
if (opt_cuuid == NULL && (!opt_exec || opt_api_version >= 1))
151157
nexit("Container UUID not provided. Use --cuuid");
152158

159+
if (opt_seccomp_notify_plugins == NULL)
160+
opt_seccomp_notify_plugins = getenv("CONMON_SECCOMP_NOTIFY_PLUGINS");
161+
153162
if (opt_runtime_path == NULL)
154163
nexit("Runtime path not provided. Use --runtime");
155164
if (access(opt_runtime_path, X_OK) < 0)

src/cli.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ extern char *opt_log_tag;
4343
extern gboolean opt_no_sync_log;
4444
extern gboolean opt_sync;
4545
extern char *opt_sdnotify_socket;
46+
extern char *opt_seccomp_notify_socket;
47+
extern char *opt_seccomp_notify_plugins;
4648
extern GOptionEntry opt_entries[];
4749
extern gboolean opt_full_attach_path;
4850

src/conmon.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "parent_pipe_fd.h"
1919
#include "ctr_exit.h"
2020
#include "close_fds.h"
21+
#include "seccomp_notify.h"
2122
#include "runtime_args.h"
2223

2324
#include <sys/prctl.h>
@@ -133,6 +134,7 @@ int main(int argc, char *argv[])
133134
}
134135

135136
_cleanup_free_ char *csname = NULL;
137+
_cleanup_free_ char *seccomp_listener = NULL;
136138
int workerfd_stdin = -1;
137139
int workerfd_stdout = -1;
138140
int workerfd_stderr = -1;
@@ -175,6 +177,15 @@ int main(int argc, char *argv[])
175177
g_unix_fd_add(winsz_fd_r, G_IO_IN, ctrl_winsz_cb, NULL);
176178
}
177179

180+
if (opt_seccomp_notify_socket != NULL) {
181+
#if !USE_SECCOMP
182+
pexit("seccomp support not present");
183+
#endif
184+
if (opt_seccomp_notify_plugins == NULL)
185+
pexit("seccomp notify socket specified without any plugin");
186+
seccomp_listener = setup_seccomp_socket(opt_seccomp_notify_socket);
187+
}
188+
178189
/* We always create a stderr pipe, because that way we can capture
179190
runc stderr messages before the tty is created */
180191
if (pipe2(fds, O_CLOEXEC) < 0)
@@ -317,6 +328,9 @@ int main(int argc, char *argv[])
317328
if (workerfd_stderr > -1)
318329
close(workerfd_stderr);
319330

331+
if (seccomp_listener != NULL)
332+
g_unix_fd_add(seccomp_socket_fd, G_IO_IN, seccomp_accept_cb, csname);
333+
320334
if (csname != NULL) {
321335
g_unix_fd_add(console_socket_fd, G_IO_IN, terminal_accept_cb, csname);
322336
/* Process any SIGCHLD we may have missed before the signal handler was in place. */
@@ -490,6 +504,8 @@ int main(int argc, char *argv[])
490504
if (!g_file_set_contents(exit_file_path, status_str, -1, &err))
491505
nexitf("Failed to write %s to exit file: %s", status_str, err->message);
492506
}
507+
if (seccomp_listener != NULL)
508+
unlink(seccomp_listener);
493509

494510
/* Send the command exec exit code back to the parent */
495511
if (opt_exec && sync_pipe_fd >= 0)

src/conn_sock.c

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "config.h"
77
#include "cli.h" // opt_stdin
88

9+
#include <libgen.h>
910
#include <stdbool.h>
1011
#include <sys/socket.h>
1112
#include <unistd.h>
@@ -25,6 +26,7 @@ static gboolean local_sock_write_cb(G_GNUC_UNUSED int fd, G_GNUC_UNUSED GIOCondi
2526
static char *bind_unix_socket(char *socket_relative_name, int sock_type, mode_t perms, struct remote_sock_s *remote_sock,
2627
gboolean use_full_attach_path);
2728
static char *socket_parent_dir(gboolean use_full_attach_path, size_t desired_len);
29+
static char *setup_socket(int *fd, const char *path);
2830
/*
2931
Since our socket handling is abstract now, handling is based on sock_type, so we can pass around a structure
3032
that contains everything we need to handle I/O. Callbacks used to handle IO, for example, and whether this
@@ -72,38 +74,80 @@ struct remote_sock_s remote_notify_sock = {
7274
};
7375

7476
/* External */
77+
7578
char *setup_console_socket(void)
79+
{
80+
return setup_socket(&console_socket_fd, NULL);
81+
}
82+
83+
char *setup_seccomp_socket(const char *socket)
84+
{
85+
return setup_socket(&seccomp_socket_fd, socket);
86+
}
87+
88+
static char *setup_socket(int *fd, const char *path)
7689
{
7790
struct sockaddr_un addr = {0};
78-
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();
79-
char *csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL);
80-
/*
81-
* Generate a temporary name. Is this unsafe? Probably, but we can
82-
* replace it with a rename(2) setup if necessary.
83-
*/
91+
char *csname = NULL;
92+
_cleanup_close_ int sfd = -1;
93+
_cleanup_free_ char *dname_buf = NULL;
94+
_cleanup_free_ char *bname_buf = NULL;
95+
char *dname = NULL, *bname = NULL;
96+
97+
if (path != NULL) {
98+
csname = strdup(path);
99+
dname_buf = strdup(path);
100+
bname_buf = strdup(path);
101+
if (csname == NULL || dname_buf == NULL || bname_buf == NULL) {
102+
pexit("Failed to allocate memory");
103+
return NULL;
104+
}
105+
dname = dirname(dname_buf);
106+
if (dname == NULL)
107+
pexitf("Cannot get dirname for %s", csname);
84108

85-
int unusedfd = g_mkstemp(csname);
86-
if (unusedfd < 0)
87-
pexit("Failed to generate random path for console-socket");
88-
close(unusedfd);
109+
sfd = open(dname, O_CREAT | O_PATH, 0600);
110+
if (sfd < 0)
111+
pexit("Failed to create file for console-socket");
112+
113+
bname = basename(bname_buf);
114+
if (bname == NULL)
115+
pexitf("Cannot get basename for %s", csname);
116+
} else {
117+
_cleanup_free_ const char *tmpdir = g_get_tmp_dir();
118+
119+
csname = g_build_filename(tmpdir, "conmon-term.XXXXXX", NULL);
120+
/*
121+
* Generate a temporary name. Is this unsafe? Probably, but we can
122+
* replace it with a rename(2) setup if necessary.
123+
*/
124+
sfd = g_mkstemp(csname);
125+
if (sfd < 0)
126+
pexit("Failed to generate random path for console-socket");
127+
/* XXX: This should be handled with a rename(2). */
128+
if (unlink(csname) < 0)
129+
pexit("Failed to unlink temporary random path");
130+
close(sfd);
131+
sfd = -1;
132+
}
89133

90134
addr.sun_family = AF_UNIX;
91-
strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);
135+
if (bname)
136+
snprintf(addr.sun_path, sizeof(addr.sun_path) - 1, "/proc/self/fd/%d/%s", sfd, bname);
137+
else
138+
strncpy(addr.sun_path, csname, sizeof(addr.sun_path) - 1);
92139

93140
ninfof("addr{sun_family=AF_UNIX, sun_path=%s}", addr.sun_path);
94141

95142
/* Bind to the console socket path. */
96-
console_socket_fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
97-
if (console_socket_fd < 0)
98-
pexit("Failed to create console-socket");
99-
if (fchmod(console_socket_fd, 0700))
143+
*fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
144+
if (*fd < 0)
145+
pexit("Failed to create socket");
146+
if (fchmod(*fd, 0700))
100147
pexit("Failed to change console-socket permissions");
101-
/* XXX: This should be handled with a rename(2). */
102-
if (unlink(csname) < 0)
103-
pexit("Failed to unlink temporary random path");
104-
if (bind(console_socket_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
148+
if (bind(*fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
105149
pexit("Failed to bind to console-socket");
106-
if (listen(console_socket_fd, 128) < 0)
150+
if (listen(*fd, 128) < 0)
107151
pexit("Failed to listen on console-socket");
108152

109153
return csname;

src/conn_sock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct local_sock_s {
4848
};
4949

5050
char *setup_console_socket(void);
51+
char *setup_seccomp_socket(const char *socket);
5152
char *setup_attach_socket(void);
5253
void setup_notify_socket(char *);
5354
void schedule_main_stdin_write();

src/ctrl.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "conn_sock.h"
99
#include "cmsg.h"
1010
#include "cli.h" // opt_bundle_path
11+
#include "seccomp_notify.h"
1112

1213
#include <sys/ioctl.h>
1314
#include <sys/socket.h>

src/globals.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ int mainfd_stderr = -1;
99

1010
int attach_socket_fd = -1;
1111
int console_socket_fd = -1;
12+
int seccomp_socket_fd = -1;
1213
int terminal_ctrl_fd = -1;
1314
int inotify_fd = -1;
1415
int winsz_fd_w = -1;

src/globals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ extern int mainfd_stderr;
1414

1515
extern int attach_socket_fd;
1616
extern int console_socket_fd;
17+
extern int seccomp_socket_fd;
1718
extern int terminal_ctrl_fd;
1819
extern int inotify_fd;
1920
extern int winsz_fd_w;

0 commit comments

Comments
 (0)