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

Last change on this file since 2154c77 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
  • 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  
    2626 * ----------------------------------------------------------------------- */
    2727
    2828/*
    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 "$@"
    3030 *
    3131 * This program should be called as the last thing in a shell script
    3232 * acting as /init in an initramfs; it does the following:
    3333 *
    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.
    4043 */
    4144
     45#include <stdbool.h>
    4246#include <stdlib.h>
    4347#include <stdio.h>
    4448#include <unistd.h>
    static const char *program; 
    5155static void __attribute__ ((noreturn)) usage(void)
    5256{
    5357        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",
    5559                program);
    5660        exit(1);
    5761}
    int main(int argc, char *argv[]) 
    6468        const char *init;
    6569        const char *error;
    6670        const char *drop_caps = NULL;
     71        bool dry_run = false;
    6772        char **initargs;
    6873
    6974        /* Variables... */
    int main(int argc, char *argv[]) 
    7277        /* Parse the command line */
    7378        program = argv[0];
    7479
    75         while ((o = getopt(argc, argv, "c:d:")) != -1) {
     80        while ((o = getopt(argc, argv, "c:d:n")) != -1) {
    7681                if (o == 'c') {
    7782                        console = optarg;
    7883                } else if (o == 'd') {
    7984                        drop_caps = optarg;
     85                } else if (o == 'n') {
     86                        dry_run = true;
    8087                } else {
    8188                        usage();
    8289                }
    int main(int argc, char *argv[]) 
    8996        init = argv[optind + 1];
    9097        initargs = argv + optind + 1;
    9198
    92         error = run_init(realroot, console, drop_caps, init, initargs);
     99        error = run_init(realroot, console, drop_caps, dry_run, init, initargs);
    93100
    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        }
    97108}
  • usr/kinit/run-init/run-init.h

    a b  
    2828#ifndef RUN_INIT_H
    2929#define RUN_INIT_H
    3030
     31#include <stdbool.h>
     32
    3133const 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);
    3336
    3437#endif
  • usr/kinit/run-init/runinitlib.c

    a b static int nuke(const char *what) 
    156156}
    157157
    158158const 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,
    160160                     char **initargs)
    161161{
    162         struct stat rst, cst;
     162        struct stat rst, cst, ist;
    163163        struct statfs sfs;
    164164        int confd;
    165165
    const char *run_init(const char *realroo 
    186186
    187187        /* Okay, I think we should be safe... */
    188188
    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        }
    196198
    197199        /* chroot, chdir */
    198200        if (chroot(".") || chdir("/"))
    const char *run_init(const char *realroo 
    205207        /* Open /dev/console */
    206208        if ((confd = open(console, O_RDWR)) < 0)
    207209                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        }
    211215        close(confd);
    212216
    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        }
    216230}
  • usr/kinit/kinit.c

    a b int main(int argc, char *argv[]) 
    304304        init_argv[0] = strrchr(init_path, '/') + 1;
    305305
    306306        errmsg = run_init("/root", "/dev/console",
    307                           get_arg(cmdc, cmdv, "drop_capabilities="),
     307                          get_arg(cmdc, cmdv, "drop_capabilities="), false,
    308308                          init_path, init_argv);
    309309
    310310        /* If run_init returned, something went bad */
Note: See TracBrowser for help on using the repository browser.