Skip to content

Commit c0cedb4

Browse files
committed
seccomp: support notify listener
The OCI runtime specs[1] recently gained the support for seccomp notifications. [1] opencontainers/runtime-spec#1074 Signed-off-by: Giuseppe Scrivano <[email protected]>
1 parent e29de40 commit c0cedb4

File tree

5 files changed

+264
-11
lines changed

5 files changed

+264
-11
lines changed

src/libcrun/container.c

Lines changed: 242 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,197 @@ libcrun_configure_handler (struct container_entrypoint_s *args, libcrun_error_t
803803
return crun_make_error (err, EINVAL, "invalid handler specified `%s`", annotation);
804804
}
805805

806+
static int
807+
get_yajl_result (yajl_gen gen, char **out, size_t *out_len)
808+
{
809+
const unsigned char *buf = NULL;
810+
size_t buf_len = 0;
811+
int r;
812+
813+
r = yajl_gen_get_buf (gen, &buf, &buf_len);
814+
if (UNLIKELY (r != yajl_gen_status_ok))
815+
return r;
816+
817+
*out_len = buf_len;
818+
819+
*out = malloc (buf_len + 1);
820+
if (*out == NULL)
821+
OOM ();
822+
memcpy (*out, buf, buf_len);
823+
(*out)[buf_len] = '\0';
824+
825+
return yajl_gen_status_ok;
826+
}
827+
828+
static int
829+
get_seccomp_receiver_fd_payload (libcrun_container_t *container, const char *status, pid_t own_pid,
830+
char **seccomp_fd_payload, size_t *seccomp_fd_payload_len, libcrun_error_t *err)
831+
{
832+
int r;
833+
yajl_gen gen = NULL;
834+
runtime_spec_schema_config_schema *def = container->container_def;
835+
836+
gen = yajl_gen_alloc (NULL);
837+
if (gen == NULL)
838+
return crun_make_error (err, 0, "yajl_gen_alloc failed");
839+
840+
yajl_gen_config (gen, yajl_gen_beautify, 1);
841+
yajl_gen_config (gen, yajl_gen_validate_utf8, 1);
842+
843+
r = yajl_gen_map_open (gen);
844+
if (UNLIKELY (r != yajl_gen_status_ok))
845+
goto exit;
846+
847+
r = yajl_gen_string (gen, YAJL_STR ("ociVersion"), strlen ("ociVersion"));
848+
if (UNLIKELY (r != yajl_gen_status_ok))
849+
goto exit;
850+
851+
r = yajl_gen_string (gen, YAJL_STR ("0.2.0"), strlen ("0.2.0"));
852+
if (UNLIKELY (r != yajl_gen_status_ok))
853+
goto exit;
854+
855+
r = yajl_gen_string (gen, YAJL_STR ("fds"), strlen ("fds"));
856+
if (UNLIKELY (r != yajl_gen_status_ok))
857+
goto exit;
858+
859+
r = yajl_gen_array_open (gen);
860+
if (UNLIKELY (r != yajl_gen_status_ok))
861+
goto exit;
862+
863+
r = yajl_gen_string (gen, YAJL_STR ("seccompFd"), strlen ("seccompFd"));
864+
if (UNLIKELY (r != yajl_gen_status_ok))
865+
goto exit;
866+
867+
r = yajl_gen_array_close (gen);
868+
if (UNLIKELY (r != yajl_gen_status_ok))
869+
goto exit;
870+
871+
r = yajl_gen_string (gen, YAJL_STR ("pid"), strlen ("pid"));
872+
if (UNLIKELY (r != yajl_gen_status_ok))
873+
goto exit;
874+
875+
r = yajl_gen_integer (gen, own_pid);
876+
if (UNLIKELY (r != yajl_gen_status_ok))
877+
goto exit;
878+
879+
if (def && def->linux && def->linux->seccomp)
880+
{
881+
const char *metadata = def->linux->seccomp->listener_metadata;
882+
883+
if (metadata)
884+
{
885+
r = yajl_gen_string (gen, YAJL_STR ("metadata"), strlen ("metadata"));
886+
if (UNLIKELY (r != yajl_gen_status_ok))
887+
goto exit;
888+
889+
r = yajl_gen_string (gen, YAJL_STR (metadata), strlen (metadata));
890+
if (UNLIKELY (r != yajl_gen_status_ok))
891+
goto exit;
892+
}
893+
}
894+
895+
/* State. */
896+
r = yajl_gen_string (gen, YAJL_STR ("state"), strlen ("state"));
897+
if (UNLIKELY (r != yajl_gen_status_ok))
898+
goto exit;
899+
900+
r = yajl_gen_map_open (gen);
901+
if (UNLIKELY (r != yajl_gen_status_ok))
902+
goto exit;
903+
904+
r = yajl_gen_string (gen, YAJL_STR ("ociVersion"), strlen ("ociVersion"));
905+
if (UNLIKELY (r != yajl_gen_status_ok))
906+
goto exit;
907+
908+
r = yajl_gen_string (gen, YAJL_STR ("0.2.0"), strlen ("0.2.0"));
909+
if (UNLIKELY (r != yajl_gen_status_ok))
910+
goto exit;
911+
912+
if (container->context && container->context->id)
913+
{
914+
r = yajl_gen_string (gen, YAJL_STR ("id"), strlen ("id"));
915+
if (UNLIKELY (r != yajl_gen_status_ok))
916+
goto exit;
917+
918+
r = yajl_gen_string (gen, YAJL_STR (container->context->id), strlen (container->context->id));
919+
if (UNLIKELY (r != yajl_gen_status_ok))
920+
goto exit;
921+
}
922+
923+
r = yajl_gen_string (gen, YAJL_STR ("status"), strlen ("status"));
924+
if (UNLIKELY (r != yajl_gen_status_ok))
925+
goto exit;
926+
927+
r = yajl_gen_string (gen, YAJL_STR (status), strlen (status));
928+
if (UNLIKELY (r != yajl_gen_status_ok))
929+
goto exit;
930+
931+
r = yajl_gen_string (gen, YAJL_STR ("pid"), strlen ("pid"));
932+
if (UNLIKELY (r != yajl_gen_status_ok))
933+
goto exit;
934+
935+
r = yajl_gen_integer (gen, own_pid);
936+
if (UNLIKELY (r != yajl_gen_status_ok))
937+
goto exit;
938+
939+
if (container->context && container->context->bundle)
940+
{
941+
r = yajl_gen_string (gen, YAJL_STR ("bundle"), strlen ("bundle"));
942+
if (UNLIKELY (r != yajl_gen_status_ok))
943+
goto exit;
944+
945+
r = yajl_gen_string (gen, YAJL_STR (container->context->bundle), strlen (container->context->bundle));
946+
if (UNLIKELY (r != yajl_gen_status_ok))
947+
goto exit;
948+
}
949+
950+
if (def->annotations && def->annotations->len)
951+
{
952+
size_t i;
953+
954+
r = yajl_gen_string (gen, YAJL_STR ("annotations"), strlen ("annotations"));
955+
if (UNLIKELY (r != yajl_gen_status_ok))
956+
goto exit;
957+
958+
r = yajl_gen_map_open (gen);
959+
if (UNLIKELY (r != yajl_gen_status_ok))
960+
goto exit;
961+
962+
for (i = 0; i < def->annotations->len; i++)
963+
{
964+
const char *key = def->annotations->keys[i];
965+
const char *val = def->annotations->values[i];
966+
967+
r = yajl_gen_string (gen, YAJL_STR (key), strlen (key));
968+
if (UNLIKELY (r != yajl_gen_status_ok))
969+
goto exit;
970+
971+
r = yajl_gen_string (gen, YAJL_STR (val), strlen (val));
972+
if (UNLIKELY (r != yajl_gen_status_ok))
973+
goto exit;
974+
}
975+
r = yajl_gen_map_close (gen);
976+
if (UNLIKELY (r != yajl_gen_status_ok))
977+
goto exit;
978+
}
979+
980+
r = yajl_gen_map_close (gen);
981+
if (UNLIKELY (r != yajl_gen_status_ok))
982+
goto exit;
983+
/* End state. */
984+
985+
r = yajl_gen_map_close (gen);
986+
if (UNLIKELY (r != yajl_gen_status_ok))
987+
goto exit;
988+
989+
r = get_yajl_result (gen, seccomp_fd_payload, seccomp_fd_payload_len);
990+
991+
exit:
992+
yajl_gen_free (gen);
993+
994+
return yajl_error_to_crun_error (r, err);
995+
}
996+
806997
/* Initialize the environment where the container process runs.
807998
It is used by the container init process. */
808999
static int
@@ -996,15 +1187,24 @@ container_init_setup (void *args, pid_t own_pid, char *notify_socket, int sync_s
9961187
{
9971188
char **seccomp_flags = NULL;
9981189
size_t seccomp_flags_len = 0;
1190+
cleanup_free char *seccomp_fd_payload = NULL;
1191+
size_t seccomp_fd_payload_len = 0;
9991192

10001193
if (def->linux && def->linux->seccomp)
10011194
{
10021195
seccomp_flags = def->linux->seccomp->flags;
10031196
seccomp_flags_len = def->linux->seccomp->flags_len;
10041197
}
10051198

1006-
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd, seccomp_flags,
1007-
seccomp_flags_len, err);
1199+
if (entrypoint_args->seccomp_receiver_fd >= 0)
1200+
{
1201+
ret = get_seccomp_receiver_fd_payload (container, "creating", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
1202+
if (UNLIKELY (ret < 0))
1203+
return ret;
1204+
}
1205+
1206+
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd,
1207+
seccomp_fd_payload, seccomp_fd_payload_len, seccomp_flags, seccomp_flags_len, err);
10081208
if (UNLIKELY (ret < 0))
10091209
return ret;
10101210

@@ -1138,14 +1338,24 @@ container_init (void *args, char *notify_socket, int sync_socket, libcrun_error_
11381338
{
11391339
char **seccomp_flags = NULL;
11401340
size_t seccomp_flags_len = 0;
1341+
cleanup_free char *seccomp_fd_payload = NULL;
1342+
size_t seccomp_fd_payload_len = 0;
11411343

11421344
if (def->linux && def->linux->seccomp)
11431345
{
11441346
seccomp_flags = def->linux->seccomp->flags;
11451347
seccomp_flags_len = def->linux->seccomp->flags_len;
11461348
}
11471349

1148-
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd, seccomp_flags,
1350+
if (entrypoint_args->seccomp_receiver_fd >= 0)
1351+
{
1352+
ret = get_seccomp_receiver_fd_payload (entrypoint_args->container, "creating", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
1353+
if (UNLIKELY (ret < 0))
1354+
return ret;
1355+
}
1356+
1357+
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd,
1358+
seccomp_fd_payload, seccomp_fd_payload_len, seccomp_flags,
11491359
seccomp_flags_len, err);
11501360
if (UNLIKELY (ret < 0))
11511361
return ret;
@@ -1812,6 +2022,7 @@ get_seccomp_receiver_fd (libcrun_container_t *container, int *fd, int *self_rece
18122022
libcrun_error_t *err)
18132023
{
18142024
const char *tmp;
2025+
runtime_spec_schema_config_schema *def = container->container_def;
18152026

18162027
*fd = -1;
18172028
*self_receiver_fd = -1;
@@ -1831,7 +2042,10 @@ get_seccomp_receiver_fd (libcrun_container_t *container, int *fd, int *self_rece
18312042
*plugins = tmp;
18322043
}
18332044

1834-
tmp = find_annotation (container, "run.oci.seccomp.receiver");
2045+
if (def && def->linux && def->linux->seccomp && def->linux->seccomp->listener_path)
2046+
tmp = def->linux->seccomp->listener_path;
2047+
else
2048+
tmp = find_annotation (container, "run.oci.seccomp.receiver");
18352049
if (tmp == NULL)
18362050
tmp = getenv ("RUN_OCI_SECCOMP_RECEIVER");
18372051
if (tmp)
@@ -2872,7 +3086,18 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, runtime_spec
28723086

28733087
if (! process->no_new_privileges)
28743088
{
2875-
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_flags, seccomp_flags_len, err);
3089+
cleanup_free char *seccomp_fd_payload = NULL;
3090+
size_t seccomp_fd_payload_len = 0;
3091+
3092+
if (seccomp_receiver_fd >= 0)
3093+
{
3094+
ret = get_seccomp_receiver_fd_payload (container, "running", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
3095+
if (UNLIKELY (ret < 0))
3096+
return ret;
3097+
}
3098+
3099+
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_fd_payload,
3100+
seccomp_fd_payload_len, seccomp_flags, seccomp_flags_len, err);
28763101
if (UNLIKELY (ret < 0))
28773102
return ret;
28783103
close_and_reset (&seccomp_fd);
@@ -2897,9 +3122,20 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, runtime_spec
28973122

28983123
if (process->no_new_privileges)
28993124
{
2900-
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_flags, seccomp_flags_len, err);
3125+
cleanup_free char *seccomp_fd_payload = NULL;
3126+
size_t seccomp_fd_payload_len = 0;
3127+
3128+
if (seccomp_receiver_fd >= 0)
3129+
{
3130+
ret = get_seccomp_receiver_fd_payload (container, "running", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
3131+
if (UNLIKELY (ret < 0))
3132+
return ret;
3133+
}
3134+
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_fd_payload,
3135+
seccomp_fd_payload_len, seccomp_flags, seccomp_flags_len, err);
29013136
if (UNLIKELY (ret < 0))
29023137
return ret;
3138+
29033139
close_and_reset (&seccomp_fd);
29043140
close_and_reset (&seccomp_receiver_fd);
29053141
}

src/libcrun/seccomp.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ cleanup_seccompp (void *p)
168168
#define cleanup_seccomp __attribute__ ((cleanup (cleanup_seccompp)))
169169

170170
int
171-
libcrun_apply_seccomp (int infd, int listener_receiver_fd, char **seccomp_flags, size_t seccomp_flags_len,
171+
libcrun_apply_seccomp (int infd, int listener_receiver_fd, const char *receiver_fd_payload,
172+
size_t receiver_fd_payload_len, char **seccomp_flags, size_t seccomp_flags_len,
172173
libcrun_error_t *err)
173174
{
174175
#ifdef HAVE_SECCOMP
@@ -233,7 +234,8 @@ libcrun_apply_seccomp (int infd, int listener_receiver_fd, char **seccomp_flags,
233234
{
234235
int fd = ret;
235236

236-
ret = send_fd_to_socket (listener_receiver_fd, fd, err);
237+
ret = send_fd_to_socket_with_payload (listener_receiver_fd, fd,
238+
receiver_fd_payload, receiver_fd_payload_len, err);
237239
if (UNLIKELY (ret < 0))
238240
return crun_error_wrap (err, "send listener fd `%d` to receiver", fd);
239241
}

src/libcrun/seccomp.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ enum
3232
};
3333

3434
int libcrun_generate_seccomp (libcrun_container_t *container, int outfd, unsigned int options, libcrun_error_t *err);
35-
int libcrun_apply_seccomp (int infd, int listener_receiver_fd, char **flags, size_t flags_len, libcrun_error_t *err);
35+
int libcrun_apply_seccomp (int infd, int listener_receiver_fd, const char *receiver_fd_payload,
36+
size_t receiver_fd_payload_len, char **flags, size_t flags_len, libcrun_error_t *err);
3637

3738
#endif

src/libcrun/utils.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -922,18 +922,30 @@ open_unix_domain_socket (const char *path, int dgram, libcrun_error_t *err)
922922

923923
int
924924
send_fd_to_socket (int server, int fd, libcrun_error_t *err)
925+
{
926+
return send_fd_to_socket_with_payload (server, fd, NULL, 0, err);
927+
}
928+
929+
int
930+
send_fd_to_socket_with_payload (int server, int fd, const char *payload, size_t payload_len, libcrun_error_t *err)
925931
{
926932
int ret;
927933
struct cmsghdr *cmsg = NULL;
928-
struct iovec iov[1];
934+
struct iovec iov[2];
929935
struct msghdr msg = {};
930-
char ctrl_buf[CMSG_SPACE (sizeof (int))] = {};
936+
char ctrl_buf[CMSG_SPACE (1 + sizeof (int))] = {};
931937
char data[1];
932938

933939
data[0] = ' ';
934940
iov[0].iov_base = data;
935941
iov[0].iov_len = sizeof (data);
936942

943+
if (payload_len > 0)
944+
{
945+
iov[0].iov_base = (void *) payload;
946+
iov[0].iov_len = payload_len;
947+
}
948+
937949
msg.msg_name = NULL;
938950
msg.msg_namelen = 0;
939951
msg.msg_iov = iov;

src/libcrun/utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ int open_unix_domain_socket (const char *path, int dgram, libcrun_error_t *err);
221221

222222
int send_fd_to_socket (int server, int fd, libcrun_error_t *err);
223223

224+
int send_fd_to_socket_with_payload (int server, int fd, const char *payload, size_t payload_len, libcrun_error_t *err);
225+
224226
int create_socket_pair (int *pair, libcrun_error_t *err);
225227

226228
int receive_fd_from_socket (int from, libcrun_error_t *err);

0 commit comments

Comments
 (0)