[LEDE-DEV] [RFC 09/13] procd: init: add support for sysupgrades triggered from preinit
Matthias Schiffer
mschiffer at universe-factory.net
Sun Apr 23 17:06:58 PDT 2017
This will allow to add sysupgrade support via upgraded for failsafe mode.
Signed-off-by: Matthias Schiffer <mschiffer at universe-factory.net>
Note: obviously, this patch should go into the procd repo when it is
actually applied; it is provided like this for now to allow easier testing
of the whole series.
---
...pport-for-sysupgrades-triggered-from-prei.patch | 272 +++++++++++++++++++++
1 file changed, 272 insertions(+)
create mode 100644 package/system/procd/patches/0005-init-add-support-for-sysupgrades-triggered-from-prei.patch
diff --git a/package/system/procd/patches/0005-init-add-support-for-sysupgrades-triggered-from-prei.patch b/package/system/procd/patches/0005-init-add-support-for-sysupgrades-triggered-from-prei.patch
new file mode 100644
index 0000000000..bbd7b6dd92
--- /dev/null
+++ b/package/system/procd/patches/0005-init-add-support-for-sysupgrades-triggered-from-prei.patch
@@ -0,0 +1,272 @@
+From 49970e3f3c5c4ba35b6566e52104cacfc9d3e939 Mon Sep 17 00:00:00 2001
+Message-Id: <49970e3f3c5c4ba35b6566e52104cacfc9d3e939.1492987636.git.mschiffer at universe-factory.net>
+In-Reply-To: <3462ccc0c91964ec92c1c61cde803a6504b2fb24.1492987636.git.mschiffer at universe-factory.net>
+References: <3462ccc0c91964ec92c1c61cde803a6504b2fb24.1492987636.git.mschiffer at universe-factory.net>
+From: Matthias Schiffer <mschiffer at universe-factory.net>
+Date: Mon, 24 Apr 2017 00:40:27 +0200
+Subject: [PATCH 5/5] init: add support for sysupgrades triggered from preinit
+
+This will allow to add sysupgrade support via upgraded for failsafe mode.
+
+Signed-off-by: Matthias Schiffer <mschiffer at universe-factory.net>
+---
+ CMakeLists.txt | 4 ++--
+ initd/preinit.c | 46 +++++++++++++++++++++++++++++++++++++++++-----
+ system.c | 35 ++++-------------------------------
+ sysupgrade.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
+ sysupgrade.h | 15 +++++++++++++++
+ watchdog.h | 2 ++
+ 6 files changed, 113 insertions(+), 38 deletions(-)
+ create mode 100644 sysupgrade.c
+ create mode 100644 sysupgrade.h
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 0729459..7d05e97 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -18,7 +18,7 @@ INSTALL(TARGETS setlbf
+ )
+
+
+-SET(SOURCES procd.c signal.c state.c inittab.c rcS.c ubus.c system.c
++SET(SOURCES procd.c signal.c state.c inittab.c rcS.c ubus.c system.c sysupgrade.c
+ service/service.c service/instance.c service/validate.c service/trigger.c service/watch.c
+ utils/utils.c)
+ IF(NOT DISABLE_INIT)
+@@ -54,7 +54,7 @@ INCLUDE_DIRECTORIES(${ubox_include_dir})
+ IF(DISABLE_INIT)
+ ADD_DEFINITIONS(-DDISABLE_INIT)
+ ELSE()
+-ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c watchdog.c
++ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c sysupgrade.c watchdog.c
+ utils/utils.c ${SOURCES_ZRAM})
+ TARGET_LINK_LIBRARIES(init ${LIBS})
+ INSTALL(TARGETS init
+diff --git a/initd/preinit.c b/initd/preinit.c
+index 729978e..dda6576 100644
+--- a/initd/preinit.c
++++ b/initd/preinit.c
+@@ -27,6 +27,7 @@
+
+ #include "init.h"
+ #include "../watchdog.h"
++#include "../sysupgrade.h"
+
+ static struct uloop_process preinit_proc;
+ static struct uloop_process plugd_proc;
+@@ -49,23 +50,58 @@ check_dbglvl(void)
+ }
+
+ static void
++check_sysupgrade(void)
++{
++ char *prefix = NULL, *path = NULL, *command = NULL;
++ size_t n;
++
++ if (chdir("/"))
++ return;
++
++ FILE *sysupgrade = fopen("/tmp/sysupgrade", "r");
++ if (!sysupgrade)
++ return;
++
++ n = 0;
++ if (getdelim(&prefix, &n, 0, sysupgrade) < 0)
++ goto fail;
++ n = 0;
++ if (getdelim(&path, &n, 0, sysupgrade) < 0)
++ goto fail;
++ n = 0;
++ if (getdelim(&command, &n, 0, sysupgrade) < 0)
++ goto fail;
++
++ fclose(sysupgrade);
++
++ sysupgrade_exec_upgraded(prefix, path, command);
++
++ while (true)
++ sleep(1);
++
++fail:
++ fclose(sysupgrade);
++ free(prefix);
++ free(path);
++ free(command);
++}
++
++static void
+ spawn_procd(struct uloop_process *proc, int ret)
+ {
+ char *wdt_fd = watchdog_fd();
+ char *argv[] = { "/sbin/procd", NULL};
+- struct stat s;
+ char dbg[2];
+
+ if (plugd_proc.pid > 0)
+ kill(plugd_proc.pid, SIGKILL);
+
+- if (!stat("/tmp/sysupgrade", &s))
+- while (true)
+- sleep(1);
+-
+ unsetenv("INITRAMFS");
+ unsetenv("PREINIT");
+ unlink("/tmp/.preinit");
++
++ check_sysupgrade();
++
+ DEBUG(2, "Exec to real procd now\n");
+ if (wdt_fd)
+ setenv("WDTFD", wdt_fd, 1);
+diff --git a/system.c b/system.c
+index dc509ff..8b8cdbc 100644
+--- a/system.c
++++ b/system.c
+@@ -28,6 +28,7 @@
+ #include <libubox/uloop.h>
+
+ #include "procd.h"
++#include "sysupgrade.h"
+ #include "watchdog.h"
+
+ static struct blob_buf b;
+@@ -346,34 +347,6 @@ static const struct blobmsg_policy sysupgrade_policy[__SYSUPGRADE_MAX] = {
+ [SYSUPGRADE_COMMAND] = { .name = "command", .type = BLOBMSG_TYPE_STRING },
+ };
+
+-static void
+-procd_exec_upgraded(const char *prefix, char *path, char *command)
+-{
+- char *wdt_fd = watchdog_fd();
+- char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
+-
+- if (chroot(prefix)) {
+- fprintf(stderr, "Failed to chroot for upgraded exec.\n");
+- return;
+- }
+-
+- argv[1] = path;
+- argv[2] = command;
+-
+- DEBUG(2, "Exec to upgraded now\n");
+- if (wdt_fd) {
+- watchdog_set_cloexec(false);
+- setenv("WDTFD", wdt_fd, 1);
+- }
+- execvp(argv[0], argv);
+-
+- /* Cleanup on failure */
+- fprintf(stderr, "Failed to exec upgraded.\n");
+- unsetenv("WDTFD");
+- watchdog_set_cloexec(true);
+- chroot(".");
+-}
+-
+ static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+@@ -387,9 +360,9 @@ static int sysupgrade(struct ubus_context *ctx, struct ubus_object *obj,
+ if (!tb[SYSUPGRADE_PATH] || !tb[SYSUPGRADE_PREFIX])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+- procd_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]),
+- blobmsg_get_string(tb[SYSUPGRADE_PATH]),
+- tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL);
++ sysupgrade_exec_upgraded(blobmsg_get_string(tb[SYSUPGRADE_PREFIX]),
++ blobmsg_get_string(tb[SYSUPGRADE_PATH]),
++ tb[SYSUPGRADE_COMMAND] ? blobmsg_get_string(tb[SYSUPGRADE_COMMAND]) : NULL);
+ return 0;
+ }
+
+diff --git a/sysupgrade.c b/sysupgrade.c
+new file mode 100644
+index 0000000..30f1836
+--- /dev/null
++++ b/sysupgrade.c
+@@ -0,0 +1,49 @@
++/*
++ * Copyright (C) 2013 Felix Fietkau <nbd at openwrt.org>
++ * Copyright (C) 2013 John Crispin <blogic at openwrt.org>
++ * Copyright (C) 2017 Matthias Schiffer <mschiffer at universe-factory.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++
++#include "watchdog.h"
++#include "sysupgrade.h"
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++
++
++void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command)
++{
++ char *wdt_fd = watchdog_fd();
++ char *argv[] = { "/sbin/upgraded", NULL, NULL, NULL};
++
++ if (chroot(prefix)) {
++ fprintf(stderr, "Failed to chroot for upgraded exec.\n");
++ return;
++ }
++
++ argv[1] = path;
++ argv[2] = command;
++
++ if (wdt_fd) {
++ watchdog_set_cloexec(false);
++ setenv("WDTFD", wdt_fd, 1);
++ }
++ execvp(argv[0], argv);
++
++ /* Cleanup on failure */
++ fprintf(stderr, "Failed to exec upgraded.\n");
++ unsetenv("WDTFD");
++ watchdog_set_cloexec(true);
++ chroot(".");
++}
+diff --git a/sysupgrade.h b/sysupgrade.h
+new file mode 100644
+index 0000000..2122f36
+--- /dev/null
++++ b/sysupgrade.h
+@@ -0,0 +1,15 @@
++/*
++ * Copyright (C) 2017 Matthias Schiffer <mschiffer at universe-factory.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 2.1
++ * as published by the Free Software Foundation
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ */
++
++
++void sysupgrade_exec_upgraded(const char *prefix, char *path, char *command);
+diff --git a/watchdog.h b/watchdog.h
+index 641e7e1..3c4a487 100644
+--- a/watchdog.h
++++ b/watchdog.h
+@@ -15,6 +15,8 @@
+ #ifndef __PROCD_WATCHDOG_H
+ #define __PROCD_WATCHDOG_H
+
++#include <stdbool.h>
++
+ #ifndef DISABLE_INIT
+ void watchdog_init(int preinit);
+ char* watchdog_fd(void);
+--
+2.12.2
+
--
2.12.2
More information about the Lede-dev
mailing list