source:
npl/system/klibc/patches/run-init-add-dry-run-mode.patch
@
128fde4
Last change on this file since 128fde4 was c5c522c, checked in by , 8 years ago | |
---|---|
|
|
File size: 5.6 KB |
-
usr/kinit/run-init/run-init.c
From: Ben Hutchings <ben@decadent.org.uk> Date: Sun, 17 Jan 2016 19:50:28 +0000 Subject: run-init: Add dry-run mode Bug-Debian: https://bugs.debian.org/810965 initramfs-tools wants to validate the real init program before running it, as there is no way out once it has exec'd run-init. This is complicated by the increasing use of symlinks for /sbin/init and for /sbin itself. We can't simply resolve them with 'readlink -f' because any absolute symlinks will be resolved using the wrong root. Add a dry-run mode (-n option) to run-init that goes as far as possible to validate that the given init is executable. Signed-off-by: Ben Hutchings <ben@decadent.org.uk> ---
a b 26 26 * ----------------------------------------------------------------------- */ 27 27 28 28 /* 29 * Usage: exec run-init [-d caps] [-c /dev/console] /real-root /sbin/init "$@"29 * Usage: exec run-init [-d caps] [-c /dev/console] [-n] /real-root /sbin/init "$@" 30 30 * 31 31 * This program should be called as the last thing in a shell script 32 32 * acting as /init in an initramfs; it does the following: 33 33 * 34 * - Delete all files in the initramfs; 35 * - Remounts /real-root onto the root filesystem; 36 * - Drops comma-separated list of capabilities; 37 * - Chroots; 38 * - Opens /dev/console; 39 * - 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. 40 43 */ 41 44 45 #include <stdbool.h> 42 46 #include <stdlib.h> 43 47 #include <stdio.h> 44 48 #include <unistd.h> … … static const char *program; 51 55 static void __attribute__ ((noreturn)) usage(void) 52 56 { 53 57 fprintf(stderr, 54 "Usage: exec %s [-d caps] [-c consoledev] /real-root /sbin/init [args]\n",58 "Usage: exec %s [-d caps] [-c consoledev] [-n] /real-root /sbin/init [args]\n", 55 59 program); 56 60 exit(1); 57 61 } … … int main(int argc, char *argv[]) 64 68 const char *init; 65 69 const char *error; 66 70 const char *drop_caps = NULL; 71 bool dry_run = false; 67 72 char **initargs; 68 73 69 74 /* Variables... */ … … int main(int argc, char *argv[]) 72 77 /* Parse the command line */ 73 78 program = argv[0]; 74 79 75 while ((o = getopt(argc, argv, "c:d: ")) != -1) {80 while ((o = getopt(argc, argv, "c:d:n")) != -1) { 76 81 if (o == 'c') { 77 82 console = optarg; 78 83 } else if (o == 'd') { 79 84 drop_caps = optarg; 85 } else if (o == 'n') { 86 dry_run = true; 80 87 } else { 81 88 usage(); 82 89 } … … int main(int argc, char *argv[]) 89 96 init = argv[optind + 1]; 90 97 initargs = argv + optind + 1; 91 98 92 error = run_init(realroot, console, drop_caps, init, initargs);99 error = run_init(realroot, console, drop_caps, dry_run, init, initargs); 93 100 94 /* If run_init returns, something went wrong */ 95 fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno)); 96 return 1; 101 if (error) { 102 fprintf(stderr, "%s: %s: %s\n", program, error, strerror(errno)); 103 return 1; 104 } else { 105 /* Must have been a dry run */ 106 return 0; 107 } 97 108 } -
usr/kinit/run-init/run-init.h
a b 28 28 #ifndef RUN_INIT_H 29 29 #define RUN_INIT_H 30 30 31 #include <stdbool.h> 32 31 33 const char *run_init(const char *realroot, const char *console, 32 const char *drop_caps, const char *init, char **initargs); 34 const char *drop_caps, bool dry_run, 35 const char *init, char **initargs); 33 36 34 37 #endif -
usr/kinit/run-init/runinitlib.c
a b static int nuke(const char *what) 156 156 } 157 157 158 158 const char *run_init(const char *realroot, const char *console, 159 const char *drop_caps, const char *init,159 const char *drop_caps, bool dry_run, const char *init, 160 160 char **initargs) 161 161 { 162 struct stat rst, cst ;162 struct stat rst, cst, ist; 163 163 struct statfs sfs; 164 164 int confd; 165 165 … … const char *run_init(const char *realroo 186 186 187 187 /* Okay, I think we should be safe... */ 188 188 189 /* Delete rootfs contents */ 190 if (nuke_dir("/")) 191 return "nuking initramfs contents"; 192 193 /* Overmount the root */ 194 if (mount(".", "/", NULL, MS_MOVE, NULL)) 195 return "overmounting root"; 189 if (!dry_run) { 190 /* Delete rootfs contents */ 191 if (nuke_dir("/")) 192 return "nuking initramfs contents"; 193 194 /* Overmount the root */ 195 if (mount(".", "/", NULL, MS_MOVE, NULL)) 196 return "overmounting root"; 197 } 196 198 197 199 /* chroot, chdir */ 198 200 if (chroot(".") || chdir("/")) … … const char *run_init(const char *realroo 205 207 /* Open /dev/console */ 206 208 if ((confd = open(console, O_RDWR)) < 0) 207 209 return "opening console"; 208 dup2(confd, 0); 209 dup2(confd, 1); 210 dup2(confd, 2); 210 if (!dry_run) { 211 dup2(confd, 0); 212 dup2(confd, 1); 213 dup2(confd, 2); 214 } 211 215 close(confd); 212 216 213 /* Spawn init */ 214 execv(init, initargs); 215 return init; /* Failed to spawn init */ 217 if (!dry_run) { 218 /* Spawn init */ 219 execv(init, initargs); 220 return init; /* Failed to spawn init */ 221 } else { 222 if (stat(init, &ist)) 223 return init; 224 if (!S_ISREG(ist.st_mode) || !(ist.st_mode & S_IXUGO)) { 225 errno = EACCES; 226 return init; 227 } 228 return NULL; /* Success */ 229 } 216 230 } -
usr/kinit/kinit.c
a b int main(int argc, char *argv[]) 304 304 init_argv[0] = strrchr(init_path, '/') + 1; 305 305 306 306 errmsg = run_init("/root", "/dev/console", 307 get_arg(cmdc, cmdv, "drop_capabilities="), 307 get_arg(cmdc, cmdv, "drop_capabilities="), false, 308 308 init_path, init_argv); 309 309 310 310 /* If run_init returned, something went bad */
Note: See TracBrowser
for help on using the repository browser.