summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2022-02-18 18:51:53 +0000
committerLaurent Bercot <ska@appnovation.com>2022-02-18 18:51:53 +0000
commitdbbf64f5e5ff8f5cc3c2e6432f74cf6c27fe3362 (patch)
tree5f4b7cd2537b24db6049168ceb12cba8b9fbcfb1
parent217964474a39f8ab2c8eec9f188546d84570c3a3 (diff)
downloads6-linux-init-dbbf64f5e5ff8f5cc3c2e6432f74cf6c27fe3362.tar.xz
Transmit console to stage2. Read stage1 envdir verbatim.
Signed-off-by: Laurent Bercot <ska@appnovation.com>
-rw-r--r--src/init/s6-linux-init.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/src/init/s6-linux-init.c b/src/init/s6-linux-init.c
index c7873be..4fcbdcb 100644
--- a/src/init/s6-linux-init.c
+++ b/src/init/s6-linux-init.c
@@ -87,6 +87,24 @@ static void kbspecials (void)
strerr_warnwu1sys("trap ctrl-alt-del") ;
}
+static void opendevnull (void)
+{
+ if (open("/dev/null", O_RDONLY))
+ { /* ghetto /dev/null to the rescue */
+ int p[2] ;
+ strerr_warnwu1sys("open /dev/null") ;
+ if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ;
+ close(p[1]) ;
+ if (fd_move(0, p[0]) < 0) strerr_diefu1sys(111, "fd_move to stdin") ;
+ }
+}
+
+static void reset_stdin (void)
+{
+ close(0) ;
+ opendevnull() ;
+}
+
static inline void run_stage2 (char const *basedir, char const **argv, unsigned int argc, char const *const *envp, size_t envlen, char const *modifs, size_t modiflen, char const *initdefault, char const *tty)
{
size_t dirlen = strlen(basedir) ;
@@ -97,12 +115,11 @@ static inline void run_stage2 (char const *basedir, char const **argv, unsigned
if (setsid() == -1) strerr_diefu1sys(111, "setsid") ;
if (tty)
{
- int fd = openb_read(tty) ;
- if (fd == -1) strerr_warnwu2sys("open ", tty) ;
- else if (fd_move(0, fd) == -1)
+ close(0) ;
+ if (openb_read(tty))
{
- strerr_warnwu3sys("make ", tty, " into new stdin") ;
- close(fd) ;
+ strerr_warnwu2sys("open ", tty) ;
+ opendevnull() ;
}
}
memcpy(fn, basedir, dirlen) ;
@@ -196,37 +213,33 @@ int main (int argc, char const **argv, char const *const *envp)
else if (hasconsole) allwrite(1, BANNER, sizeof(BANNER) - 1) ;
if (chdir("/") == -1) strerr_diefu1sys(111, "chdir to /") ;
umask(mask) ;
- close(0) ;
if (slashdev)
{
int nope, e ;
+ close(0) ;
close(1) ;
close(2) ;
/* at this point we're totally in the dark, hoping /dev/console will work */
nope = mount("dev", slashdev, "devtmpfs", MS_NOSUID | MS_NOEXEC, "") < 0 ;
e = errno ;
if (open("/dev/console", O_WRONLY) && open("/dev/null", O_WRONLY)) return 111 ;
- if (fd_move(2, 0) < 0 || fd_copy(1, 2) < 0) return 111 ;
+ if (fd_move(2, 0) < 0) return 111 ;
+ if (fd_copy(1, 2) < 0) strerr_diefu1sys(111, "fd_copy") ;
if (nope)
{
errno = e ;
strerr_diefu1sys(111, "mount a devtmpfs on /dev") ;
}
- }
-
- if (open("/dev/null", O_RDONLY))
- { /* ghetto /dev/null to the rescue */
- int p[2] ;
- strerr_warnwu1sys("open /dev/null") ;
- if (pipe(p) < 0) strerr_diefu1sys(111, "pipe") ;
- close(p[1]) ;
- if (fd_move(0, p[0]) < 0) strerr_diefu1sys(111, "fd_move to stdin") ;
+ if (open("/dev/console", O_RDONLY)) opendevnull() ;
}
if (!hasconsole)
+ {
+ if (!slashdev) reset_stdin() ;
if (open("/dev/null", O_WRONLY) != 1 || fd_copy(2, 1) == -1)
return 111 ;
+ }
if (mounttype)
{
@@ -256,7 +269,7 @@ int main (int argc, char const **argv, char const *const *envp)
if (!hiercopy(fn, S6_LINUX_INIT_TMPFS))
strerr_diefu3sys(111, "copy ", fn, " to " S6_LINUX_INIT_TMPFS) ;
memcpy(fn + dirlen + 1, ENVSTAGE1, sizeof(ENVSTAGE1)) ;
- if (envdir(fn, &envmodifs) == -1)
+ if (envdir_verbatim_chomp(fn, &envmodifs) == -1)
strerr_warnwu2sys("envdir ", fn) ;
}
if (envdumpdir && !env_dump(envdumpdir, 0700, envp))
@@ -287,12 +300,13 @@ int main (int argc, char const **argv, char const *const *envp)
newenvp[0] = pathvar ;
}
if (nologger && pipe(notifpipe) < 0) strerr_diefu1sys(111, "pipe") ;
- if (tty && ioctl(1, TIOCNOTTY) == -1) strerr_warnwu1sys("relinquish control terminal") ;
+ if (tty && !slashdev && ioctl(1, TIOCNOTTY) == -1) strerr_warnwu1sys("relinquish control terminal") ;
pid = fork() ;
if (pid == -1) strerr_diefu1sys(111, "fork") ;
if (!pid) run_stage2(basedir, argv, argc, newenvp, !!path, envmodifs.s, envmodifs.len, initdefault, tty) ;
+ reset_stdin() ;
setsid() ; /* just in case our caller is something weird */
if (nologger)
{