Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 32 additions & 11 deletions src/shared/os-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,17 @@ int path_is_os_tree(const char *path) {
return 1;
}

int open_os_release(const char *root, char **ret_path, int *ret_fd) {
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd) {
_cleanup_free_ char *q = NULL;
const char *p;
char **paths, **p;
int r, fd;

FOREACH_STRING(p, "/etc/os-release", "/usr/lib/os-release") {
r = chase_symlinks(p, root, CHASE_PREFIX_ROOT,
if (extension)
paths = STRV_MAKE(strjoina("/usr/lib/extension-release.d/extension-release.", extension));
else
paths = STRV_MAKE("/etc/os-release", "/usr/lib/os-release");
STRV_FOREACH(p, paths) {
r = chase_symlinks(*p, root, CHASE_PREFIX_ROOT,
ret_path ? &q : NULL,
ret_fd ? &fd : NULL);
if (r != -ENOENT)
Expand All @@ -64,16 +68,16 @@ int open_os_release(const char *root, char **ret_path, int *ret_fd) {
return 0;
}

int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file) {
_cleanup_free_ char *p = NULL;
_cleanup_close_ int fd = -1;
FILE *f;
int r;

if (!ret_file)
return open_os_release(root, ret_path, NULL);
return open_extension_release(root, extension, ret_path, NULL);

r = open_os_release(root, ret_path ? &p : NULL, &fd);
r = open_extension_release(root, extension, ret_path ? &p : NULL, &fd);
if (r < 0)
return r;

Expand All @@ -89,18 +93,35 @@ int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
return 0;
}

int parse_os_release(const char *root, ...) {
static int parse_release_internal(const char *root, const char *extension, va_list ap) {
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *p = NULL;
va_list ap;
int r;

r = fopen_os_release(root, &p, &f);
r = fopen_extension_release(root, extension, &p, &f);
if (r < 0)
return r;

return parse_env_filev(f, p, ap);
}

int parse_extension_release(const char *root, const char *extension, ...) {
va_list ap;
int r;

va_start(ap, extension);
r = parse_release_internal(root, extension, ap);
va_end(ap);

return r;
}

int parse_os_release(const char *root, ...) {
va_list ap;
int r;

va_start(ap, root);
r = parse_env_filev(f, p, ap);
r = parse_release_internal(root, NULL, ap);
va_end(ap);

return r;
Expand Down
14 changes: 12 additions & 2 deletions src/shared/os-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@

int path_is_os_tree(const char *path);

int open_os_release(const char *root, char **ret_path, int *ret_fd);
int fopen_os_release(const char *root, char **ret_path, FILE **ret_file);
/* The *_extension_release flavours will look for /usr/lib/extension-release/extension-release.NAME
* in accordance with the OS extension specification, rather than for /usr/lib/ or /etc/os-release. */
int open_extension_release(const char *root, const char *extension, char **ret_path, int *ret_fd);
static inline int open_os_release(const char *root, char **ret_path, int *ret_fd) {
return open_extension_release(root, NULL, ret_path, ret_fd);
}

int fopen_extension_release(const char *root, const char *extension, char **ret_path, FILE **ret_file);
static inline int fopen_os_release(const char *root, char **ret_path, FILE **ret_file) {
return fopen_extension_release(root, NULL, ret_path, ret_file);
}

int parse_extension_release(const char *root, const char *extension, ...) _sentinel_;
int parse_os_release(const char *root, ...) _sentinel_;
int load_os_release_pairs(const char *root, char ***ret);
int load_os_release_pairs_with_prefix(const char *root, const char *prefix, char ***ret);
17 changes: 13 additions & 4 deletions src/sysext/sysext.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,16 +455,24 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
_cleanup_(dissected_image_unrefp) DissectedImage *m = NULL;
_cleanup_(loop_device_unrefp) LoopDevice *d = NULL;
_cleanup_(decrypted_image_unrefp) DecryptedImage *di = NULL;
_cleanup_(verity_settings_done) VeritySettings verity_settings = VERITY_SETTINGS_DEFAULT;
DissectImageFlags flags = DISSECT_IMAGE_READ_ONLY|DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_MOUNT_ROOT_ONLY;

r = verity_settings_load(&verity_settings, img->path, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to read verity artifacts for %s: %m", img->path);

if (verity_settings.data_path)
flags |= DISSECT_IMAGE_NO_PARTITION_TABLE;

r = loop_device_make_by_path(img->path, O_RDONLY, 0, &d);
if (r < 0)
return log_error_errno(r, "Failed to set up loopback device: %m");

r = dissect_image_and_warn(
d->fd,
img->path,
NULL,
&verity_settings,
NULL,
flags,
&m);
Expand All @@ -473,7 +481,7 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {

r = dissected_image_decrypt_interactively(
m, NULL,
NULL,
&verity_settings,
flags,
&di);
if (r < 0)
Expand Down Expand Up @@ -501,14 +509,15 @@ static int merge_subprocess(Hashmap *images, const char *workspace) {
}

/* Now that we can look into the extension image, let's see of the OS version is compatible */
r = parse_os_release(
r = parse_extension_release(
p,
img->name,
"ID", &extension_os_release_id,
"VERSION_ID", &extension_os_release_version_id,
"SYSEXT_LEVEL", &extension_os_release_sysext_level,
NULL);
if (r == -ENOENT)
log_notice_errno(r, "Extension '%s' carries no os-release data, not checking for version compatibility.", img->name);
return log_notice_errno(r, "Extension '%s' carries no extension-release data, ignoring extension.", img->name);
else if (r < 0)
return log_error_errno(r, "Failed to acquire 'os-release' data of extension '%s': %m", img->name);
else {
Expand Down