From e6cdcf8aa18381bcf00e83ef93bf10031049997a Mon Sep 17 00:00:00 2001 From: Patrick McCarty Date: Tue, 11 Apr 2017 16:36:53 -0700 Subject: [PATCH] verify: enforce format transitions When using verify's -m option, it generally only makes sense to verify a build within the same format, since the subsequent format (if any) might not be compatible. Therefore, we should disallow verifying to a build with a different format by default. This commit adds the proper enforcement by making this condition a fatal error. The early exit can be bypassed using the -x/--force option, which will print a warning message instead. For now, this compatibility check is targeting the use case of verifying to a newer build, so I also report the latest supported build for the current format. Verifying to an older build is not guaranteed to succeed at present, and swupd-client does not yet understand the version/formatN/first file. In other words, reporting to the user the oldest build they can verify to will be a future improvement. Signed-off-by: Patrick McCarty --- include/swupd.h | 1 + src/helpers.c | 25 +++++++++++++++++++++++++ src/verify.c | 17 +++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/swupd.h b/include/swupd.h index 573e9dbc..1d03a315 100644 --- a/include/swupd.h +++ b/include/swupd.h @@ -331,6 +331,7 @@ extern struct list *files_from_bundles(struct list *bundles); extern bool version_files_consistent(void); extern bool string_in_list(char *string_to_check, struct list *list_to_check); extern void print_progress(unsigned int count, unsigned int max); +extern bool is_compatible_format(int format_num); /* subscription.c */ struct list *free_list_file(struct list *item); diff --git a/src/helpers.c b/src/helpers.c index 30dcd6aa..6cfe1192 100644 --- a/src/helpers.c +++ b/src/helpers.c @@ -965,3 +965,28 @@ void print_progress(unsigned int count, unsigned int max) } } } + +/* Compare formats of the global variable (format_string) and the format number + * from a manifest (usually a MoM). Because "staging" is treated specially and + * never appears in a manifest, it is skipped. */ +bool is_compatible_format(int format_num) +{ + if (strcmp(format_string, "staging") == 0) { + return true; + } + + char *format_manifest = NULL; + string_or_die(&format_manifest, "%d", format_num); + + size_t len = strlen(format_string); + + bool ret; + if (strncmp(format_string, format_manifest, len) == 0) { + ret = true; + } else { + ret = false; + } + + free(format_manifest); + return ret; +} diff --git a/src/verify.c b/src/verify.c index eaf6660f..f288cae8 100644 --- a/src/verify.c +++ b/src/verify.c @@ -702,6 +702,23 @@ int verify_main(int argc, char **argv) goto clean_and_exit; } + if (!is_compatible_format(official_manifest->manifest_version)) { + if (force) { + fprintf(stderr, "WARNING: the force option is specified; ignoring" + " format mismatch for verify\n"); + } else { + fprintf(stderr, "ERROR: Mismatching formats detected when verifying %d" + " (expected: %s; actual: %d)\n", + version, format_string, official_manifest->manifest_version); + int latest = get_latest_version(); + if (latest > 0) { + fprintf(stderr, "Latest supported version to verify: %d\n", latest); + } + ret = EMANIFEST_LOAD; + goto clean_and_exit; + } + } + ret = add_included_manifests(official_manifest, version, &subs); if (ret) { ret = EMANIFEST_LOAD;