From 27f9ec75b2518f072cca967f9f70b048e9f4f869 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 18 Aug 2021 22:14:18 +0200 Subject: [PATCH] autoupdater: execute sysupgrade test before network shutdown Currently the autoupdater stops network prior starting the sysupgrade process. This has the issue of leaving the device in a state with stopped network in case the sysupgrade process fails, as execl does not spawn a subprocess but instead replaces the current process with another one, in our case the sysupgrade process. This commit modifies the autoupdater behavior in a way it starts sysupgrade in test mode prior stopping network. This way, common causes for failing the sysupgrade process can be detected in a remote-recoverable manner, most prominently a failed platform check / incompatible images. Signed-off-by: David Bauer --- admin/autoupdater/src/autoupdater.c | 32 +++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/admin/autoupdater/src/autoupdater.c b/admin/autoupdater/src/autoupdater.c index 0b80c07..2f6a0f9 100644 --- a/admin/autoupdater/src/autoupdater.c +++ b/admin/autoupdater/src/autoupdater.c @@ -48,6 +48,7 @@ #include #include #include +#include #define MAX_LINE_LENGTH 512 @@ -275,6 +276,30 @@ static void recv_image_cb(struct uclient *cl) { } } +static int sysupgrade_image_check(const char *image_path) +{ + int status; + pid_t pid; + int ret; + + if ((pid = fork()) == 0) { + execl(sysupgrade_path, sysupgrade_path, "-T", firmware_path, NULL); + _exit(127); + } + + if (pid < 0) + return pid; + + ret = waitpid(pid, &status, 0); + if (ret < 0) + return -1; + + if (!WIFEXITED(status)) + return -1; + + return WEXITSTATUS(status); +} + static bool autoupdate(const char *mirror, struct settings *s, int lock_fd) { bool ret = false; @@ -380,6 +405,13 @@ static bool autoupdate(const char *mirror, struct settings *s, int lock_fd) { clear_manifest(m); + /* Test if the image is compatible with the device. This avoids bringing down services. */ + if (sysupgrade_image_check(firmware_path)) { + /* Image not compatible */ + fputs("autoupdater: error: image not compatible with device\n", stderr); + goto fail_after_download; + } + /**** Call sysupgrade ************************************************/ if (s->no_action) { printf(