[lxc-devel] [lxc/master] init: rework dumb init
brauner on Github
lxc-bot at linuxcontainers.org
Tue Oct 10 16:06:54 UTC 2017
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 460 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20171010/d46be712/attachment.bin>
-------------- next part --------------
From f6d9b7d50ea6919631cf061014600bab357e9488 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 10 Oct 2017 15:53:11 +0200
Subject: [PATCH 1/2] init: become session leader
Before exec()ing we need to become session leader otherwise some shells will
not be able to correctly initialize job control.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/tools/lxc_init.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/lxc/tools/lxc_init.c b/src/lxc/tools/lxc_init.c
index cac1e8c02..3aab2397e 100644
--- a/src/lxc/tools/lxc_init.c
+++ b/src/lxc/tools/lxc_init.c
@@ -77,7 +77,7 @@ static void usage(void) {
int main(int argc, char *argv[])
{
- pid_t pid;
+ pid_t pid, sid;
int err;
char **aargv;
sigset_t mask, omask;
@@ -189,6 +189,10 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ sid = setsid();
+ if (sid < 0)
+ DEBUG("Failed to make child session leader");
+
NOTICE("About to exec '%s'", aargv[0]);
ret = execvp(aargv[0], aargv);
From a6f151a7ce1c67f75663e9f23a1ae6e691443d15 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Tue, 10 Oct 2017 16:53:25 +0200
Subject: [PATCH 2/2] init: rework dumb init
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/Makefile.am | 3 +-
src/lxc/execute.c | 27 ++---
src/lxc/initutils.c | 106 ++++++++++++++++++
src/lxc/initutils.h | 43 ++++++--
src/lxc/lxccontainer.c | 1 +
src/lxc/tools/lxc_init.c | 273 +++++++++++++++++++++++++----------------------
src/lxc/utils.c | 129 ----------------------
src/lxc/utils.h | 1 -
8 files changed, 306 insertions(+), 277 deletions(-)
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 9a429b8cf..b71992d75 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -298,7 +298,8 @@ 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
+init_lxc_static_SOURCES = tools/lxc_init.c error.c log.c initutils.c caps.c \
+ arguments.c
if !HAVE_GETLINE
if HAVE_FGETLN
diff --git a/src/lxc/execute.c b/src/lxc/execute.c
index ddfd9fadb..2f7f13747 100644
--- a/src/lxc/execute.c
+++ b/src/lxc/execute.c
@@ -64,33 +64,36 @@ static int execute_start(struct lxc_handler *handler, void* data)
initpath = choose_init(NULL);
if (!initpath) {
- ERROR("Failed to find an lxc-init or init.lxc");
+ ERROR("Failed to find an init.lxc or init.lxc.static");
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++] = "--name";
- argv[i++] = (char *)handler->name;
- argv[i++] = "--lxcpath";
+ argv[i++] = "-P";
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);
diff --git a/src/lxc/initutils.c b/src/lxc/initutils.c
index c190d6d50..12c33630b 100644
--- a/src/lxc/initutils.c
+++ b/src/lxc/initutils.c
@@ -21,6 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <sys/prctl.h>
+
#include "initutils.h"
#include "log.h"
@@ -296,3 +298,107 @@ 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;
+}
diff --git a/src/lxc/initutils.h b/src/lxc/initutils.h
index c021fd617..ec44554e3 100644
--- a/src/lxc/initutils.h
+++ b/src/lxc/initutils.h
@@ -25,17 +25,16 @@
#define __LXC_INITUTILS_H
#include <errno.h>
-#include <stdio.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 <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"
@@ -44,11 +43,37 @@
#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);
-FILE *fopen_cloexec(const char *path, const char *mode);
+extern FILE *fopen_cloexec(const char *path, const char *mode);
+extern int setproctitle(char *title);
#endif /* __LXC_INITUTILS_H */
diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c
index 5e8ad00f9..fa144c55b 100644
--- a/src/lxc/lxccontainer.c
+++ b/src/lxc/lxccontainer.c
@@ -50,6 +50,7 @@
#include "confile_utils.h"
#include "console.h"
#include "criu.h"
+#include "initutils.h"
#include "log.h"
#include "lxc.h"
#include "lxccontainer.h"
diff --git a/src/lxc/tools/lxc_init.c b/src/lxc/tools/lxc_init.c
index 3aab2397e..56cc7e084 100644
--- a/src/lxc/tools/lxc_init.c
+++ b/src/lxc/tools/lxc_init.c
@@ -22,35 +22,27 @@
*/
#define _GNU_SOURCE
-#include <stdio.h>
-#include <unistd.h>
-#include <stdlib.h>
#include <errno.h>
-#include <signal.h>
+#include <getopt.h>
#include <libgen.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <getopt.h>
#include <lxc/lxccontainer.h>
-#include "log.h"
+#include "arguments.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)
@@ -59,114 +51,124 @@ static void interrupt_handler(int sig)
was_interrupted = sig;
}
-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 const struct option my_longopts[] = {
+ LXC_COMMON_OPTIONS
+};
+
+static int my_parser(struct lxc_arguments *args, int c, char *arg)
+{
+ return 0;
}
+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;
- 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);
- }
- }
+ if (lxc_arguments_parse(&my_args, argc, argv))
+ exit(EXIT_FAILURE);
- log.name = name;
- log.file = name ? NULL : "none";
- log.level = logpriority;
- log.prefix = basename(argv[0]);
- log.quiet = quiet;
- log.lxcpath = lxcpath;
+ 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];
- err = lxc_log_init(&log);
- if (err < 0)
+ ret = lxc_log_init(&log);
+ if (ret < 0)
exit(EXIT_FAILURE);
lxc_log_options_no_override();
- if (!argv[optind]) {
- ERROR("Missing command to launch");
+ if (!my_args.argc) {
+ ERROR("Please specify a command to execute");
exit(EXIT_FAILURE);
}
- aargv = &argv[optind];
-
- /*
- * mask all the signals so we are safe to install a
- * signal handler and to fork
+ /* 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");
+ ret = sigfillset(&mask);
+ if (ret < 0)
exit(EXIT_FAILURE);
- }
- 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");
+ 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);
+
+ ret = sigdelset(&act.sa_mask, SIGBUS);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+
+ ret = sigdelset(&act.sa_mask, SIGSTOP);
+ if (ret < 0)
+ exit(EXIT_FAILURE);
+
+ ret = sigdelset(&act.sa_mask, SIGKILL);
+ if (ret < 0)
+ 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;
- if (sigaction(i, &act, NULL) && errno != EINVAL) {
- SYSERROR("Failed to sigaction");
+ ret = sigaction(i, &act, NULL);
+ if (ret < 0) {
+ if (errno == EINVAL)
+ continue;
+
+ SYSERROR("Failed to change signal action");
exit(EXIT_FAILURE);
}
}
@@ -178,13 +180,19 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
if (!pid) {
- int ret;
-
/* restore default signal handlers */
- for (i = 1; i < NSIG; i++)
- signal(i, SIG_DFL);
+ 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);
+ }
+ }
- if (sigprocmask(SIG_SETMASK, &omask, NULL)) {
+ ret = sigprocmask(SIG_SETMASK, &omask, NULL);
+ if (ret < 0) {
SYSERROR("Failed to set signal mask");
exit(EXIT_FAILURE);
}
@@ -193,25 +201,31 @@ int main(int argc, char *argv[])
if (sid < 0)
DEBUG("Failed to make child session leader");
- NOTICE("About to exec '%s'", aargv[0]);
+ NOTICE("Exec'ing \"%s\"", my_args.argv[0]);
- ret = execvp(aargv[0], aargv);
- ERROR("Failed to exec: '%s' : %s", aargv[0], strerror(errno));
+ ret = execvp(my_args.argv[0], my_args.argv);
+ ERROR("%s - Failed to exec \"%s\"", strerror(errno), my_args.argv[0]);
exit(ret);
}
- /* let's process the signals now */
- if (sigdelset(&omask, SIGALRM) ||
- sigprocmask(SIG_SETMASK, &omask, NULL)) {
+ 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) {
SYSERROR("Failed to set signal mask");
exit(EXIT_FAILURE);
}
- /* no need of other inherited fds but stderr */
- close(fileno(stdin));
- close(fileno(stdout));
+ /* No need of other inherited fds but stderr. */
+ close(STDIN_FILENO);
+ close(STDOUT_FILENO);
- err = EXIT_SUCCESS;
for (;;) {
int status;
pid_t waited_pid;
@@ -223,47 +237,56 @@ int main(int argc, char *argv[])
case SIGTERM:
if (!shutdown) {
shutdown = 1;
- kill(-1, SIGTERM);
+ ret = kill(-1, SIGTERM);
+ if (ret < 0)
+ DEBUG("%s - Failed to send SIGTERM to "
+ "all children", strerror(errno));
alarm(1);
}
break;
case SIGALRM:
- kill(-1, SIGKILL);
+ ret = kill(-1, SIGKILL);
+ if (ret < 0)
+ DEBUG("%s - Failed to send SIGKILL to all "
+ "children", strerror(errno));
break;
default:
- kill(pid, was_interrupted);
+ ret = kill(pid, was_interrupted);
+ if (ret < 0)
+ DEBUG("%s - Failed to send signal \"%d\" to "
+ "%d", strerror(errno), was_interrupted, pid);
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("Failed to wait child : %s",
- strerror(errno));
+ ERROR("%s - Failed to wait on child %d",
+ strerror(errno), pid);
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 started application
- * (not wrapped pid) and continue to wait for
- * the end of the orphan group.
+ /* Keep the exit code of the started application (not wrapped
+ * pid) and continue to wait for the end of the orphan group.
*/
if (waited_pid == pid && !have_status) {
- err = lxc_error_set_and_log(waited_pid, status);
+ ret = lxc_error_set_and_log(waited_pid, status);
have_status = 1;
}
}
out:
- if (err < 0)
+ if (ret < 0)
exit(EXIT_FAILURE);
- exit(err);
+ exit(ret);
}
diff --git a/src/lxc/utils.c b/src/lxc/utils.c
index c9a60979a..4c886cadd 100644
--- a/src/lxc/utils.c
+++ b/src/lxc/utils.c
@@ -49,31 +49,6 @@
#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
@@ -1439,110 +1414,6 @@ char *get_template_path(const char *t)
}
/*
- * 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.
* Updated on return to reflect the next segment.
diff --git a/src/lxc/utils.h b/src/lxc/utils.h
index 833ec4416..41c43827a 100644
--- a/src/lxc/utils.h
+++ b/src/lxc/utils.h
@@ -340,7 +340,6 @@ 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);
More information about the lxc-devel
mailing list