Skip to content

Commit cd3b662

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 <gscrivan@redhat.com>
1 parent f6108d1 commit cd3b662

5 files changed

Lines changed: 265 additions & 11 deletions

File tree

src/libcrun/container.c

Lines changed: 243 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,198 @@ 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+
const char *const OCI_VERSION = "0.2.0";
836+
837+
gen = yajl_gen_alloc (NULL);
838+
if (gen == NULL)
839+
return crun_make_error (err, 0, "yajl_gen_alloc failed");
840+
841+
yajl_gen_config (gen, yajl_gen_beautify, 1);
842+
yajl_gen_config (gen, yajl_gen_validate_utf8, 1);
843+
844+
r = yajl_gen_map_open (gen);
845+
if (UNLIKELY (r != yajl_gen_status_ok))
846+
goto exit;
847+
848+
r = yajl_gen_string (gen, YAJL_STR ("ociVersion"), strlen ("ociVersion"));
849+
if (UNLIKELY (r != yajl_gen_status_ok))
850+
goto exit;
851+
852+
r = yajl_gen_string (gen, YAJL_STR (OCI_VERSION), strlen (OCI_VERSION));
853+
if (UNLIKELY (r != yajl_gen_status_ok))
854+
goto exit;
855+
856+
r = yajl_gen_string (gen, YAJL_STR ("fds"), strlen ("fds"));
857+
if (UNLIKELY (r != yajl_gen_status_ok))
858+
goto exit;
859+
860+
r = yajl_gen_array_open (gen);
861+
if (UNLIKELY (r != yajl_gen_status_ok))
862+
goto exit;
863+
864+
r = yajl_gen_string (gen, YAJL_STR ("seccompFd"), strlen ("seccompFd"));
865+
if (UNLIKELY (r != yajl_gen_status_ok))
866+
goto exit;
867+
868+
r = yajl_gen_array_close (gen);
869+
if (UNLIKELY (r != yajl_gen_status_ok))
870+
goto exit;
871+
872+
r = yajl_gen_string (gen, YAJL_STR ("pid"), strlen ("pid"));
873+
if (UNLIKELY (r != yajl_gen_status_ok))
874+
goto exit;
875+
876+
r = yajl_gen_integer (gen, own_pid);
877+
if (UNLIKELY (r != yajl_gen_status_ok))
878+
goto exit;
879+
880+
if (def && def->linux && def->linux->seccomp)
881+
{
882+
const char *metadata = def->linux->seccomp->listener_metadata;
883+
884+
if (metadata)
885+
{
886+
r = yajl_gen_string (gen, YAJL_STR ("metadata"), strlen ("metadata"));
887+
if (UNLIKELY (r != yajl_gen_status_ok))
888+
goto exit;
889+
890+
r = yajl_gen_string (gen, YAJL_STR (metadata), strlen (metadata));
891+
if (UNLIKELY (r != yajl_gen_status_ok))
892+
goto exit;
893+
}
894+
}
895+
896+
/* State. */
897+
r = yajl_gen_string (gen, YAJL_STR ("state"), strlen ("state"));
898+
if (UNLIKELY (r != yajl_gen_status_ok))
899+
goto exit;
900+
901+
r = yajl_gen_map_open (gen);
902+
if (UNLIKELY (r != yajl_gen_status_ok))
903+
goto exit;
904+
905+
r = yajl_gen_string (gen, YAJL_STR ("ociVersion"), strlen ("ociVersion"));
906+
if (UNLIKELY (r != yajl_gen_status_ok))
907+
goto exit;
908+
909+
r = yajl_gen_string (gen, YAJL_STR (OCI_VERSION), strlen (OCI_VERSION));
910+
if (UNLIKELY (r != yajl_gen_status_ok))
911+
goto exit;
912+
913+
if (container->context && container->context->id)
914+
{
915+
r = yajl_gen_string (gen, YAJL_STR ("id"), strlen ("id"));
916+
if (UNLIKELY (r != yajl_gen_status_ok))
917+
goto exit;
918+
919+
r = yajl_gen_string (gen, YAJL_STR (container->context->id), strlen (container->context->id));
920+
if (UNLIKELY (r != yajl_gen_status_ok))
921+
goto exit;
922+
}
923+
924+
r = yajl_gen_string (gen, YAJL_STR ("status"), strlen ("status"));
925+
if (UNLIKELY (r != yajl_gen_status_ok))
926+
goto exit;
927+
928+
r = yajl_gen_string (gen, YAJL_STR (status), strlen (status));
929+
if (UNLIKELY (r != yajl_gen_status_ok))
930+
goto exit;
931+
932+
r = yajl_gen_string (gen, YAJL_STR ("pid"), strlen ("pid"));
933+
if (UNLIKELY (r != yajl_gen_status_ok))
934+
goto exit;
935+
936+
r = yajl_gen_integer (gen, own_pid);
937+
if (UNLIKELY (r != yajl_gen_status_ok))
938+
goto exit;
939+
940+
if (container->context && container->context->bundle)
941+
{
942+
r = yajl_gen_string (gen, YAJL_STR ("bundle"), strlen ("bundle"));
943+
if (UNLIKELY (r != yajl_gen_status_ok))
944+
goto exit;
945+
946+
r = yajl_gen_string (gen, YAJL_STR (container->context->bundle), strlen (container->context->bundle));
947+
if (UNLIKELY (r != yajl_gen_status_ok))
948+
goto exit;
949+
}
950+
951+
if (def->annotations && def->annotations->len)
952+
{
953+
size_t i;
954+
955+
r = yajl_gen_string (gen, YAJL_STR ("annotations"), strlen ("annotations"));
956+
if (UNLIKELY (r != yajl_gen_status_ok))
957+
goto exit;
958+
959+
r = yajl_gen_map_open (gen);
960+
if (UNLIKELY (r != yajl_gen_status_ok))
961+
goto exit;
962+
963+
for (i = 0; i < def->annotations->len; i++)
964+
{
965+
const char *key = def->annotations->keys[i];
966+
const char *val = def->annotations->values[i];
967+
968+
r = yajl_gen_string (gen, YAJL_STR (key), strlen (key));
969+
if (UNLIKELY (r != yajl_gen_status_ok))
970+
goto exit;
971+
972+
r = yajl_gen_string (gen, YAJL_STR (val), strlen (val));
973+
if (UNLIKELY (r != yajl_gen_status_ok))
974+
goto exit;
975+
}
976+
r = yajl_gen_map_close (gen);
977+
if (UNLIKELY (r != yajl_gen_status_ok))
978+
goto exit;
979+
}
980+
981+
r = yajl_gen_map_close (gen);
982+
if (UNLIKELY (r != yajl_gen_status_ok))
983+
goto exit;
984+
/* End state. */
985+
986+
r = yajl_gen_map_close (gen);
987+
if (UNLIKELY (r != yajl_gen_status_ok))
988+
goto exit;
989+
990+
r = get_yajl_result (gen, seccomp_fd_payload, seccomp_fd_payload_len);
991+
992+
exit:
993+
yajl_gen_free (gen);
994+
995+
return yajl_error_to_crun_error (r, err);
996+
}
997+
806998
/* Initialize the environment where the container process runs.
807999
It is used by the container init process. */
8081000
static int
@@ -996,15 +1188,24 @@ container_init_setup (void *args, pid_t own_pid, char *notify_socket, int sync_s
9961188
{
9971189
char **seccomp_flags = NULL;
9981190
size_t seccomp_flags_len = 0;
1191+
cleanup_free char *seccomp_fd_payload = NULL;
1192+
size_t seccomp_fd_payload_len = 0;
9991193

10001194
if (def->linux && def->linux->seccomp)
10011195
{
10021196
seccomp_flags = def->linux->seccomp->flags;
10031197
seccomp_flags_len = def->linux->seccomp->flags_len;
10041198
}
10051199

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

@@ -1138,14 +1339,24 @@ container_init (void *args, char *notify_socket, int sync_socket, libcrun_error_
11381339
{
11391340
char **seccomp_flags = NULL;
11401341
size_t seccomp_flags_len = 0;
1342+
cleanup_free char *seccomp_fd_payload = NULL;
1343+
size_t seccomp_fd_payload_len = 0;
11411344

11421345
if (def->linux && def->linux->seccomp)
11431346
{
11441347
seccomp_flags = def->linux->seccomp->flags;
11451348
seccomp_flags_len = def->linux->seccomp->flags_len;
11461349
}
11471350

1148-
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd, seccomp_flags,
1351+
if (entrypoint_args->seccomp_receiver_fd >= 0)
1352+
{
1353+
ret = get_seccomp_receiver_fd_payload (entrypoint_args->container, "creating", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
1354+
if (UNLIKELY (ret < 0))
1355+
return ret;
1356+
}
1357+
1358+
ret = libcrun_apply_seccomp (entrypoint_args->seccomp_fd, entrypoint_args->seccomp_receiver_fd,
1359+
seccomp_fd_payload, seccomp_fd_payload_len, seccomp_flags,
11491360
seccomp_flags_len, err);
11501361
if (UNLIKELY (ret < 0))
11511362
return ret;
@@ -1812,6 +2023,7 @@ get_seccomp_receiver_fd (libcrun_container_t *container, int *fd, int *self_rece
18122023
libcrun_error_t *err)
18132024
{
18142025
const char *tmp;
2026+
runtime_spec_schema_config_schema *def = container->container_def;
18152027

18162028
*fd = -1;
18172029
*self_receiver_fd = -1;
@@ -1831,7 +2043,10 @@ get_seccomp_receiver_fd (libcrun_container_t *container, int *fd, int *self_rece
18312043
*plugins = tmp;
18322044
}
18332045

1834-
tmp = find_annotation (container, "run.oci.seccomp.receiver");
2046+
if (def && def->linux && def->linux->seccomp && def->linux->seccomp->listener_path)
2047+
tmp = def->linux->seccomp->listener_path;
2048+
else
2049+
tmp = find_annotation (container, "run.oci.seccomp.receiver");
18352050
if (tmp == NULL)
18362051
tmp = getenv ("RUN_OCI_SECCOMP_RECEIVER");
18372052
if (tmp)
@@ -2873,7 +3088,18 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, runtime_spec
28733088

28743089
if (! process->no_new_privileges)
28753090
{
2876-
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_flags, seccomp_flags_len, err);
3091+
cleanup_free char *seccomp_fd_payload = NULL;
3092+
size_t seccomp_fd_payload_len = 0;
3093+
3094+
if (seccomp_receiver_fd >= 0)
3095+
{
3096+
ret = get_seccomp_receiver_fd_payload (container, "running", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
3097+
if (UNLIKELY (ret < 0))
3098+
return ret;
3099+
}
3100+
3101+
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_fd_payload,
3102+
seccomp_fd_payload_len, seccomp_flags, seccomp_flags_len, err);
28773103
if (UNLIKELY (ret < 0))
28783104
return ret;
28793105
close_and_reset (&seccomp_fd);
@@ -2898,9 +3124,20 @@ libcrun_container_exec (libcrun_context_t *context, const char *id, runtime_spec
28983124

28993125
if (process->no_new_privileges)
29003126
{
2901-
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_flags, seccomp_flags_len, err);
3127+
cleanup_free char *seccomp_fd_payload = NULL;
3128+
size_t seccomp_fd_payload_len = 0;
3129+
3130+
if (seccomp_receiver_fd >= 0)
3131+
{
3132+
ret = get_seccomp_receiver_fd_payload (container, "running", own_pid, &seccomp_fd_payload, &seccomp_fd_payload_len, err);
3133+
if (UNLIKELY (ret < 0))
3134+
return ret;
3135+
}
3136+
ret = libcrun_apply_seccomp (seccomp_fd, seccomp_receiver_fd, seccomp_fd_payload,
3137+
seccomp_fd_payload_len, seccomp_flags, seccomp_flags_len, err);
29023138
if (UNLIKELY (ret < 0))
29033139
return ret;
3140+
29043141
close_and_reset (&seccomp_fd);
29053142
close_and_reset (&seccomp_receiver_fd);
29063143
}

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)