@@ -399,6 +399,71 @@ static int strverscmpp(char *const* a, char *const* b) {
399399 return strverscmp (* a , * b );
400400}
401401
402+ static int validate_version (
403+ const char * root ,
404+ const char * name ,
405+ const char * host_os_release_id ,
406+ const char * host_os_release_version_id ,
407+ const char * host_os_release_sysext_level ) {
408+
409+ _cleanup_free_ char * extension_release_id = NULL , * extension_release_version_id = NULL , * extension_release_sysext_level = NULL ;
410+ int r ;
411+
412+ assert (root );
413+ assert (name );
414+
415+ /* Insist that extension images do not overwrite the underlying OS release file (it's fine if
416+ * they place one in /etc/os-release, i.e. where things don't matter, as they aren't
417+ * merged.) */
418+ r = chase_symlinks ("/usr/lib/os-release" , root , CHASE_PREFIX_ROOT , NULL , NULL );
419+ if (r < 0 ) {
420+ if (r != - ENOENT )
421+ return log_error_errno (r , "Failed to determine whether /usr/lib/os-release exists in the extension image: %m" );
422+ } else
423+ return log_error_errno (SYNTHETIC_ERRNO (EINVAL ),
424+ "Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing." );
425+
426+ /* Now that we can look into the extension image, let's see if the OS version is compatible */
427+ r = parse_extension_release (
428+ root ,
429+ name ,
430+ "ID" , & extension_release_id ,
431+ "VERSION_ID" , & extension_release_version_id ,
432+ "SYSEXT_LEVEL" , & extension_release_sysext_level ,
433+ NULL );
434+ if (r == - ENOENT ) {
435+ log_notice_errno (r , "Extension '%s' carries no extension-release data, ignoring extension." , name );
436+ return 0 ;
437+ }
438+ if (r < 0 )
439+ return log_error_errno (r , "Failed to acquire 'os-release' data of extension '%s': %m" , name );
440+
441+ if (!streq_ptr (host_os_release_id , extension_release_id )) {
442+ log_notice ("Extension '%s' is for OS '%s', but running on '%s', ignoring extension." ,
443+ name , strna (extension_release_id ), strna (host_os_release_id ));
444+ return 0 ;
445+ }
446+
447+ /* If the extension has a sysext API level declared, then it must match the host API
448+ * level. Otherwise, compare OS version as a whole */
449+ if (extension_release_sysext_level ) {
450+ if (!streq_ptr (host_os_release_sysext_level , extension_release_sysext_level )) {
451+ log_notice ("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension." ,
452+ name , extension_release_sysext_level , strna (host_os_release_sysext_level ));
453+ return 0 ;
454+ }
455+ } else {
456+ if (!streq_ptr (host_os_release_version_id , extension_release_version_id )) {
457+ log_notice ("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension." ,
458+ name , extension_release_version_id , strna (host_os_release_version_id ));
459+ return 0 ;
460+ }
461+ }
462+
463+ log_debug ("Version info of extension '%s' matches host." , name );
464+ return 1 ;
465+ }
466+
402467static int merge_subprocess (Hashmap * images , const char * workspace ) {
403468 _cleanup_free_ char * host_os_release_id = NULL , * host_os_release_version_id = NULL , * host_os_release_sysext_level = NULL ,
404469 * buf = NULL ;
@@ -440,8 +505,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
440505
441506 /* Let's now mount all images */
442507 HASHMAP_FOREACH (img , images ) {
443- _cleanup_free_ char * p = NULL ,
444- * extension_release_id = NULL , * extension_release_version_id = NULL , * extension_release_sysext_level = NULL ;
508+ _cleanup_free_ char * p = NULL ;
445509
446510 p = path_join (workspace , "extensions" , img -> name );
447511 if (!p )
@@ -523,57 +587,17 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
523587 assert_not_reached ("Unsupported image type" );
524588 }
525589
526- /* Insist that extension images do not overwrite the underlying OS release file (it's fine if
527- * they place one in /etc/os-release, i.e. where things don't matter, as they aren't
528- * merged.) */
529- r = chase_symlinks ("/usr/lib/os-release" , p , CHASE_PREFIX_ROOT , NULL , NULL );
530- if (r < 0 ) {
531- if (r != - ENOENT )
532- return log_error_errno (r , "Failed to determine whether /usr/lib/os-release exists in the extension image: %m" );
533- } else
534- return log_error_errno (SYNTHETIC_ERRNO (EINVAL ),
535- "Extension image contains /usr/lib/os-release file, which is not allowed (it may carry /etc/os-release), refusing." );
536-
537- /* Now that we can look into the extension image, let's see if the OS version is compatible */
538- r = parse_extension_release (
590+ r = validate_version (
539591 p ,
540592 img -> name ,
541- "ID" , & extension_release_id ,
542- "VERSION_ID" , & extension_release_version_id ,
543- "SYSEXT_LEVEL" , & extension_release_sysext_level ,
544- NULL );
545- if ( r == - ENOENT ) {
546- log_notice_errno ( r , "Extension '%s' carries no extension-release data, ignoring extension." , img -> name );
593+ host_os_release_id ,
594+ host_os_release_version_id ,
595+ host_os_release_sysext_level );
596+ if ( r < 0 )
597+ return r ;
598+ if ( r == 0 ) {
547599 n_ignored ++ ;
548600 continue ;
549- } else if (r < 0 )
550- return log_error_errno (r , "Failed to acquire 'os-release' data of extension '%s': %m" , img -> name );
551- else {
552- if (!streq_ptr (host_os_release_id , extension_release_id )) {
553- log_notice ("Extension '%s' is for OS '%s', but running on '%s', ignoring extension." ,
554- img -> name , strna (extension_release_id ), strna (host_os_release_id ));
555- n_ignored ++ ;
556- continue ;
557- }
558-
559- /* If the extension has a sysext API level declared, then it must match the host API level. Otherwise, compare OS version as a whole */
560- if (extension_release_sysext_level ) {
561- if (!streq_ptr (host_os_release_sysext_level , extension_release_sysext_level )) {
562- log_notice ("Extension '%s' is for sysext API level '%s', but running on sysext API level '%s', ignoring extension." ,
563- img -> name , extension_release_sysext_level , strna (host_os_release_sysext_level ));
564- n_ignored ++ ;
565- continue ;
566- }
567- } else {
568- if (!streq_ptr (host_os_release_version_id , extension_release_version_id )) {
569- log_notice ("Extension '%s' is for OS version '%s', but running on OS version '%s', ignoring extension." ,
570- img -> name , extension_release_version_id , strna (host_os_release_version_id ));
571- n_ignored ++ ;
572- continue ;
573- }
574- }
575-
576- log_debug ("Version info of extension '%s' matches host." , img -> name );
577601 }
578602
579603 /* Noice! This one is an extension we want. */
0 commit comments