2424#include "../linux.h"
2525#include <unistd.h>
2626#include <sys/stat.h>
27+ #include <sys/socket.h>
2728#include <errno.h>
2829#include <sys/param.h>
2930#include <sys/types.h>
6263#define KRUN_FLAVOR_NITRO "aws-nitro"
6364#define KRUN_FLAVOR_SEV "sev"
6465
66+ #define PASST_FD_PARENT 0
67+ #define PASST_FD_CHILD 1
68+
6569struct krun_config
6670{
6771 void * handle ;
@@ -74,6 +78,7 @@ struct krun_config
7478 int32_t ctx_id_nitro ;
7579 bool has_kvm ;
7680 bool has_nitro ;
81+ int passt_fds [2 ];
7782};
7883
7984/* libkrun handler. */
@@ -314,6 +319,7 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
314319 int32_t (* krun_set_console_output ) (uint32_t ctx_id , const char * c_filepath );
315320 int32_t (* krun_set_exec ) (uint32_t ctx_id , const char * exec_path ,
316321 const char * const argv [], const char * const envp []);
322+ 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 );
317323 struct krun_config * kconf = (struct krun_config * ) cookie ;
318324 void * handle ;
319325 uint32_t num_vcpus , ram_mib ;
@@ -426,6 +432,13 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
426432 if (UNLIKELY (ret < 0 ))
427433 error (EXIT_FAILURE , - ret , "could not set krun vm configuration" );
428434
435+ krun_add_net_unixstream = dlsym (handle , "krun_add_net_unixstream" );
436+
437+ uint8_t mac [] = { 0x5a , 0x94 , 0xef , 0xe4 , 0x0c , 0xee };
438+ ret = krun_add_net_unixstream (ctx_id , NULL , kconf -> passt_fds [PASST_FD_PARENT ], & mac [0 ], COMPAT_NET_FEATURES , 0 );
439+ if (UNLIKELY (ret < 0 ))
440+ error (EXIT_FAILURE , - ret , "could not set krun net configuration" );
441+
429442 if (access ("/dev/dri" , F_OK ) == 0 && access ("/usr/libexec/virgl_render_server" , F_OK ) == 0 )
430443 {
431444 ret = libkrun_enable_virtio_gpu (kconf );
@@ -440,6 +453,69 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
440453 return - ret ;
441454}
442455
456+ static int
457+ libkrun_start_passt (void * cookie )
458+ {
459+ struct krun_config * kconf = (struct krun_config * ) cookie ;
460+ pid_t pid ;
461+ char fd_as_str [16 ];
462+ int pipefd [2 ];
463+ int ret ;
464+
465+ socketpair (AF_UNIX , SOCK_STREAM , 0 , kconf -> passt_fds );
466+ snprintf (fd_as_str , sizeof (fd_as_str ), "%d" , kconf -> passt_fds [PASST_FD_CHILD ]);
467+
468+ char * const argv [] = {
469+ (char * ) "passt" ,
470+ (char * ) "-t" ,
471+ (char * ) "all" ,
472+ (char * ) "-u" ,
473+ (char * ) "all" ,
474+ (char * ) "-f" ,
475+ (char * ) "--fd" ,
476+ fd_as_str ,
477+ NULL
478+ };
479+
480+ ret = pipe (pipefd );
481+ if (UNLIKELY (ret == -1 ))
482+ return ret ;
483+
484+ pid = fork ();
485+ if (pid < 0 )
486+ {
487+ close (pipefd [0 ]);
488+ close (pipefd [1 ]);
489+ return pid ;
490+ }
491+ else if (pid == 0 )
492+ {
493+ close (pipefd [0 ]);
494+
495+ ret = dup2 (pipefd [1 ], STDERR_FILENO );
496+ if (UNLIKELY (ret == -1 ))
497+ {
498+ exit (EXIT_FAILURE );
499+ }
500+
501+ close (pipefd [1 ]);
502+ execvp ("passt" , argv );
503+ }
504+ else
505+ {
506+ /* We need to make sure passt has already started before continuing. A
507+ simple way to do it is with a blocking read on its stdout. */
508+ char buffer [1 ];
509+ close (pipefd [1 ]);
510+ ret = read (pipefd [0 ], buffer , 1 );
511+ if (UNLIKELY (ret < 0 ))
512+ return ret ;
513+ close (pipefd [0 ]);
514+ }
515+
516+ return 0 ;
517+ }
518+
443519/* libkrun_create_kvm_device: explicitly adds kvm device. */
444520static int
445521libkrun_configure_container (void * cookie , enum handler_configure_phase phase ,
@@ -501,6 +577,10 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
501577 if (phase != HANDLER_CONFIGURE_AFTER_MOUNTS )
502578 return 0 ;
503579
580+ ret = libkrun_start_passt (cookie );
581+ if (UNLIKELY (ret < 0 ))
582+ return crun_make_error (err , errno , "start passt" );
583+
504584 /* Do nothing if /dev/kvm is already present in spec */
505585 for (i = 0 ; i < def -> linux -> devices_len ; i ++ )
506586 {
@@ -771,6 +851,42 @@ libkrun_modify_oci_configuration (void *cookie arg_unused, libcrun_context_t *co
771851 return 0 ;
772852}
773853
854+ static int
855+ libkrun_close_fds (void * cookie , int preserve_fds )
856+ {
857+ struct krun_config * kconf = (struct krun_config * ) cookie ;
858+ int first_fd_to_close = preserve_fds + 3 ;
859+ int high_passt_fd ;
860+ int low_passt_fd ;
861+ int ret ;
862+ int i ;
863+
864+ if (kconf -> passt_fds [PASST_FD_CHILD ] > kconf -> passt_fds [PASST_FD_PARENT ])
865+ {
866+ high_passt_fd = kconf -> passt_fds [PASST_FD_CHILD ];
867+ low_passt_fd = kconf -> passt_fds [PASST_FD_PARENT ];
868+ }
869+ else
870+ {
871+ high_passt_fd = kconf -> passt_fds [PASST_FD_PARENT ];
872+ low_passt_fd = kconf -> passt_fds [PASST_FD_CHILD ];
873+ }
874+
875+ if (first_fd_to_close < high_passt_fd )
876+ {
877+ for (i = first_fd_to_close ; i < high_passt_fd ; i ++ )
878+ {
879+ if (i == low_passt_fd )
880+ continue ;
881+ close (i );
882+ }
883+
884+ first_fd_to_close = high_passt_fd + 1 ;
885+ }
886+
887+ return mark_or_close_fds_ge_than (first_fd_to_close , true, NULL );
888+ }
889+
774890struct custom_handler_s handler_libkrun = {
775891 .name = "krun" ,
776892 .alias = NULL ,
@@ -780,6 +896,7 @@ struct custom_handler_s handler_libkrun = {
780896 .run_func = libkrun_exec ,
781897 .configure_container = libkrun_configure_container ,
782898 .modify_oci_configuration = libkrun_modify_oci_configuration ,
899+ .close_fds = libkrun_close_fds ,
783900};
784901
785902#endif
0 commit comments