source: npl/system/klibc/patches/run-init-add-dry-run-mode.patch @ a39aa4c

perl-5.22
Last change on this file since a39aa4c was c5c522c, checked in by Edwin Eefting <edwin@datux.nl>, 8 years ago

initial commit, transferred from cleaned syn3 svn tree

  • Property mode set to 100644
File size: 5.6 KB
RevLine 
[c5c522c]1From: Ben Hutchings <ben@decadent.org.uk>
2Date: Sun, 17 Jan 2016 19:50:28 +0000
3Subject: run-init: Add dry-run mode
4Bug-Debian: https://bugs.debian.org/810965
5
6initramfs-tools wants to validate the real init program before running
7it, as there is no way out once it has exec'd run-init.  This is
8complicated by the increasing use of symlinks for /sbin/init and for
9/sbin itself.  We can't simply resolve them with 'readlink -f' because
10any absolute symlinks will be resolved using the wrong root.  Add a
11dry-run mode (-n option) to run-init that goes as far as possible to
12validate that the given init is executable.
13
14Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
15---
16--- a/usr/kinit/run-init/run-init.c
17+++ b/usr/kinit/run-init/run-init.c
18@@ -26,19 +26,23 @@
19  * ----------------------------------------------------------------------- */
20 
21 /*
22- * Usage: exec run-init [-d caps] [-c /dev/console] /real-root /sbin/init "$@"
23+ * Usage: exec run-init [-d caps] [-c /dev/console] [-n] /real-root /sbin/init "$@"
24  *
25  * This program should be called as the last thing in a shell script
26  * acting as /init in an initramfs; it does the following:
27  *
28- * - Delete all files in the initramfs;
29- * - Remounts /real-root onto the root filesystem;
30- * - Drops comma-separated list of capabilities;
31- * - Chroots;
32- * - Opens /dev/console;
33- * - Spawns the specified init program (with arguments.)
34+ * 1. Delete all files in the initramfs;
35+ * 2. Remounts /real-root onto the root filesystem;
36+ * 3. Drops comma-separated list of capabilities;
37+ * 4. Chroots;
38+ * 5. Opens /dev/console;
39+ * 6. Spawns the specified init program (with arguments.)
40+ *
41+ * With the -n option, it skips steps 1, 2 and 6 and can be used to check
42+ * whether the given root and init are likely to work.
43  */
44 
45+#include <stdbool.h>
46 #include <stdlib.h>
47 #include <stdio.h>
48 #include <unistd.h>
49@@ -51,7 +55,7 @@ static const char *program;
50 static void __attribute__ ((noreturn)) usage(void)
51 {
52        fprintf(stderr,
53-               "Usage: exec %s [-d caps] [-c consoledev] /real-root /sbin/init [args]\n",
54+               "Usage: exec %s [-d caps] [-c consoledev] [-n] /real-root /sbin/init [args]\n",
55                program);
56        exit(1);
57 }
58@@ -64,6 +68,7 @@ int main(int argc, char *argv[])
59        const char *init;
60        const char *error;
61        const char *drop_caps = NULL;
62+       bool dry_run = false;
63        char **initargs;
64 
65        /* Variables... */
66@@ -72,11 +77,13 @@ int main(int argc, char *argv[])
67        /* Parse the command line */
68        program = argv[0];
69 
70-       while ((o = getopt(argc, argv, "c:d:")) != -1) {
71+       while ((o = getopt(argc, argv, "c:d:n")) != -1) {
72                if (o == 'c') {
73                        console = optarg;
74                } else if (o == 'd') {
75                        drop_caps = optarg;
76+               } else if (o == 'n') {
77+                       dry_run = true;
78                } else {
79                        usage();
80                }
81@@ -89,9 +96,13 @@ int main(int argc, char *argv[])
82        init = argv[optind + 1];
83        initargs = argv + optind + 1;
84 
85-       error = run_init(realroot, console, drop_caps, init, initargs);
86+       error = run_init(realroot, console, drop_caps, dry_run, init, initargs);
87 
88-       /* If run_init returns, something went wrong */
89-       fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno));
90-       return 1;
91+       if (error) {
92+               fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno));
93+               return 1;
94+       } else {
95+               /* Must have been a dry run */
96+               return 0;
97+       }
98 }
99--- a/usr/kinit/run-init/run-init.h
100+++ b/usr/kinit/run-init/run-init.h
101@@ -28,7 +28,10 @@
102 #ifndef RUN_INIT_H
103 #define RUN_INIT_H
104 
105+#include <stdbool.h>
106+
107 const char *run_init(const char *realroot, const char *console,
108-                    const char *drop_caps, const char *init, char **initargs);
109+                    const char *drop_caps, bool dry_run,
110+                    const char *init, char **initargs);
111 
112 #endif
113--- a/usr/kinit/run-init/runinitlib.c
114+++ b/usr/kinit/run-init/runinitlib.c
115@@ -156,10 +156,10 @@ static int nuke(const char *what)
116 }
117 
118 const char *run_init(const char *realroot, const char *console,
119-                    const char *drop_caps, const char *init,
120+                    const char *drop_caps, bool dry_run, const char *init,
121                     char **initargs)
122 {
123-       struct stat rst, cst;
124+       struct stat rst, cst, ist;
125        struct statfs sfs;
126        int confd;
127 
128@@ -186,13 +186,15 @@ const char *run_init(const char *realroo
129 
130        /* Okay, I think we should be safe... */
131 
132-       /* Delete rootfs contents */
133-       if (nuke_dir("/"))
134-               return "nuking initramfs contents";
135-
136-       /* Overmount the root */
137-       if (mount(".", "/", NULL, MS_MOVE, NULL))
138-               return "overmounting root";
139+       if (!dry_run) {
140+               /* Delete rootfs contents */
141+               if (nuke_dir("/"))
142+                       return "nuking initramfs contents";
143+
144+               /* Overmount the root */
145+               if (mount(".", "/", NULL, MS_MOVE, NULL))
146+                       return "overmounting root";
147+       }
148 
149        /* chroot, chdir */
150        if (chroot(".") || chdir("/"))
151@@ -205,12 +207,24 @@ const char *run_init(const char *realroo
152        /* Open /dev/console */
153        if ((confd = open(console, O_RDWR)) < 0)
154                return "opening console";
155-       dup2(confd, 0);
156-       dup2(confd, 1);
157-       dup2(confd, 2);
158+       if (!dry_run) {
159+               dup2(confd, 0);
160+               dup2(confd, 1);
161+               dup2(confd, 2);
162+       }
163        close(confd);
164 
165-       /* Spawn init */
166-       execv(init, initargs);
167-       return init;            /* Failed to spawn init */
168+       if (!dry_run) {
169+               /* Spawn init */
170+               execv(init, initargs);
171+               return init;            /* Failed to spawn init */
172+       } else {
173+               if (stat(init, &ist))
174+                       return init;
175+               if (!S_ISREG(ist.st_mode) || !(ist.st_mode & S_IXUGO)) {
176+                       errno = EACCES;
177+                       return init;
178+               }
179+               return NULL;            /* Success */
180+       }
181 }
182--- a/usr/kinit/kinit.c
183+++ b/usr/kinit/kinit.c
184@@ -304,7 +304,7 @@ int main(int argc, char *argv[])
185        init_argv[0] = strrchr(init_path, '/') + 1;
186 
187        errmsg = run_init("/root", "/dev/console",
188-                         get_arg(cmdc, cmdv, "drop_capabilities="),
189+                         get_arg(cmdc, cmdv, "drop_capabilities="), false,
190                          init_path, init_argv);
191 
192        /* If run_init returned, something went bad */
Note: See TracBrowser for help on using the repository browser.