about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2017-08-28 08:12:20 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2017-08-28 08:12:20 +0000
commitc29368d9e34fee0e2fe0fae2fdf2865580be4ae0 (patch)
tree066714d4ec6c52ea2bb450b0f84e7ffb9ebea0da
parent17c03cf8f0a6339d78ad8fb968ef3b999d658034 (diff)
downloads6-linux-init-c29368d9e34fee0e2fe0fae2fdf2865580be4ae0.tar.gz
s6-linux-init-c29368d9e34fee0e2fe0fae2fdf2865580be4ae0.tar.xz
s6-linux-init-c29368d9e34fee0e2fe0fae2fdf2865580be4ae0.zip
Add namespaces support, prepare for 0.3.1.0
-rw-r--r--COPYING2
-rw-r--r--INSTALL10
-rw-r--r--NEWS6
-rw-r--r--doc/index.html12
-rw-r--r--doc/s6-linux-init-maker.html11
-rw-r--r--doc/upgrade.html15
-rw-r--r--package/info2
-rw-r--r--src/init/hpr.c63
-rw-r--r--src/init/s6-linux-init-maker.c48
9 files changed, 149 insertions, 20 deletions
diff --git a/COPYING b/COPYING
index fabed3c..a34920e 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (c) 2015-2016 Laurent Bercot <ska-skaware@skarnet.org>
+Copyright (c) 2015-2017 Laurent Bercot <ska-skaware@skarnet.org>
 
 Permission to use, copy, modify, and distribute this software for any
 purpose with or without fee is hereby granted, provided that the above
diff --git a/INSTALL b/INSTALL
index f516bd6..5562636 100644
--- a/INSTALL
+++ b/INSTALL
@@ -6,15 +6,15 @@ Build Instructions
 
   - A Linux-based system with a standard C development environment
   - GNU make version 3.81 or later
-  - skalibs version 2.5.0.0 or later: http://skarnet.org/software/skalibs/
+  - skalibs version 2.6.0.0 or later: http://skarnet.org/software/skalibs/
 
  The scripts generated by the s6-linux-init-maker program have some
 additional dependencies:
 
-  - execline version 2.3.0.0 or later: http://skarnet.org/software/execline/
-  - s6-portable-utils version 2.2.0.0 or later: http://skarnet.org/software/s6-portable-utils/
-  - s6-linux-utils version 2.3.0.0 or later: http://skarnet.org/software/s6-linux-utils/
-  - s6 version 2.5.0.0 or later: http://skarnet.org/software/s6/
+  - execline version 2.3.0.2 or later: http://skarnet.org/software/execline/
+  - s6-portable-utils version 2.2.1.1 or later: http://skarnet.org/software/s6-portable-utils/
+  - s6-linux-utils version 2.4.0.0 or later: http://skarnet.org/software/s6-linux-utils/
+  - s6 version 2.6.1.0 or later: http://skarnet.org/software/s6/
 
  This software is Linux-specific. It will run on a Linux kernel,
 version 2.6.32 or later. However, it should not be too hard to port to
diff --git a/NEWS b/NEWS
index 3a1b074..e165197 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,11 @@
 Changelog for s6-linux-init.
 
+In 0.3.1.0
+----------
+
+ - Support for running in Linux containers
+
+
 In 0.3.0.0
 ----------
 
diff --git a/doc/index.html b/doc/index.html
index 4c1ff7d..dd93276 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -50,15 +50,15 @@ a small FAQ.
  <li> A Linux-based system with a standard C development environment </li>
  <li> GNU make, version 3.81 or later </li>
  <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
-2.5.0.0 or later </li>
+2.6.0.0 or later </li>
  <li> <a href="//skarnet.org/software/execline/">execline</a> version
-2.3.0.0 or later </li>
+2.3.0.2 or later </li>
  <li> <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a> version
-2.2.0.0 or later </li>
+2.2.1.1 or later </li>
  <li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a> version
-2.3.0.0 or later </li>
+2.4.0.0 or later </li>
  <li> <a href="//skarnet.org/software/s6/">s6</a> version
-2.5.0.0 or later </li>
+2.6.1.0 or later </li>
 </ul>
 
 <p>
@@ -87,7 +87,7 @@ against the shared version of the skalibs library, it also becomes a
 
 <ul>
  <li> The current released version of s6-linux-init is
-<a href="s6-linux-init-0.3.0.0.tar.gz">0.3.0.0</a>. </li>
+<a href="s6-linux-init-0.3.1.0.tar.gz">0.3.1.0</a>. </li>
  <li> Alternatively, you can checkout a copy of the
 <a href="//git.skarnet.org/cgi-bin/cgit.cgi/s6-linux-init/">s6-linux-init
 git repository</a>:
diff --git a/doc/s6-linux-init-maker.html b/doc/s6-linux-init-maker.html
index b7648ed..41d8372 100644
--- a/doc/s6-linux-init-maker.html
+++ b/doc/s6-linux-init-maker.html
@@ -63,6 +63,7 @@ machine</em> - else the scripts will crash.
        [ -d <em>dev_style</em> ] \
        [ -s <em>env_store</em> ] \
        [ -e <em>initial_envvar</em> ] ... \
+       [ -n ] \
        <em>dir</em>
 </pre>
 
@@ -374,6 +375,14 @@ environment, or of the form <em>VAR=VALUE</em>, to add an
 environment variable <em>VAR</em> with the value <em>VALUE</em>.
 The TZ variable, for instance, is a good candidate to be set in
 the global environment. </li> <p />
+
+ <li> <tt>-n</tt>&nbsp;: tells s6-linux-init-maker that the init script
+is going to run in a container, as pid 1 in a non-root namespace.
+This modifies the <tt>.s6-svscan/finish</tt>, <tt>.s6-svscan/SIGHUP</tt>
+and <tt>.s6-svscan/SIGINT</tt> scripts slightly, in order to provide
+adequate functionality when the containerized system is asked to
+shutdown. Do not add this option if the init script is going to run
+in the root pid namespace. </li> <p />
 </ul>
 
 <h2> Notes </h2>
@@ -407,6 +416,8 @@ you could probably invoke
 <a href="//skarnet.org/software/s6/s6-svscan.html">s6-svscan</a>
 directly as your process 1, or build a script by hand, which
 would result in a simpler init with less dependencies.
+Nevertheless, if you prefer using s6-linux-init-maker, it
+supports this case via the <tt>-n</tt> option.
 </p>
 
 </body>
diff --git a/doc/upgrade.html b/doc/upgrade.html
index 8108b4d..38e6ac1 100644
--- a/doc/upgrade.html
+++ b/doc/upgrade.html
@@ -18,6 +18,21 @@
 
 <h1> What has changed in s6-linux-init </h1>
 
+<h2> in 0.3.1.0 </h2>
+
+<ul>
+ <li> <a href="//skarnet.org/software/skalibs/">skalibs</a>
+dependency bumped to 2.6.0.0. </li>
+ <li> <a href="//skarnet.org/software/execline/">execline</a>
+dependency bumped to 2.3.0.2. </li>
+ <li> <a href="//skarnet.org/software/s6-portable-utils/">s6-portable-utils</a>
+dependency bumped to 2.2.1.1. </li>
+ <li> <a href="//skarnet.org/software/s6-linux-utils/">s6-linux-utils</a>
+dependency bumped to 2.4.0.0. </li>
+ <li> <a href="//skarnet.org/software/s6/">s6</a>
+dependency bumped to 2.6.1.0. </li>
+</ul>
+
 <h2> in 0.3.0.0 </h2>
 
 <ul>
diff --git a/package/info b/package/info
index c63cb84..a3417c4 100644
--- a/package/info
+++ b/package/info
@@ -1,4 +1,4 @@
 package=s6-linux-init
-version=0.3.0.0
+version=0.3.1.0
 category=admin
 package_macro_name=S6_LINUX_INIT
diff --git a/src/init/hpr.c b/src/init/hpr.c
index faa0a7c..b587dba 100644
--- a/src/init/hpr.c
+++ b/src/init/hpr.c
@@ -1,13 +1,61 @@
 /* ISC license. */
 
+#include <skalibs/sysdeps.h>
+#include <skalibs/nonposix.h>
 #include <unistd.h>
 #include <signal.h>
+#include <errno.h>
 #include <sys/reboot.h>
 #include <skalibs/strerr2.h>
 #include <skalibs/sgetopt.h>
+#include <skalibs/sig.h>
+#include <skalibs/djbunix.h>
 
 #define USAGE PROGNAME " [ -h | -p | -r ] [ -f ]"
 
+#ifdef SKALIBS_HASNSGETPARENT
+
+#include <sys/ioctl.h>
+#include <linux/nsfs.h>
+
+static int test_in_namespace (void)
+{
+  int r ;
+  int fd = open_read("/proc/1/ns/pid") ;
+  if (fd < 0) return 0 ;
+  r = ioctl(myfd, NS_GET_PARENT) ;
+  close(fd) ;
+  return r >= 0 ;
+}
+
+#else
+
+ /*
+   When in doubt, always trap signals. This incurs a small race:
+   if ctrl-alt-del is pressed at the wrong time, the process will
+   exit and cause a kernel panic. But the alternatives are WAY
+   more hackish than this.
+ */
+
+static int test_in_namespace (void)
+{
+  return 1 ;
+}
+
+#endif
+
+static void sigint_handler (int sig)
+{
+  (void)sig ;
+  _exit(1) ;
+}
+
+static void sighup_handler (int sig)
+{
+  (void)sig ;
+  _exit(0) ;
+}
+
 int main (int argc, char const *const *argv)
 {
   int what = WHATDEFAULT ;
@@ -32,9 +80,24 @@ int main (int argc, char const *const *argv)
     argc -= l.ind ; argv += l.ind ;
   }
 
+  if (geteuid())
+  {
+    errno = EPERM ;
+    strerr_dief1sys(100, "nice try, peon") ;
+  }
+
   if (force)
   {
     sync() ;
+    if (getpid() == 1)
+    {
+      if (test_in_namespace())
+      {
+        if (sig_catch(SIGINT, &sigint_handler) < 0
+         || sig_catch(SIGHUP, &sighup_handler) < 0)
+          strerr_diefu1sys(111, "catch signals") ;
+      }
+    }
     reboot(what == 3 ? RB_AUTOBOOT : what == 2 ? RB_POWER_OFF : RB_HALT_SYSTEM) ;
     strerr_diefu1sys(111, "reboot()") ;
   }
diff --git a/src/init/s6-linux-init-maker.c b/src/init/s6-linux-init-maker.c
index 802d924..2aa28da 100644
--- a/src/init/s6-linux-init-maker.c
+++ b/src/init/s6-linux-init-maker.c
@@ -16,11 +16,12 @@
 #include <skalibs/sgetopt.h>
 #include <skalibs/skamisc.h>
 
-#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -Z finish_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -s env_store ] [ -e initial_envvar ... ] dir"
+#define USAGE "s6-linux-init-maker [ -c basedir ] [ -l tmpfsdir ] [ -b execline_bindir ] [ -u log_uid -g log_gid | -U ] [ -G early_getty_cmd ] [ -2 stage2_script ] [ -r ] [ -Z finish_script ] [ -3 stage3_script ] [ -p initial_path ] [ -m initial_umask ] [ -t timestamp_style ] [ -d dev_style ] [ -s env_store ] [ -e initial_envvar ... ] [ -n ] dir"
 #define dieusage() strerr_dieusage(100, USAGE)
 #define dienomem() strerr_diefu1sys(111, "stralloc_catb") ;
 
 #define BANNER "\n  init created by s6-linux-init-maker\n  see http://skarnet.org/software/s6-linux-init/\n\n"
+#define EXITCODENAME "file\\ created\\ by\\ s6-linux-init,\\ storing\\ a\\ container's\\ exit\\ code"
 
 #define CRASH_SCRIPT \
 "redirfd -r 0 /dev/console\n" \
@@ -45,6 +46,7 @@ static unsigned int initial_umask = 022 ;
 static unsigned int timestamp_style = 1 ;
 static unsigned int slashdev_style = 2 ;
 static int redirect_stage2 = 0 ;
+static int in_namespace = 0 ;
 
 typedef int writetobuf_func_t (buffer *) ;
 typedef writetobuf_func_t *writetobuf_func_t_ref ;
@@ -101,10 +103,22 @@ static int finish_script (buffer *b)
   size_t sabase = satmp.len ;
   if (buffer_puts(b, "#!") < 0
    || buffer_puts(b, bindir) < 0
-   || buffer_puts(b, "/execlineb -S0\n\n"
-    "cd /\nredirfd -w 2 /dev/console\nfdmove -c 1 2\nforeground { s6-svc -X -- ") < 0
+   || buffer_puts(b, "/execlineb -S0\n\n") < 0
    || !string_quote(&satmp, slashrun, strlen(slashrun))) return 0 ;
-  if (buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
+
+  if (in_namespace)
+  {
+    if (buffer_puts(b, "ifelse { redirfd -r 0 ") < 0
+     || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0
+     || buffer_puts(b, "/" EXITCODENAME " exit 0 }\n{ redirfd -r 0 ") < 0
+     || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0
+     || buffer_puts(b, "/" EXITCODENAME " withstdinas -in CODE foreground { s6-rmrf ") < 0
+     || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0
+     || buffer_puts(b, "/" EXITCODENAME " } importas -ui CODE CODE exit ${CODE} }\n") < 0) goto err ;
+  }
+
+  if (buffer_puts(b, "cd /\nredirfd -w 2 /dev/console\nfdmove -c 1 2\nforeground { s6-svc -X -- ") < 0
+   || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0) goto err ;
   satmp.len = sabase ;
   if (buffer_puts(b, "/service/s6-svscan-log }\nunexport ?\nwait -r -- { }\n") < 0
    || !string_quote(&satmp, shutdown_script, strlen(shutdown_script))) return 0 ;
@@ -138,6 +152,25 @@ static int sig_script (buffer *b, char c)
   return 0 ;
 }
 
+static int onlyexit (buffer *b, char c)
+{
+  size_t sabase = satmp.len ;
+  if (!put_shebang(b)
+   || buffer_puts(b, "foreground { redirfd -w 1 ") < 0
+   || !string_quote(&satmp, slashrun, strlen(slashrun))
+   || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0
+   || buffer_puts(b, "/" EXITCODENAME " s6-echo -- ") < 0
+   || buffer_put(b, &c, 1) < 0
+   || buffer_puts(b, " }\ns6-svscanctl -b ") < 0
+   || buffer_put(b, satmp.s + sabase, satmp.len - sabase) < 0
+   || buffer_puts(b, "/service\n") < 0) goto err ;
+  satmp.len = sabase ;
+  return 1 ;
+ err:
+  satmp.len = sabase ;
+  return 0 ;
+}
+
 static int sigterm_script (buffer *b)
 {
   return sig_script(b, 't') ;
@@ -145,7 +178,7 @@ static int sigterm_script (buffer *b)
 
 static int sighup_script (buffer *b)
 {
-  return sig_script(b, 'h') ;
+  return in_namespace ? onlyexit(b, '0') : sig_script(b, 'h') ;
 }
 
 static int sigquit_script (buffer *b)
@@ -155,7 +188,7 @@ static int sigquit_script (buffer *b)
 
 static int sigint_script (buffer *b)
 {
-  return sig_script(b, '6') ;
+  return in_namespace ? onlyexit(b, '1') : sig_script(b, '6') ;
 }
 
 static int sigusr1_script (buffer *b)
@@ -361,7 +394,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
     subgetopt_t l = SUBGETOPT_ZERO ;
     for (;;)
     {
-      int opt = subgetopt_r(argc, argv, "c:l:b:u:g:UG:2:rZ:3:p:m:t:d:s:e:", &l) ;
+      int opt = subgetopt_r(argc, argv, "c:l:b:u:g:UG:2:rZ:3:p:m:t:d:s:e:n", &l) ;
       if (opt == -1) break ;
       switch (opt)
       {
@@ -390,6 +423,7 @@ int main (int argc, char const *const *argv, char const *const *envp)
         case 'd' : if (!uint0_scan(l.arg, &slashdev_style)) dieusage() ; break ;
         case 's' : env_store = l.arg ; break ;
         case 'e' : if (!stralloc_catb(&satmp, l.arg, strlen(l.arg) + 1)) dienomem() ; break ;
+        case 'n' : in_namespace = 1 ; break ;
         default : dieusage() ;
       }
     }