jail: netifd: check target netns fd before using it
[project/procd.git] / initd / init.c
index d458f295cfef6da4457f251c78460cb61b918127..2eb6ead2c0f466a7d91eb813f7de0cbdaedba42d 100644 (file)
@@ -20,6 +20,7 @@
 #include <libubox/uloop.h>
 #include <libubus.h>
 
+#include <limits.h>
 #include <stdlib.h>
 #include <fcntl.h>
 #include <getopt.h>
 #include <unistd.h>
 #include <stdio.h>
 
+#if defined(WITH_SELINUX)
+#include <selinux/selinux.h>
+#endif
+
+#include "../utils/utils.h"
 #include "init.h"
 #include "../watchdog.h"
 
@@ -53,35 +59,64 @@ static struct sigaction sa_shutdown = {
 static void
 cmdline(void)
 {
-       char line[256];
-       int r, fd = open("/proc/cmdline", O_RDONLY);
-       regex_t pat_cmdline;
-       regmatch_t matches[2];
-
-       if (fd < 0)
-               return;
-
-       r = read(fd, line, sizeof(line) - 1);
-       line[r] = '\0';
-       close(fd);
-
-       regcomp(&pat_cmdline, "init_debug=([0-9]+)", REG_EXTENDED);
-       if (!regexec(&pat_cmdline, line, 2, matches, 0)) {
-               line[matches[1].rm_eo] = '\0';
-               debug = atoi(&line[matches[1].rm_so]);
+       char line[20];
+       char* res;
+       long    r;
+
+       res = get_cmdline_val("init_debug", line, sizeof(line));
+       if (res != NULL) {
+               r = strtol(line, NULL, 10);
+               if ((r != LONG_MIN) && (r != LONG_MAX))
+                       debug = (int) r;
+       }
+}
+
+#if defined(WITH_SELINUX)
+static int
+selinux(char **argv)
+{
+       int enforce = 0;
+       int ret;
+
+       /* SELinux already initialized */
+       if (getenv("SELINUX_INIT"))
+               return 0;
+
+       putenv("SELINUX_INIT=1");
+
+       ret = selinux_init_load_policy(&enforce);
+       if (ret == 0)
+               execv(argv[0], argv);
+
+       if (enforce > 0) {
+               fprintf(stderr, "Cannot load SELinux policy, but system in enforcing mode. Halting.\n");
+               return 1;
        }
-       regfree(&pat_cmdline);
+
+       return 0;
 }
+#else
+static int
+selinux(char **argv)
+{
+       return 0;
+}
+#endif
 
 int
 main(int argc, char **argv)
 {
        pid_t pid;
 
+       ulog_open(ULOG_KMSG, LOG_DAEMON, "init");
+
        sigaction(SIGTERM, &sa_shutdown, NULL);
        sigaction(SIGUSR1, &sa_shutdown, NULL);
        sigaction(SIGUSR2, &sa_shutdown, NULL);
+       sigaction(SIGPWR, &sa_shutdown, NULL);
 
+       if (selinux(argv))
+               exit(-1);
        early();
        cmdline();
        watchdog_init(1);
@@ -90,23 +125,26 @@ main(int argc, char **argv)
        if (!pid) {
                char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL };
 
-               if (debug < 3) {
-                       int fd = open("/dev/null", O_RDWR);
+               if (debug < 3)
+                       patch_stdio("/dev/null");
 
-                       if (fd > -1) {
-                               dup2(fd, STDIN_FILENO);
-                               dup2(fd, STDOUT_FILENO);
-                               dup2(fd, STDERR_FILENO);
-                               if (fd > STDERR_FILENO)
-                                       close(fd);
-                       }
-               }
                execvp(kmod[0], kmod);
-               ERROR("Failed to start kmodloader\n");
-               exit(-1);
+               ERROR("Failed to start kmodloader: %m\n");
+               exit(EXIT_FAILURE);
+       }
+       if (pid <= 0) {
+               ERROR("Failed to start kmodloader instance: %m\n");
+       } else {
+               const struct timespec req = {0, 10 * 1000 * 1000};
+               int i;
+
+               for (i = 0; i < 1200; i++) {
+                       if (waitpid(pid, NULL, WNOHANG) > 0)
+                               break;
+                       nanosleep(&req, NULL);
+                       watchdog_ping();
+               }
        }
-       if (pid <= 0)
-               ERROR("Failed to start kmodloader instance\n");
        uloop_init();
        preinit();
        uloop_run();