[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