Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 09 May 2002 17:15:17 +0000
From:      Tony Finch <dot@dotat.at>
To:        freebsd-audit@freebsd.org
Subject:   correct error handling in reboot(8)
Message-ID:  <E175rVd-000JbC-00@hand.dotat.at>

next in thread | raw e-mail | index | archive | help

I just noticed when looking at reboot(8) following the killall rant in
the recent RISKS that there a number of cases after SIGSTOPping init
in which it may abort calling err() but fail to restart init. This
patch uses atexit() to ensure that init is restarted if things go wrong.
The same problem and fix apply to -STABLE.

Index: reboot.c
===================================================================
RCS file: /home/ncvs/src/sbin/reboot/reboot.c,v
retrieving revision 1.15
diff -u -r1.15 reboot.c
--- reboot.c	26 Apr 2002 22:32:15 -0000	1.15
+++ reboot.c	9 May 2002 17:03:58 -0000
@@ -60,8 +60,9 @@
 #include <string.h>
 #include <unistd.h>
 
-void usage(void);
 u_int get_pageins(void);
+void restart_init(void);
+void usage(void);
 
 int dohalt;
 
@@ -69,7 +70,7 @@
 main(int argc, char *argv[])
 {
 	struct passwd *pw;
-	int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag, sverrno;
+	int ch, howto, i, fd, kflag, lflag, nflag, qflag, pflag;
 	u_int pageins;
 	char *kernel, *p;
 	const char *user;
@@ -156,6 +157,8 @@
 		sync();
 
 	/* Just stop init -- if we fail, we'll restart it. */
+	if (atexit(restart_init) == -1)
+		err(1, "atexit");
 	if (kill(1, SIGTSTP) == -1)
 		err(1, "SIGTSTP init");
 
@@ -187,24 +190,28 @@
 		if (kill(-1, SIGKILL) == -1) {
 			if (errno == ESRCH)
 				break;
-			goto restart;
+			err(1, "killall");
 		}
 		if (i > 5) {
-			(void)fprintf(stderr,
-			    "WARNING: some process(es) wouldn't die\n");
+			warnx("WARNING: some process(es) wouldn't die");
 			break;
 		}
 		(void)sleep(2 * i);
 	}
 
+	/*
+	 * If the reboot() succeeds then we never get control back,
+	 * otherwise we exit via some error reporting and restart_init().
+	 */
 	reboot(howto);
-	/* FALLTHROUGH */
+	err(1, "reboot failed");
+}
 
-restart:
-	sverrno = errno;
-	errx(1, "%s%s", kill(1, SIGHUP) == -1 ? "(can't restart init): " : "",
-	    strerror(sverrno));
-	/* NOTREACHED */
+void
+restart_init()
+{
+	if (kill(1, SIGHUP) == -1)
+		warn("can't restart init");
 }
 
 void

Tony.
-- 
f.a.n.finch <dot@dotat.at> http://dotat.at/
CROMARTY FORTH TYNE DOGGER: NORTHEASTERLY 3 OR 4, OCCASIONALLY 5. PATCHY RAIN
AT FIRST. MODERATE OR GOOD WITH FOG PATCHES.

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-audit" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E175rVd-000JbC-00>