5959 */
6060#define KRUN_VM_FILE "/.krun_vm.json"
6161
62+ #define KRUN_FLAVOR_SEV "sev"
63+
6264struct krun_config
6365{
6466 void * handle ;
@@ -138,17 +140,11 @@ libkrun_configure_kernel (uint32_t ctx_id, void *handle, yajl_val *config_tree,
138140}
139141
140142static int
141- libkrun_configure_vm ( uint32_t ctx_id , void * handle , bool * configured , libcrun_error_t * err )
143+ libkrun_read_vm_config ( yajl_val * config_tree , libcrun_error_t * err )
142144{
143- int32_t (* krun_set_vm_config ) (uint32_t ctx_id , uint8_t num_vcpus , uint32_t ram_mib );
144- struct parser_context ctx = { 0 , stderr };
145- cleanup_free char * config = NULL ;
146- yajl_val config_tree = NULL ;
147- yajl_val cpus = NULL ;
148- yajl_val ram_mib = NULL ;
149- const char * path_cpus [] = { "cpus" , (const char * ) 0 };
150- const char * path_ram_mib [] = { "ram_mib" , (const char * ) 0 };
151145 int ret ;
146+ cleanup_free char * config = NULL ;
147+ struct parser_context ctx = { 0 , stderr };
152148
153149 if (access (KRUN_VM_FILE , F_OK ) != 0 )
154150 return 0 ;
@@ -157,20 +153,36 @@ libkrun_configure_vm (uint32_t ctx_id, void *handle, bool *configured, libcrun_e
157153 if (UNLIKELY (ret < 0 ))
158154 return ret ;
159155
160- ret = parse_json_file (& config_tree , config , & ctx , err );
156+ ret = parse_json_file (config_tree , config , & ctx , err );
161157 if (UNLIKELY (ret < 0 ))
162158 return ret ;
163159
160+ return 0 ;
161+ }
162+
163+ static int
164+ libkrun_configure_vm (uint32_t ctx_id , void * handle , bool * configured , yajl_val * config_tree , libcrun_error_t * err )
165+ {
166+ int32_t (* krun_set_vm_config ) (uint32_t ctx_id , uint8_t num_vcpus , uint32_t ram_mib );
167+ yajl_val cpus = NULL ;
168+ yajl_val ram_mib = NULL ;
169+ const char * path_cpus [] = { "cpus" , (const char * ) 0 };
170+ const char * path_ram_mib [] = { "ram_mib" , (const char * ) 0 };
171+ int ret ;
172+
173+ if (* config_tree == NULL )
174+ return 0 ;
175+
164176 /* Try to configure an external kernel. If the configuration file doesn't
165177 * specify a kernel, libkrun automatically fall back to using libkrunfw,
166178 * if the library is present and was loaded while creating the context.
167179 */
168- ret = libkrun_configure_kernel (ctx_id , handle , & config_tree , err );
180+ ret = libkrun_configure_kernel (ctx_id , handle , config_tree , err );
169181 if (UNLIKELY (ret ))
170182 return ret ;
171183
172- cpus = yajl_tree_get (config_tree , path_cpus , yajl_t_number );
173- ram_mib = yajl_tree_get (config_tree , path_ram_mib , yajl_t_number );
184+ cpus = yajl_tree_get (* config_tree , path_cpus , yajl_t_number );
185+ ram_mib = yajl_tree_get (* config_tree , path_ram_mib , yajl_t_number );
174186 /* Both cpus and ram_mib must be present at the same time */
175187 if (cpus == NULL || ram_mib == NULL || ! YAJL_IS_INTEGER (cpus ) || ! YAJL_IS_INTEGER (ram_mib ))
176188 return 0 ;
@@ -189,6 +201,60 @@ libkrun_configure_vm (uint32_t ctx_id, void *handle, bool *configured, libcrun_e
189201 return 0 ;
190202}
191203
204+ static int
205+ libkrun_configure_flavor (void * cookie , yajl_val * config_tree , libcrun_error_t * err )
206+ {
207+ int ret , sev_indicated = 0 ;
208+ const char * path_flavor [] = { "flavor" , (const char * ) 0 };
209+ struct krun_config * kconf = (struct krun_config * ) cookie ;
210+ yajl_val val_flavor = NULL ;
211+ char * flavor = NULL ;
212+
213+ // Read if the SEV flavor was indicated in the krun VM config.
214+ val_flavor = yajl_tree_get (* config_tree , path_flavor , yajl_t_string );
215+ if (val_flavor != NULL && YAJL_IS_STRING (val_flavor ))
216+ {
217+ flavor = YAJL_GET_STRING (val_flavor );
218+
219+ // The SEV flavor will be used if the krun VM config indicates to use SEV
220+ // within the "flavor" field.
221+ sev_indicated |= strcmp (flavor , KRUN_FLAVOR_SEV ) == 0 ;
222+ }
223+
224+ // To maintain backward compatibility, also use the SEV flavor if the
225+ // KRUN_SEV_FILE was found.
226+ sev_indicated |= access (KRUN_SEV_FILE , F_OK ) == 0 ;
227+
228+ if (sev_indicated )
229+ {
230+ if (kconf -> handle_sev == NULL )
231+ error (EXIT_FAILURE , 0 , "the container requires libkrun-sev but it's not available" );
232+
233+ // We no longer need the libkrun handle.
234+ ret = dlclose (kconf -> handle );
235+ if (UNLIKELY (ret != 0 ))
236+ return crun_make_error (err , 0 , "could not unload handle: `%s`" , dlerror ());
237+
238+ kconf -> handle = kconf -> handle_sev ;
239+ kconf -> ctx_id = kconf -> ctx_id_sev ;
240+ kconf -> sev = true;
241+ }
242+ else
243+ {
244+ if (kconf -> handle == NULL )
245+ error (EXIT_FAILURE , 0 , "the container requires libkrun but it's not available" );
246+
247+ // We no longer need the libkrun-sev handle.
248+ ret = dlclose (kconf -> handle_sev );
249+ if (UNLIKELY (ret != 0 ))
250+ return crun_make_error (err , 0 , "could not unload handle: `%s`" , dlerror ());
251+
252+ kconf -> sev = false;
253+ }
254+
255+ return 0 ;
256+ }
257+
192258static int
193259libkrun_exec (void * cookie , libcrun_container_t * container , const char * pathname , char * const argv [])
194260{
@@ -206,23 +272,18 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
206272 cpu_set_t set ;
207273 libcrun_error_t err ;
208274 bool configured = false;
275+ yajl_val config_tree = NULL ;
209276
210- if (access (KRUN_SEV_FILE , F_OK ) == 0 )
211- {
212- if (kconf -> handle_sev == NULL )
213- error (EXIT_FAILURE , 0 , "the container requires libkrun-sev but it's not available" );
214- handle = kconf -> handle_sev ;
215- ctx_id = kconf -> ctx_id_sev ;
216- kconf -> sev = true;
217- }
218- else
219- {
220- if (kconf -> handle == NULL )
221- error (EXIT_FAILURE , 0 , "the container requires libkrun but it's not available" );
222- handle = kconf -> handle ;
223- ctx_id = kconf -> ctx_id ;
224- kconf -> sev = false;
225- }
277+ ret = libkrun_read_vm_config (& config_tree , & err );
278+ if (UNLIKELY (ret < 0 ))
279+ error (EXIT_FAILURE , - ret , "libkrun VM config exists, but unable to parse" );
280+
281+ ret = libkrun_configure_flavor (cookie , & config_tree , & err );
282+ if (UNLIKELY (ret < 0 ))
283+ error (EXIT_FAILURE , - ret , "unable to configure libkrun flavor" );
284+
285+ handle = kconf -> handle ;
286+ ctx_id = kconf -> ctx_id ;
226287
227288 krun_set_log_level = dlsym (handle , "krun_set_log_level" );
228289 krun_start_enter = dlsym (handle , "krun_start_enter" );
@@ -259,7 +320,7 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
259320 error (EXIT_FAILURE , - ret , "could not set krun root" );
260321 }
261322
262- ret = libkrun_configure_vm (ctx_id , handle , & configured , & err );
323+ ret = libkrun_configure_vm (ctx_id , handle , & configured , & config_tree , & err );
263324 if (UNLIKELY (ret ))
264325 {
265326 libcrun_error_t * tmp_err = & err ;
@@ -295,6 +356,8 @@ libkrun_exec (void *cookie, libcrun_container_t *container, const char *pathname
295356 error (EXIT_FAILURE , - ret , "could not set krun vm configuration" );
296357 }
297358
359+ yajl_tree_free (config_tree );
360+
298361 ret = krun_start_enter (ctx_id );
299362 return - ret ;
300363}
@@ -467,12 +530,6 @@ libkrun_unload (void *cookie, libcrun_error_t *err)
467530 if (UNLIKELY (r != 0 ))
468531 return crun_make_error (err , 0 , "could not unload handle: `%s`" , dlerror ());
469532 }
470- if (kconf -> handle_sev != NULL )
471- {
472- r = dlclose (kconf -> handle_sev );
473- if (UNLIKELY (r != 0 ))
474- return crun_make_error (err , 0 , "could not unload handle_sev: `%s`" , dlerror ());
475- }
476533 }
477534 return 0 ;
478535}
0 commit comments