From owner-freebsd-audit Thu May 9 10:15:26 2002 Delivered-To: freebsd-audit@freebsd.org Received: from hand.dotat.at (host217-34-79-171.in-addr.btopenworld.com [217.34.79.171]) by hub.freebsd.org (Postfix) with ESMTP id EC89C37B404 for ; Thu, 9 May 2002 10:15:20 -0700 (PDT) Received: from fanf by hand.dotat.at with local (Exim 3.35 #1) id 175rVd-000JbC-00 for freebsd-audit@freebsd.org; Thu, 09 May 2002 17:15:17 +0000 From: Tony Finch To: freebsd-audit@freebsd.org Subject: correct error handling in reboot(8) Message-Id: Date: Thu, 09 May 2002 17:15:17 +0000 Sender: owner-freebsd-audit@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG 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 #include -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 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