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>
6869#define KRUN_FLAVOR_AWS_NITRO "aws-nitro"
6970#define KRUN_FLAVOR_SEV "sev"
7071
72+ #define PASST_FD_PARENT 0
73+ #define PASST_FD_CHILD 1
74+
7175struct krun_config
7276{
7377 void * handle ;
@@ -80,6 +84,7 @@ struct krun_config
8084 int32_t ctx_id_awsnitro ;
8185 bool has_kvm ;
8286 bool has_awsnitro ;
87+ int passt_fds [2 ];
8388};
8489
8590/* libkrun handler. */
@@ -366,6 +371,7 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
366371 int32_t (* krun_set_console_output ) (uint32_t ctx_id , const char * c_filepath );
367372 int32_t (* krun_set_exec ) (uint32_t ctx_id , const char * exec_path ,
368373 const char * const argv [], const char * const envp []);
374+ 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 );
369375 struct krun_config * kconf = (struct krun_config * ) cookie ;
370376 void * handle ;
371377 uint32_t num_vcpus , ram_mib ;
@@ -498,6 +504,13 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
498504 if (UNLIKELY (ret < 0 ))
499505 error (EXIT_FAILURE , - ret , "could not set krun vm configuration" );
500506
507+ krun_add_net_unixstream = dlsym (handle , "krun_add_net_unixstream" );
508+
509+ uint8_t mac [] = { 0x5a , 0x94 , 0xef , 0xe4 , 0x0c , 0xee };
510+ ret = krun_add_net_unixstream (ctx_id , NULL , kconf -> passt_fds [PASST_FD_PARENT ], & mac [0 ], COMPAT_NET_FEATURES , 0 );
511+ if (UNLIKELY (ret < 0 ))
512+ error (EXIT_FAILURE , - ret , "could not set krun net configuration" );
513+
501514 if (access ("/dev/dri" , F_OK ) == 0 && access ("/usr/libexec/virgl_render_server" , F_OK ) == 0 )
502515 {
503516 ret = libkrun_enable_virtio_gpu (kconf );
@@ -515,6 +528,69 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
515528 return ret ;
516529}
517530
531+ static int
532+ libkrun_start_passt (void * cookie )
533+ {
534+ struct krun_config * kconf = (struct krun_config * ) cookie ;
535+ pid_t pid ;
536+ char fd_as_str [16 ];
537+ int pipefd [2 ];
538+ int ret ;
539+
540+ socketpair (AF_UNIX , SOCK_STREAM , 0 , kconf -> passt_fds );
541+ snprintf (fd_as_str , sizeof (fd_as_str ), "%d" , kconf -> passt_fds [PASST_FD_CHILD ]);
542+
543+ char * const argv [] = {
544+ (char * ) "passt" ,
545+ (char * ) "-t" ,
546+ (char * ) "all" ,
547+ (char * ) "-u" ,
548+ (char * ) "all" ,
549+ (char * ) "-f" ,
550+ (char * ) "--fd" ,
551+ fd_as_str ,
552+ NULL
553+ };
554+
555+ ret = pipe (pipefd );
556+ if (UNLIKELY (ret == -1 ))
557+ return ret ;
558+
559+ pid = fork ();
560+ if (pid < 0 )
561+ {
562+ close (pipefd [0 ]);
563+ close (pipefd [1 ]);
564+ return pid ;
565+ }
566+ else if (pid == 0 )
567+ {
568+ close (pipefd [0 ]);
569+
570+ ret = dup2 (pipefd [1 ], STDERR_FILENO );
571+ if (UNLIKELY (ret == -1 ))
572+ {
573+ exit (EXIT_FAILURE );
574+ }
575+
576+ close (pipefd [1 ]);
577+ execvp ("passt" , argv );
578+ }
579+ else
580+ {
581+ /* We need to make sure passt has already started before continuing. A
582+ simple way to do it is with a blocking read on its stdout. */
583+ char buffer [1 ];
584+ close (pipefd [1 ]);
585+ ret = read (pipefd [0 ], buffer , 1 );
586+ if (UNLIKELY (ret < 0 ))
587+ return ret ;
588+ close (pipefd [0 ]);
589+ }
590+
591+ return 0 ;
592+ }
593+
518594/* libkrun_create_kvm_device: explicitly adds kvm device. */
519595static int
520596libkrun_configure_container (void * cookie , enum handler_configure_phase phase ,
@@ -576,6 +652,10 @@ libkrun_configure_container (void *cookie, enum handler_configure_phase phase,
576652 if (phase != HANDLER_CONFIGURE_AFTER_MOUNTS )
577653 return 0 ;
578654
655+ ret = libkrun_start_passt (cookie );
656+ if (UNLIKELY (ret < 0 ))
657+ return crun_make_error (err , errno , "start passt" );
658+
579659 /* Do nothing if /dev/kvm is already present in spec */
580660 for (i = 0 ; i < def -> linux -> devices_len ; i ++ )
581661 {
@@ -846,6 +926,42 @@ libkrun_modify_oci_configuration (void *cookie arg_unused, libcrun_context_t *co
846926 return 0 ;
847927}
848928
929+ static int
930+ libkrun_close_fds (void * cookie , libcrun_container_t * container , int preserve_fds )
931+ {
932+ struct krun_config * kconf = (struct krun_config * ) cookie ;
933+ int first_fd_to_close = preserve_fds + 3 ;
934+ int high_passt_fd ;
935+ int low_passt_fd ;
936+ int ret ;
937+ int i ;
938+
939+ if (kconf -> passt_fds [PASST_FD_CHILD ] > kconf -> passt_fds [PASST_FD_PARENT ])
940+ {
941+ high_passt_fd = kconf -> passt_fds [PASST_FD_CHILD ];
942+ low_passt_fd = kconf -> passt_fds [PASST_FD_PARENT ];
943+ }
944+ else
945+ {
946+ high_passt_fd = kconf -> passt_fds [PASST_FD_PARENT ];
947+ low_passt_fd = kconf -> passt_fds [PASST_FD_CHILD ];
948+ }
949+
950+ if (first_fd_to_close < high_passt_fd )
951+ {
952+ for (i = first_fd_to_close ; i < high_passt_fd ; i ++ )
953+ {
954+ if (i == low_passt_fd )
955+ continue ;
956+ close (i );
957+ }
958+
959+ first_fd_to_close = high_passt_fd + 1 ;
960+ }
961+
962+ return mark_or_close_fds_ge_than (container , first_fd_to_close , true, NULL );
963+ }
964+
849965struct custom_handler_s handler_libkrun = {
850966 .name = "krun" ,
851967 .alias = NULL ,
@@ -855,6 +971,7 @@ struct custom_handler_s handler_libkrun = {
855971 .run_func = libkrun_exec ,
856972 .configure_container = libkrun_configure_container ,
857973 .modify_oci_configuration = libkrun_modify_oci_configuration ,
974+ .close_fds = libkrun_close_fds ,
858975};
859976
860977#endif
0 commit comments