]> git.proxmox.com Git - mirror_lxc.git/commitdiff
Revert "init: rework dumb init"
authorStéphane Graber <stgraber@ubuntu.com>
Tue, 17 Oct 2017 05:46:22 +0000 (01:46 -0400)
committerStéphane Graber <stgraber@ubuntu.com>
Tue, 17 Oct 2017 05:46:22 +0000 (01:46 -0400)
Seems a bit invasive for a bugfix release.

This reverts commit f9d14b54b18f6d34dea4384ba4e22d00f560ece1.

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
src/lxc/Makefile.am
src/lxc/execute.c
src/lxc/initutils.c
src/lxc/initutils.h
src/lxc/lxccontainer.c
src/lxc/tools/lxc_init.c
src/lxc/utils.c
src/lxc/utils.h

index b71992d755820f12bc5c071acaccbdcc789bc4ed..9a429b8cfe95b4310b54a7dec2e341238ac1d82f 100644 (file)
@@ -298,8 +298,7 @@ endif
 if HAVE_STATIC_LIBCAP
 sbin_PROGRAMS += init.lxc.static
 
-init_lxc_static_SOURCES = tools/lxc_init.c error.c log.c initutils.c caps.c \
-                         arguments.c
+init_lxc_static_SOURCES = tools/lxc_init.c error.c log.c initutils.c caps.c
 
 if !HAVE_GETLINE
 if HAVE_FGETLN
index 2f7f1374701ce7a3ed1b3c97bbbdc68e11fd9211..ddfd9fadb026d919c0b1341a93efad4c62b125af 100644 (file)
@@ -64,36 +64,33 @@ static int execute_start(struct lxc_handler *handler, void* data)
 
        initpath = choose_init(NULL);
        if (!initpath) {
-               ERROR("Failed to find an init.lxc or init.lxc.static");
+               ERROR("Failed to find an lxc-init or init.lxc");
                goto out2;
        }
        argv[i++] = initpath;
-
-       argv[i++] = "-n";
-       argv[i++] = (char *)handler->name;
-
-       if (lxc_log_has_valid_level()) {
-               argv[i++] = "-l";
-               argv[i++] = (char *)lxc_log_priority_to_string(lxc_log_get_level());
-       }
-
        if (my_args->quiet)
                argv[i++] = "--quiet";
-
        if (!handler->conf->rootfs.path) {
-               argv[i++] = "-P";
+               argv[i++] = "--name";
+               argv[i++] = (char *)handler->name;
+               argv[i++] = "--lxcpath";
                argv[i++] = (char *)handler->lxcpath;
-       }
 
+               if (lxc_log_has_valid_level()) {
+                       argv[i++] = "--logpriority";
+                       argv[i++] = (char *)
+                               lxc_log_priority_to_string(lxc_log_get_level());
+               }
+       }
        argv[i++] = "--";
        for (j = 0; j < argc; j++)
                argv[i++] = my_args->argv[j];
        argv[i++] = NULL;
 
-       NOTICE("Exec'ing \"%s\"", my_args->argv[0]);
+       NOTICE("exec'ing '%s'", my_args->argv[0]);
 
        execvp(argv[0], argv);
-       SYSERROR("Failed to exec %s", argv[0]);
+       SYSERROR("failed to exec %s", argv[0]);
        free(initpath);
 out2:
        free(argv);
index 12c33630b14a44e0ff7f318557770b0eed0f783b..c190d6d50a6905619a8b5913929357c9cd1ab02b 100644 (file)
@@ -21,8 +21,6 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <sys/prctl.h>
-
 #include "initutils.h"
 #include "log.h"
 
@@ -298,107 +296,3 @@ FILE *fopen_cloexec(const char *path, const char *mode)
        errno = saved_errno;
        return ret;
 }
-
-/*
- * Sets the process title to the specified title. Note that this may fail if
- * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
- */
-int setproctitle(char *title)
-{
-       static char *proctitle = NULL;
-       char buf[2048], *tmp;
-       FILE *f;
-       int i, len, ret = 0;
-
-       /* We don't really need to know all of this stuff, but unfortunately
-        * PR_SET_MM_MAP requires us to set it all at once, so we have to
-        * figure it out anyway.
-        */
-       unsigned long start_data, end_data, start_brk, start_code, end_code,
-                       start_stack, arg_start, arg_end, env_start, env_end,
-                       brk_val;
-       struct prctl_mm_map prctl_map;
-
-       f = fopen_cloexec("/proc/self/stat", "r");
-       if (!f) {
-               return -1;
-       }
-
-       tmp = fgets(buf, sizeof(buf), f);
-       fclose(f);
-       if (!tmp) {
-               return -1;
-       }
-
-       /* Skip the first 25 fields, column 26-28 are start_code, end_code,
-        * and start_stack */
-       tmp = strchr(buf, ' ');
-       for (i = 0; i < 24; i++) {
-               if (!tmp)
-                       return -1;
-               tmp = strchr(tmp+1, ' ');
-       }
-       if (!tmp)
-               return -1;
-
-       i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
-       if (i != 3)
-               return -1;
-
-       /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
-       for (i = 0; i < 19; i++) {
-               if (!tmp)
-                       return -1;
-               tmp = strchr(tmp+1, ' ');
-       }
-
-       if (!tmp)
-               return -1;
-
-       i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
-               &start_data,
-               &end_data,
-               &start_brk,
-               &env_start,
-               &env_end);
-       if (i != 5)
-               return -1;
-
-       /* Include the null byte here, because in the calculations below we
-        * want to have room for it. */
-       len = strlen(title) + 1;
-
-       proctitle = realloc(proctitle, len);
-       if (!proctitle)
-               return -1;
-
-       arg_start = (unsigned long) proctitle;
-       arg_end = arg_start + len;
-
-       brk_val = syscall(__NR_brk, 0);
-
-       prctl_map = (struct prctl_mm_map) {
-               .start_code = start_code,
-               .end_code = end_code,
-               .start_stack = start_stack,
-               .start_data = start_data,
-               .end_data = end_data,
-               .start_brk = start_brk,
-               .brk = brk_val,
-               .arg_start = arg_start,
-               .arg_end = arg_end,
-               .env_start = env_start,
-               .env_end = env_end,
-               .auxv = NULL,
-               .auxv_size = 0,
-               .exe_fd = -1,
-       };
-
-       ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
-       if (ret == 0)
-               strcpy((char*)arg_start, title);
-       else
-               INFO("setting cmdline failed - %s", strerror(errno));
-
-       return ret;
-}
index ec44554e3cb6802a7e290b3527a732e2bca1991e..c021fd6172d4d35e88b5d99de595dd6cf49553a1 100644 (file)
 #define __LXC_INITUTILS_H
 
 #include <errno.h>
-#include <fcntl.h>
-#include <inttypes.h>
-#include <stdbool.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mount.h>
+#include <stdbool.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
 
 #include "config.h"
 
 #define DEFAULT_ZFSROOT "lxc"
 #define DEFAULT_RBDPOOL "lxc"
 
-#ifndef PR_SET_MM
-#define PR_SET_MM 35
-#endif
-
-#ifndef PR_SET_MM_MAP
-#define PR_SET_MM_MAP 14
-
-struct prctl_mm_map {
-       uint64_t start_code;
-       uint64_t end_code;
-       uint64_t start_data;
-       uint64_t end_data;
-       uint64_t start_brk;
-       uint64_t brk;
-       uint64_t start_stack;
-       uint64_t arg_start;
-       uint64_t arg_end;
-       uint64_t env_start;
-       uint64_t env_end;
-       uint64_t *auxv;
-       uint32_t auxv_size;
-       uint32_t exe_fd;
-};
-#endif
-
 extern void lxc_setup_fs(void);
 extern const char *lxc_global_config_value(const char *option_name);
 
 /* open a file with O_CLOEXEC */
 extern void remove_trailing_slashes(char *p);
-extern FILE *fopen_cloexec(const char *path, const char *mode);
-extern int setproctitle(char *title);
+FILE *fopen_cloexec(const char *path, const char *mode);
 
 #endif /* __LXC_INITUTILS_H */
index fa144c55bb29ed94c055614830c29c51ad4965d3..5e8ad00f98ae9d55c858883b0504be59b630dbe3 100644 (file)
@@ -50,7 +50,6 @@
 #include "confile_utils.h"
 #include "console.h"
 #include "criu.h"
-#include "initutils.h"
 #include "log.h"
 #include "lxc.h"
 #include "lxccontainer.h"
index 56cc7e0849c38daf284e8ca28f6d2f5da181d554..3aab2397e4bca072e13b4f1c658b046f85cebec6 100644 (file)
  */
 
 #define _GNU_SOURCE
-#include <errno.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <signal.h>
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
 #include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <libgen.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <getopt.h>
 
 #include <lxc/lxccontainer.h>
 
-#include "arguments.h"
+#include "log.h"
 #include "error.h"
 #include "initutils.h"
-#include "log.h"
 
 lxc_log_define(lxc_init, lxc);
 
+static int quiet;
+
+static const struct option options[] = {
+       { "name",        required_argument, NULL, 'n' },
+       { "logpriority", required_argument, NULL, 'l' },
+       { "quiet",       no_argument,       NULL, 'q' },
+       { "lxcpath",     required_argument, NULL, 'P' },
+       { 0, 0, 0, 0 },
+};
+
 static sig_atomic_t was_interrupted = 0;
 
 static void interrupt_handler(int sig)
@@ -51,124 +59,114 @@ static void interrupt_handler(int sig)
                was_interrupted = sig;
 }
 
-static const struct option my_longopts[] = {
-       LXC_COMMON_OPTIONS
-};
-
-static int my_parser(struct lxc_arguments *args, int c, char *arg)
-{
-       return 0;
+static void usage(void) {
+       fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n"
+               "Common options :\n"
+               "  -n, --name=NAME          NAME of the container\n"
+               "  -l, --logpriority=LEVEL  Set log priority to LEVEL\n"
+               "  -q, --quiet              Don't produce any output\n"
+               "  -P, --lxcpath=PATH       Use specified container path\n"
+               "  -?, --help               Give this help list\n"
+               "\n"
+               "Mandatory or optional arguments to long options are also mandatory or optional\n"
+               "for any corresponding short options.\n"
+               "\n"
+               "NOTE: lxc-init is intended for use by lxc internally\n"
+               "      and does not need to be run by hand\n\n");
 }
 
-static struct lxc_arguments my_args = {
-       .progname = "lxc-init",
-       .help     = "\
---name=NAME -- COMMAND\n\
-\n\
-lxc-init start a COMMAND as PID 2 inside a container\n\
-\n\
-Options :\n\
-  -n, --name=NAME        NAME of the container\n\
-",
-       .options   = my_longopts,
-       .parser    = my_parser,
-};
-
 int main(int argc, char *argv[])
 {
-       int i, ret;
        pid_t pid, sid;
+       int err;
+       char **aargv;
+       sigset_t mask, omask;
        struct sigaction act;
+       int i, have_status = 0, shutdown = 0;
+       int opt;
+       char *lxcpath = NULL, *name = NULL, *logpriority = NULL;
        struct lxc_log log;
-       sigset_t mask, omask;
-       int have_status = 0, shutdown = 0;
 
-       if (lxc_arguments_parse(&my_args, argc, argv))
-               exit(EXIT_FAILURE);
+       while ((opt = getopt_long(argc, argv, "n:l:qP:", options, NULL)) != -1) {
+               switch(opt) {
+               case 'n':
+                       name = optarg;
+                       break;
+               case 'l':
+                       logpriority = optarg;
+                       break;
+               case 'q':
+                       quiet = 1;
+                       break;
+               case 'P':
+                       lxcpath = optarg;
+                       break;
+               default: /* '?' */
+                       usage();
+                       exit(EXIT_FAILURE);
+               }
+       }
 
-       log.name = my_args.name;
-       log.file = my_args.log_file;
-       log.level = my_args.log_priority;
-       log.prefix = my_args.progname;
-       log.quiet = my_args.quiet;
-       log.lxcpath = my_args.lxcpath[0];
+       log.name = name;
+       log.file = name ? NULL : "none";
+       log.level = logpriority;
+       log.prefix = basename(argv[0]);
+       log.quiet = quiet;
+       log.lxcpath = lxcpath;
 
-       ret = lxc_log_init(&log);
-       if (ret < 0)
+       err = lxc_log_init(&log);
+       if (err < 0)
                exit(EXIT_FAILURE);
        lxc_log_options_no_override();
 
-       if (!my_args.argc) {
-               ERROR("Please specify a command to execute");
+       if (!argv[optind]) {
+               ERROR("Missing command to launch");
                exit(EXIT_FAILURE);
        }
 
-       /* Mask all the signals so we are safe to install a signal handler and
-        * to fork.
-        */
-       ret = sigfillset(&mask);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&mask, SIGILL);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&mask, SIGSEGV);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&mask, SIGBUS);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigprocmask(SIG_SETMASK, &mask, &omask);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigfillset(&act.sa_mask);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&act.sa_mask, SIGILL);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&act.sa_mask, SIGSEGV);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
+       aargv = &argv[optind];
 
-       ret = sigdelset(&act.sa_mask, SIGBUS);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigdelset(&act.sa_mask, SIGSTOP);
-       if (ret < 0)
+       /*
+        * mask all the signals so we are safe to install a
+        * signal handler and to fork
+        */
+       if (sigfillset(&mask) ||
+           sigdelset(&mask, SIGILL) ||
+           sigdelset(&mask, SIGSEGV) ||
+           sigdelset(&mask, SIGBUS) ||
+           sigprocmask(SIG_SETMASK, &mask, &omask)) {
+               SYSERROR("Failed to set signal mask");
                exit(EXIT_FAILURE);
+       }
 
-       ret = sigdelset(&act.sa_mask, SIGKILL);
-       if (ret < 0)
+       if (sigfillset(&act.sa_mask) ||
+           sigdelset(&act.sa_mask, SIGILL) ||
+           sigdelset(&act.sa_mask, SIGSEGV) ||
+           sigdelset(&act.sa_mask, SIGBUS) ||
+           sigdelset(&act.sa_mask, SIGSTOP) ||
+           sigdelset(&act.sa_mask, SIGKILL)) {
+               ERROR("Failed to set signal");
                exit(EXIT_FAILURE);
-
+       }
        act.sa_flags = 0;
        act.sa_handler = interrupt_handler;
 
        for (i = 1; i < NSIG; i++) {
-               /* Exclude some signals: ILL, SEGV and BUS are likely to reveal
-                * a bug and we want a core. STOP and KILL cannot be handled
-                * anyway: they're here for documentation. 32 and 33 are not
-                * defined.
+               /* Exclude some signals: ILL, SEGV and BUS are likely to
+                * reveal a bug and we want a core. STOP and KILL cannot be
+                * handled anyway: they're here for documentation. 32 and 33
+                * are not defined.
                 */
-               if (i == SIGILL || i == SIGSEGV || i == SIGBUS ||
-                   i == SIGSTOP || i == SIGKILL || i == 32 || i == 33)
+               if (i == SIGILL ||
+                   i == SIGSEGV ||
+                   i == SIGBUS ||
+                   i == SIGSTOP ||
+                   i == SIGKILL ||
+                   i == 32 || i == 33)
                        continue;
 
-               ret = sigaction(i, &act, NULL);
-               if (ret < 0) {
-                       if (errno == EINVAL)
-                               continue;
-
-                       SYSERROR("Failed to change signal action");
+               if (sigaction(i, &act, NULL) && errno != EINVAL) {
+                       SYSERROR("Failed to sigaction");
                        exit(EXIT_FAILURE);
                }
        }
@@ -180,19 +178,13 @@ int main(int argc, char *argv[])
                exit(EXIT_FAILURE);
 
        if (!pid) {
+               int ret;
+
                /* restore default signal handlers */
-               for (i = 1; i < NSIG; i++) {
-                       sighandler_t sigerr;
-                       sigerr = signal(i, SIG_DFL);
-                       if (sigerr == SIG_ERR) {
-                               DEBUG("%s - Failed to reset to default action "
-                                     "for signal \"%d\": %d", strerror(errno),
-                                     i, pid);
-                       }
-               }
+               for (i = 1; i < NSIG; i++)
+                       signal(i, SIG_DFL);
 
-               ret = sigprocmask(SIG_SETMASK, &omask, NULL);
-               if (ret < 0) {
+               if (sigprocmask(SIG_SETMASK, &omask, NULL)) {
                        SYSERROR("Failed to set signal mask");
                        exit(EXIT_FAILURE);
                }
@@ -201,31 +193,25 @@ int main(int argc, char *argv[])
                if (sid < 0)
                        DEBUG("Failed to make child session leader");
 
-               NOTICE("Exec'ing \"%s\"", my_args.argv[0]);
+               NOTICE("About to exec '%s'", aargv[0]);
 
-               ret = execvp(my_args.argv[0], my_args.argv);
-               ERROR("%s - Failed to exec \"%s\"", strerror(errno), my_args.argv[0]);
+               ret = execvp(aargv[0], aargv);
+               ERROR("Failed to exec: '%s' : %s", aargv[0], strerror(errno));
                exit(ret);
        }
 
-       INFO("Attempting to set proc title to \"init\"");
-       setproctitle("init");
-
-       /* Let's process the signals now. */
-       ret = sigdelset(&omask, SIGALRM);
-       if (ret < 0)
-               exit(EXIT_FAILURE);
-
-       ret = sigprocmask(SIG_SETMASK, &omask, NULL);
-       if (ret < 0) {
+       /* let's process the signals now */
+       if (sigdelset(&omask, SIGALRM) ||
+           sigprocmask(SIG_SETMASK, &omask, NULL)) {
                SYSERROR("Failed to set signal mask");
                exit(EXIT_FAILURE);
        }
 
-       /* No need of other inherited fds but stderr. */
-       close(STDIN_FILENO);
-       close(STDOUT_FILENO);
+       /* no need of other inherited fds but stderr */
+       close(fileno(stdin));
+       close(fileno(stdout));
 
+       err = EXIT_SUCCESS;
        for (;;) {
                int status;
                pid_t waited_pid;
@@ -237,56 +223,47 @@ int main(int argc, char *argv[])
                case SIGTERM:
                        if (!shutdown) {
                                shutdown = 1;
-                               ret = kill(-1, SIGTERM);
-                               if (ret < 0)
-                                       DEBUG("%s - Failed to send SIGTERM to "
-                                             "all children", strerror(errno));
+                               kill(-1, SIGTERM);
                                alarm(1);
                        }
                        break;
                case SIGALRM:
-                       ret = kill(-1, SIGKILL);
-                       if (ret < 0)
-                               DEBUG("%s - Failed to send SIGKILL to all "
-                                     "children", strerror(errno));
+                       kill(-1, SIGKILL);
                        break;
                default:
-                       ret = kill(pid, was_interrupted);
-                       if (ret < 0)
-                               DEBUG("%s - Failed to send signal \"%d\" to "
-                                     "%d", strerror(errno), was_interrupted, pid);
+                       kill(pid, was_interrupted);
                        break;
                }
-               ret = EXIT_SUCCESS;
 
                was_interrupted = 0;
                waited_pid = wait(&status);
                if (waited_pid < 0) {
                        if (errno == ECHILD)
                                goto out;
-
                        if (errno == EINTR)
                                continue;
 
-                       ERROR("%s - Failed to wait on child %d",
-                             strerror(errno), pid);
+                       ERROR("Failed to wait child : %s",
+                             strerror(errno));
                        goto out;
                }
 
-               /* Reset timer each time a process exited. */
+               /* reset timer each time a process exited */
                if (shutdown)
                        alarm(1);
 
-               /* Keep the exit code of the started application (not wrapped
-                * pid) and continue to wait for the end of the orphan group.
+               /*
+                * keep the exit code of started application
+                * (not wrapped pid) and continue to wait for
+                * the end of the orphan group.
                 */
                if (waited_pid == pid && !have_status) {
-                       ret = lxc_error_set_and_log(waited_pid, status);
+                       err = lxc_error_set_and_log(waited_pid, status);
                        have_status = 1;
                }
        }
 out:
-       if (ret < 0)
+       if (err < 0)
                exit(EXIT_FAILURE);
-       exit(ret);
+       exit(err);
 }
index dc536a8f85360d9817e20dcea5dcd5d7f56864a1..e6a44a516156d61049a0e5ab528ba7744b91e15e 100644 (file)
 #include "namespace.h"
 #include "utils.h"
 
+#ifndef PR_SET_MM
+#define PR_SET_MM 35
+#endif
+
+#ifndef PR_SET_MM_MAP
+#define PR_SET_MM_MAP 14
+
+struct prctl_mm_map {
+        uint64_t   start_code;
+        uint64_t   end_code;
+        uint64_t   start_data;
+        uint64_t   end_data;
+        uint64_t   start_brk;
+        uint64_t   brk;
+        uint64_t   start_stack;
+        uint64_t   arg_start;
+        uint64_t   arg_end;
+        uint64_t   env_start;
+        uint64_t   env_end;
+        uint64_t   *auxv;
+        uint32_t   auxv_size;
+        uint32_t   exe_fd;
+};
+#endif
+
 #ifndef O_PATH
 #define O_PATH      010000000
 #endif
@@ -1345,6 +1370,110 @@ char *get_template_path(const char *t)
        return tpath;
 }
 
+/*
+ * Sets the process title to the specified title. Note that this may fail if
+ * the kernel doesn't support PR_SET_MM_MAP (kernels <3.18).
+ */
+int setproctitle(char *title)
+{
+       static char *proctitle = NULL;
+       char buf[2048], *tmp;
+       FILE *f;
+       int i, len, ret = 0;
+
+       /* We don't really need to know all of this stuff, but unfortunately
+        * PR_SET_MM_MAP requires us to set it all at once, so we have to
+        * figure it out anyway.
+        */
+       unsigned long start_data, end_data, start_brk, start_code, end_code,
+                       start_stack, arg_start, arg_end, env_start, env_end,
+                       brk_val;
+       struct prctl_mm_map prctl_map;
+
+       f = fopen_cloexec("/proc/self/stat", "r");
+       if (!f) {
+               return -1;
+       }
+
+       tmp = fgets(buf, sizeof(buf), f);
+       fclose(f);
+       if (!tmp) {
+               return -1;
+       }
+
+       /* Skip the first 25 fields, column 26-28 are start_code, end_code,
+        * and start_stack */
+       tmp = strchr(buf, ' ');
+       for (i = 0; i < 24; i++) {
+               if (!tmp)
+                       return -1;
+               tmp = strchr(tmp+1, ' ');
+       }
+       if (!tmp)
+               return -1;
+
+       i = sscanf(tmp, "%lu %lu %lu", &start_code, &end_code, &start_stack);
+       if (i != 3)
+               return -1;
+
+       /* Skip the next 19 fields, column 45-51 are start_data to arg_end */
+       for (i = 0; i < 19; i++) {
+               if (!tmp)
+                       return -1;
+               tmp = strchr(tmp+1, ' ');
+       }
+
+       if (!tmp)
+               return -1;
+
+       i = sscanf(tmp, "%lu %lu %lu %*u %*u %lu %lu",
+               &start_data,
+               &end_data,
+               &start_brk,
+               &env_start,
+               &env_end);
+       if (i != 5)
+               return -1;
+
+       /* Include the null byte here, because in the calculations below we
+        * want to have room for it. */
+       len = strlen(title) + 1;
+
+       proctitle = realloc(proctitle, len);
+       if (!proctitle)
+               return -1;
+
+       arg_start = (unsigned long) proctitle;
+       arg_end = arg_start + len;
+
+       brk_val = syscall(__NR_brk, 0);
+
+       prctl_map = (struct prctl_mm_map) {
+               .start_code = start_code,
+               .end_code = end_code,
+               .start_stack = start_stack,
+               .start_data = start_data,
+               .end_data = end_data,
+               .start_brk = start_brk,
+               .brk = brk_val,
+               .arg_start = arg_start,
+               .arg_end = arg_end,
+               .env_start = env_start,
+               .env_end = env_end,
+               .auxv = NULL,
+               .auxv_size = 0,
+               .exe_fd = -1,
+       };
+
+       ret = prctl(PR_SET_MM, PR_SET_MM_MAP, (long) &prctl_map, sizeof(prctl_map), 0);
+       if (ret == 0)
+               strcpy((char*)arg_start, title);
+       else
+               INFO("setting cmdline failed - %s", strerror(errno));
+
+       return ret;
+}
+
 /*
  * @path:    a pathname where / replaced with '\0'.
  * @offsetp: pointer to int showing which path segment was last seen.
index 4bb086d4272d822f176f1a51c5be11a97140ce7d..e83ed49eba371c2b92ff96534b7c07aef0bbbe16 100644 (file)
@@ -339,6 +339,7 @@ extern int print_to_file(const char *file, const char *content);
 extern bool switch_to_ns(pid_t pid, const char *ns);
 extern int is_dir(const char *path);
 extern char *get_template_path(const char *t);
+extern int setproctitle(char *title);
 extern int safe_mount(const char *src, const char *dest, const char *fstype,
                      unsigned long flags, const void *data,
                      const char *rootfs);