From 968f1bf9910ec533b6570589555eeb17d20a3820 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Thu, 28 Jul 2016 23:41:01 +0200 Subject: [PATCH] The science of unmounting file systems on Debian That's maybe a bit unfair. This patch implements a brief version of what is really needed to safely unmount all file systems on a modern Linux distribution. Yes, it's this insane. (Who am I kidding, it's worse! Just have a look at the ancient scrolls hidden in your /etc!) Here is where we use the new plugin_exit() and api_exit() API's from an earlier patch. Making sure to exit and close any kernel descriptors. Then follows a bizarre spell cast on leaking descriptors, rebooting in a child, remounting / as read-only, and a whole slew of other R rated stuff to prevent mount/umount from returning 32 ... Stay safe people, use protection always! Signed-off-by: Joachim Nilsson --- sig.c | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/sig.c b/sig.c index 4934eb0a..84c24b3a 100644 --- a/sig.c +++ b/sig.c @@ -88,18 +88,48 @@ void do_shutdown(int sig) _d("Sending SIGKILL to remaining processes."); kill(-1, SIGKILL); - sync(); - sync(); - _d("Unmounting file systems, remounting / read-only."); - run("/bin/umount -fa 2>/dev/null"); - run("/bin/mount -n -o remount,ro / 2>/dev/null"); - run("/sbin/swapoff -ea"); + debug = 1; + plugin_exit(); + api_exit(); + + /* Reap 'em */ + while (waitpid(-1, NULL, WNOHANG) > 0) + ; + + /* Close all local non-console descriptors */ + for (int fd = 3; fd < 128; fd++) + close(fd); + + if (vfork()) { + /* + * Put PID 1 aside and let child perform reboot/halt + * kernel may exit child and we don't want to exit PID 1 + * ... causing "aiii killing init" during reboot ... + */ + return; + } + + /* Unmount any tmpfs before unmounting swap ... */ + run("/bin/umount -r -a"); + run("/sbin/swapoff -e -a"); + + /* Now, unmount everything else ... err, just force it. */ + run("/bin/umount -n -f -r -a"); + + /* We sit on / so we must remount it ro, try all the things! */ + run("/bin/mount -n -o remount,ro -t dummytype dummydev /"); + run("/bin/mount -n -o remount,ro dummydev /"); + run("/bin/mount -n -o remount,ro /"); + + _e("PID %d: %s ...", getpid(), sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting"); + do_sleep(5); _d("%s.", sig == SIGINT || sig == SIGUSR1 ? "Rebooting" : "Halting"); if (sig == SIGINT || sig == SIGUSR1) reboot(RB_AUTOBOOT); reboot(RB_POWER_OFF); + reboot(RB_HALT_SYSTEM); /* Eh, what? Should not get here ... */ } /*