diff --git a/src/libcrun/container.c b/src/libcrun/container.c index 642ac453bf..aa7812efc2 100644 --- a/src/libcrun/container.c +++ b/src/libcrun/container.c @@ -1651,7 +1651,15 @@ container_init (void *args, char *notify_socket, int sync_socket, libcrun_error_ This is a best effort operation, because the seccomp filter is already in place and it could stop some syscalls used by mark_or_close_fds_ge_than. */ - ret = mark_or_close_fds_ge_than (entrypoint_args->context->preserve_fds + 3, true, err); + if (entrypoint_args->custom_handler->vtable->close_fds) + { + ret = entrypoint_args->custom_handler->vtable->close_fds (entrypoint_args->custom_handler->cookie, + entrypoint_args->context->preserve_fds); + } + else + { + ret = mark_or_close_fds_ge_than (entrypoint_args->context->preserve_fds + 3, true, err); + } if (UNLIKELY (ret < 0)) crun_error_release (err); diff --git a/src/libcrun/custom-handler.h b/src/libcrun/custom-handler.h index 9351daa5be..43d97b806c 100644 --- a/src/libcrun/custom-handler.h +++ b/src/libcrun/custom-handler.h @@ -48,6 +48,8 @@ struct custom_handler_s int (*modify_oci_configuration) (void *cookie, libcrun_context_t *context, runtime_spec_schema_config_schema *def, libcrun_error_t *err); + + int (*close_fds) (void *cookie, int preserve_fds); }; struct custom_handler_manager_s; diff --git a/src/libcrun/handlers/krun.c b/src/libcrun/handlers/krun.c index b0bf276c7d..5d61bd4716 100644 --- a/src/libcrun/handlers/krun.c +++ b/src/libcrun/handlers/krun.c @@ -24,6 +24,7 @@ #include "../linux.h" #include #include +#include #include #include #include @@ -62,6 +63,9 @@ #define KRUN_FLAVOR_NITRO "aws-nitro" #define KRUN_FLAVOR_SEV "sev" +#define PASST_FD_PARENT 0 +#define PASST_FD_CHILD 1 + struct krun_config { void *handle; @@ -74,6 +78,7 @@ struct krun_config int32_t ctx_id_nitro; bool has_kvm; bool has_nitro; + int passt_fds[2]; }; /* libkrun handler. */ @@ -350,6 +355,7 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname int32_t (*krun_set_root) (uint32_t ctx_id, const char *root_path); int32_t (*krun_set_root_disk) (uint32_t ctx_id, const char *disk_path); int32_t (*krun_set_tee_config_file) (uint32_t ctx_id, const char *file_path); + int32_t (*krun_add_net_unixstream) (uint32_t ctx_id, const char *c_path, int fd, uint8_t *const c_mac, uint32_t features, uint32_t flags); struct krun_config *kconf = (struct krun_config *) cookie; void *handle; uint32_t num_vcpus, ram_mib; @@ -450,6 +456,13 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname if (UNLIKELY (ret < 0)) error (EXIT_FAILURE, -ret, "could not set krun vm configuration"); + krun_add_net_unixstream = dlsym (handle, "krun_add_net_unixstream"); + + uint8_t mac[] = { 0x5a, 0x94, 0xef, 0xe4, 0x0c, 0xee }; + ret = krun_add_net_unixstream (ctx_id, NULL, kconf->passt_fds[PASST_FD_PARENT], &mac[0], COMPAT_NET_FEATURES, 0); + if (UNLIKELY (ret < 0)) + error (EXIT_FAILURE, -ret, "could not set krun net configuration"); + if (access ("/dev/dri", F_OK) == 0 && access ("/usr/libexec/virgl_render_server", F_OK) == 0) { ret = libkrun_enable_virtio_gpu (kconf); @@ -464,6 +477,69 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname return -ret; } +static int +libkrun_start_passt (void *cookie) +{ + struct krun_config *kconf = (struct krun_config *) cookie; + pid_t pid; + char fd_as_str[16]; + int pipefd[2]; + int ret; + + socketpair (AF_UNIX, SOCK_STREAM, 0, kconf->passt_fds); + snprintf (fd_as_str, sizeof (fd_as_str), "%d", kconf->passt_fds[PASST_FD_CHILD]); + + char *const argv[] = { + (char *) "passt", + (char *) "-t", + (char *) "all", + (char *) "-u", + (char *) "all", + (char *) "-f", + (char *) "--fd", + fd_as_str, + NULL + }; + + ret = pipe (pipefd); + if (UNLIKELY (ret == -1)) + return ret; + + pid = fork (); + if (pid < 0) + { + close (pipefd[0]); + close (pipefd[1]); + return pid; + } + else if (pid == 0) + { + close (pipefd[0]); + + ret = dup2 (pipefd[1], STDERR_FILENO); + if (UNLIKELY (ret == -1)) + { + exit (EXIT_FAILURE); + } + + close (pipefd[1]); + execvp ("passt", argv); + } + else + { + /* We need to make sure passt has already started before continuing. A + simple way to do it is with a blocking read on its stdout. */ + char buffer[1]; + close (pipefd[1]); + ret = read (pipefd[0], buffer, 1); + if (UNLIKELY (ret < 0)) + return ret; + close (pipefd[0]); + } + + return 0; +} + /* libkrun_create_kvm_device: explicitly adds kvm device. */ static int libkrun_configure_container (void *cookie, enum handler_configure_phase phase, @@ -525,6 +601,10 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase, if (phase != HANDLER_CONFIGURE_AFTER_MOUNTS) return 0; + ret = libkrun_start_passt (cookie); + if (UNLIKELY (ret < 0)) + return crun_make_error (err, errno, "start passt"); + /* Do nothing if /dev/kvm is already present in spec */ for (i = 0; i < def->linux->devices_len; i++) { @@ -781,6 +861,42 @@ libkrun_modify_oci_configuration (void *cookie arg_unused, libcrun_context_t *co return 0; } +static int +libkrun_close_fds (void *cookie, int preserve_fds) +{ + struct krun_config *kconf = (struct krun_config *) cookie; + int first_fd_to_close = preserve_fds + 3; + int high_passt_fd; + int low_passt_fd; + int ret; + int i; + + if (kconf->passt_fds[PASST_FD_CHILD] > kconf->passt_fds[PASST_FD_PARENT]) + { + high_passt_fd = kconf->passt_fds[PASST_FD_CHILD]; + low_passt_fd = kconf->passt_fds[PASST_FD_PARENT]; + } + else + { + high_passt_fd = kconf->passt_fds[PASST_FD_PARENT]; + low_passt_fd = kconf->passt_fds[PASST_FD_CHILD]; + } + + if (first_fd_to_close < high_passt_fd) + { + for (i = first_fd_to_close; i < high_passt_fd; i++) + { + if (i == low_passt_fd) + continue; + close (i); + } + + first_fd_to_close = high_passt_fd + 1; + } + + return mark_or_close_fds_ge_than (first_fd_to_close, true, NULL); +} + struct custom_handler_s handler_libkrun = { .name = "krun", .alias = NULL, @@ -790,6 +906,7 @@ struct custom_handler_s handler_libkrun = { .run_func = libkrun_exec, .configure_container = libkrun_configure_container, .modify_oci_configuration = libkrun_modify_oci_configuration, + .close_fds = libkrun_close_fds, }; #endif