Unverified Commit 5fb5c04d by RicardoSanchezA Committed by Christian Brauner

lxc_init: add custom argument parser

lxc_init.c should not depend on tools/arguments.{c,h}, thus it needs its own custom argument parser Signed-off-by: 's avatarRicardoSanchezA <ricardo.sanchez@utexas.edu> Signed-off-by: 's avatarChristian Brauner <christian.brauner@ubuntu.com>
parent 09d14a78
...@@ -275,7 +275,7 @@ lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c ...@@ -275,7 +275,7 @@ lxc_device_SOURCES = tools/lxc_device.c tools/arguments.c
lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c lxc_execute_SOURCES = tools/lxc_execute.c tools/arguments.c
lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c lxc_freeze_SOURCES = tools/lxc_freeze.c tools/arguments.c
lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c lxc_info_SOURCES = tools/lxc_info.c tools/arguments.c
init_lxc_SOURCES = lxc_init.c tools/arguments.c init_lxc_SOURCES = lxc_init.c
lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c lxc_monitor_SOURCES = tools/lxc_monitor.c tools/arguments.c
lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c lxc_ls_SOURCES = tools/lxc_ls.c tools/arguments.c
lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c lxc_copy_SOURCES = tools/lxc_copy.c tools/arguments.c
...@@ -303,8 +303,7 @@ endif ...@@ -303,8 +303,7 @@ endif
if HAVE_STATIC_LIBCAP if HAVE_STATIC_LIBCAP
sbin_PROGRAMS += init.lxc.static sbin_PROGRAMS += init.lxc.static
init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c \ init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c
tools/arguments.c
if !HAVE_GETLINE if !HAVE_GETLINE
if HAVE_FGETLN if HAVE_FGETLN
......
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#include <sys/prctl.h>
#include "initutils.h" #include "initutils.h"
#include "log.h" #include "log.h"
...@@ -296,3 +298,107 @@ FILE *fopen_cloexec(const char *path, const char *mode) ...@@ -296,3 +298,107 @@ FILE *fopen_cloexec(const char *path, const char *mode)
errno = saved_errno; errno = saved_errno;
return ret; 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;
}
...@@ -25,17 +25,16 @@ ...@@ -25,17 +25,16 @@
#define __LXC_INITUTILS_H #define __LXC_INITUTILS_H
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <fcntl.h>
#include <inttypes.h>
#include <stdbool.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/stat.h>
#include <sys/types.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" #include "config.h"
...@@ -44,11 +43,37 @@ ...@@ -44,11 +43,37 @@
#define DEFAULT_ZFSROOT "lxc" #define DEFAULT_ZFSROOT "lxc"
#define DEFAULT_RBDPOOL "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 void lxc_setup_fs(void);
extern const char *lxc_global_config_value(const char *option_name); extern const char *lxc_global_config_value(const char *option_name);
/* open a file with O_CLOEXEC */ /* open a file with O_CLOEXEC */
extern void remove_trailing_slashes(char *p); 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 */ #endif /* __LXC_INITUTILS_H */
...@@ -22,35 +22,32 @@ ...@@ -22,35 +22,32 @@
*/ */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <getopt.h>
#include <libgen.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/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <getopt.h> #include <ctype.h>
#include <lxc/lxccontainer.h> #include <lxc/lxccontainer.h>
#include "log.h"
#include "tools/arguments.h"
#include "error.h" #include "error.h"
#include "initutils.h" #include "initutils.h"
#include "log.h"
#include "utils.h"
#include "version.h"
lxc_log_define(lxc_init, lxc); /* option keys for long only options */
#define OPT_USAGE 0x1000
static int quiet; #define OPT_VERSION OPT_USAGE - 1
static const struct option options[] = { lxc_log_define(lxc_init, lxc);
{ "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 sig_atomic_t was_interrupted = 0;
...@@ -60,114 +57,137 @@ static void interrupt_handler(int sig) ...@@ -60,114 +57,137 @@ static void interrupt_handler(int sig)
was_interrupted = sig; was_interrupted = sig;
} }
static void usage(void) { static struct option long_options[] = {
fprintf(stderr, "Usage: lxc-init [OPTION]...\n\n" { "name", required_argument, 0, 'n' },
"Common options :\n" { "help", no_argument, 0, 'h' },
" -n, --name=NAME NAME of the container\n" { "usage", no_argument, 0, OPT_USAGE },
" -l, --logpriority=LEVEL Set log priority to LEVEL\n" { "version", no_argument, 0, OPT_VERSION },
" -q, --quiet Don't produce any output\n" { "quiet", no_argument, 0, 'q' },
" -P, --lxcpath=PATH Use specified container path\n" { "logfile", required_argument, 0, 'o' },
" -?, --help Give this help list\n" { "logpriority", required_argument, 0, 'l' },
"\n" { "lxcpath", required_argument, 0, 'P' },
"Mandatory or optional arguments to long options are also mandatory or optional\n" { 0, 0, 0, 0 }
"for any corresponding short options.\n" };
"\n" static char short_options[] = "n:hqo:l:P:";
"NOTE: lxc-init is intended for use by lxc internally\n"
" and does not need to be run by hand\n\n"); struct arguments {
} const struct option *options;
const char *shortopts;
const char *name;
char *log_file;
char *log_priority;
int quiet;
const char *lxcpath;
/* remaining arguments */
char *const *argv;
int argc;
};
static int arguments_parse(struct arguments *my_args, int argc,
char *const argv[]);
static struct arguments my_args = {
.options = long_options,
.shortopts = short_options
};
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int i, ret;
pid_t pid, sid; pid_t pid, sid;
int err;
char **aargv;
sigset_t mask, omask;
struct sigaction act; struct sigaction act;
int i, have_status = 0, shutdown = 0;
int opt;
char *lxcpath = NULL, *name = NULL, *logpriority = NULL;
struct lxc_log log; 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) { if (arguments_parse(&my_args, argc, argv))
switch(opt) { exit(EXIT_FAILURE);
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 = name; log.prefix = "lxc-init";
log.file = name ? NULL : "none"; log.name = my_args.name;
log.level = logpriority; log.file = my_args.log_file;
log.prefix = basename(argv[0]); log.level = my_args.log_priority;
log.quiet = quiet; log.quiet = my_args.quiet;
log.lxcpath = lxcpath; log.lxcpath = my_args.lxcpath;
err = lxc_log_init(&log); ret = lxc_log_init(&log);
if (err < 0) if (ret < 0)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
lxc_log_options_no_override(); lxc_log_options_no_override();
if (!argv[optind]) { if (!my_args.argc) {
ERROR("Missing command to launch"); ERROR("Please specify a command to execute");
exit(EXIT_FAILURE); 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) || ret = sigfillset(&mask);
sigdelset(&mask, SIGILL) || if (ret < 0)
sigdelset(&mask, SIGSEGV) ||
sigdelset(&mask, SIGBUS) ||
sigprocmask(SIG_SETMASK, &mask, &omask)) {
SYSERROR("Failed to set signal mask");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
}
if (sigfillset(&act.sa_mask) || ret = sigdelset(&mask, SIGILL);
sigdelset(&act.sa_mask, SIGILL) || if (ret < 0)
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); 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_flags = 0;
act.sa_handler = interrupt_handler; act.sa_handler = interrupt_handler;
for (i = 1; i < NSIG; i++) { for (i = 1; i < NSIG; i++) {
/* Exclude some signals: ILL, SEGV and BUS are likely to /* Exclude some signals: ILL, SEGV and BUS are likely to reveal
* reveal a bug and we want a core. STOP and KILL cannot be * a bug and we want a core. STOP and KILL cannot be handled
* handled anyway: they're here for documentation. 32 and 33 * anyway: they're here for documentation. 32 and 33 are not
* are not defined. * defined.
*/ */
if (i == SIGILL || if (i == SIGILL || i == SIGSEGV || i == SIGBUS ||
i == SIGSEGV || i == SIGSTOP || i == SIGKILL || i == 32 || i == 33)
i == SIGBUS ||
i == SIGSTOP ||
i == SIGKILL ||
i == 32 || i == 33)
continue; continue;
if (sigaction(i, &act, NULL) && errno != EINVAL) { ret = sigaction(i, &act, NULL);
SYSERROR("Failed to sigaction"); if (ret < 0) {
if (errno == EINVAL)
continue;
SYSERROR("Failed to change signal action");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
...@@ -179,13 +199,19 @@ int main(int argc, char *argv[]) ...@@ -179,13 +199,19 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
if (!pid) { if (!pid) {
int ret;
/* restore default signal handlers */ /* restore default signal handlers */
for (i = 1; i < NSIG; i++) for (i = 1; i < NSIG; i++) {
signal(i, SIG_DFL); 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"); SYSERROR("Failed to set signal mask");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
...@@ -197,25 +223,31 @@ int main(int argc, char *argv[]) ...@@ -197,25 +223,31 @@ int main(int argc, char *argv[])
if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) < 0) if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) < 0)
DEBUG("Failed to set controlling terminal"); DEBUG("Failed to set controlling terminal");
NOTICE("Exec'ing \"%s\"", aargv[0]); NOTICE("Exec'ing \"%s\"", my_args.argv[0]);
ret = execvp(aargv[0], aargv); ret = execvp(my_args.argv[0], my_args.argv);
ERROR("Failed to exec: '%s' : %s", aargv[0], strerror(errno)); ERROR("%s - Failed to exec \"%s\"", strerror(errno), my_args.argv[0]);
exit(ret); exit(ret);
} }
/* let's process the signals now */ INFO("Attempting to set proc title to \"init\"");
if (sigdelset(&omask, SIGALRM) || setproctitle("init");
sigprocmask(SIG_SETMASK, &omask, NULL)) {
/* 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"); SYSERROR("Failed to set signal mask");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
/* no need of other inherited fds but stderr */ /* No need of other inherited fds but stderr. */
close(fileno(stdin)); close(STDIN_FILENO);
close(fileno(stdout)); close(STDOUT_FILENO);
err = EXIT_SUCCESS;
for (;;) { for (;;) {
int status; int status;
pid_t waited_pid; pid_t waited_pid;
...@@ -227,47 +259,192 @@ int main(int argc, char *argv[]) ...@@ -227,47 +259,192 @@ int main(int argc, char *argv[])
case SIGTERM: case SIGTERM:
if (!shutdown) { if (!shutdown) {
shutdown = 1; 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); alarm(1);
} }
break; break;
case SIGALRM: case SIGALRM:
kill(-1, SIGKILL); ret = kill(-1, SIGKILL);
if (ret < 0)
DEBUG("%s - Failed to send SIGKILL to all "
"children", strerror(errno));
break; break;
default: 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; break;
} }
ret = EXIT_SUCCESS;
was_interrupted = 0; was_interrupted = 0;
waited_pid = wait(&status); waited_pid = wait(&status);
if (waited_pid < 0) { if (waited_pid < 0) {
if (errno == ECHILD) if (errno == ECHILD)
goto out; goto out;
if (errno == EINTR) if (errno == EINTR)
continue; continue;
ERROR("Failed to wait child : %s", ERROR("%s - Failed to wait on child %d",
strerror(errno)); strerror(errno), pid);
goto out; goto out;
} }
/* reset timer each time a process exited */ /* Reset timer each time a process exited. */
if (shutdown) if (shutdown)
alarm(1); alarm(1);
/* /* Keep the exit code of the started application (not wrapped
* keep the exit code of started application * pid) and continue to wait for the end of the orphan group.
* (not wrapped pid) and continue to wait for
* the end of the orphan group.
*/ */
if (waited_pid == pid && !have_status) { 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; have_status = 1;
} }
} }
out: out:
if (err < 0) if (ret < 0)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
exit(err); exit(ret);
}
static void print_usage(const struct option longopts[])
{
int i;
const struct option *opt;
fprintf(stderr, "Usage: lxc-init ");
for (opt = longopts, i = 1; opt->name; opt++, i++) {
int j;
char *uppername;
uppername = strdup(opt->name);
if (!uppername)
exit(-ENOMEM);
for (j = 0; uppername[j]; j++)
uppername[j] = toupper(uppername[j]);
fprintf(stderr, "[");
if (isprint(opt->val))
fprintf(stderr, "-%c|", opt->val);
fprintf(stderr, "--%s", opt->name);
if (opt->has_arg == required_argument)
fprintf(stderr, "=%s", uppername);
if (opt->has_arg == optional_argument)
fprintf(stderr, "[=%s]", uppername);
fprintf(stderr, "] ");
if (!(i % 4))
fprintf(stderr, "\n\t");
free(uppername);
}
fprintf(stderr, "\n");
exit(0);
}
static void print_version()
{
printf("%s%s\n", LXC_VERSION, LXC_DEVEL ? "-devel" : "");
exit(0);
}
static void print_help(int code)
{
fprintf(stderr, "\
Usage: lxc-init --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\
-o, --logfile=FILE Output log to FILE instead of stderr\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\
--usage Give a short usage message\n\
--version Print the version number\n\
\n\
Mandatory or optional arguments to long options are also mandatory or optional\n\
for any corresponding short options.\n\
\n\
See the lxc-init man page for further information.\n\n");
exit(code);
}
static int arguments_parse(struct arguments *args, int argc,
char *const argv[])
{
while (true) {
int c;
int index = 0;
c = getopt_long(argc, argv, args->shortopts, args->options, &index);
if (c == -1)
break;
switch (c) {
case 'n':
args->name = optarg;
break;
case 'o':
args->log_file = optarg;
break;
case 'l':
args->log_priority = optarg;
break;
case 'q':
args->quiet = 1;
break;
case 'P':
remove_trailing_slashes(optarg);
args->lxcpath = optarg;
break;
case OPT_USAGE:
print_usage(args->options);
case OPT_VERSION:
print_version();
case '?':
print_help(1);
case 'h':
print_help(0);
}
}
/*
* Reclaim the remaining command arguments
*/
args->argv = &argv[optind];
args->argc = argc - optind;
/* If no lxcpath was given, use default */
if (!args->lxcpath) {
args->lxcpath = lxc_global_config_value("lxc.lxcpath");
}
/* Check the command options */
if (!args->name) {
if(!args->quiet)
fprintf(stderr, "lxc-init: missing container name, use --name option\n");
return -1;
}
return 0;
} }
...@@ -50,31 +50,6 @@ ...@@ -50,31 +50,6 @@
#include "parse.h" #include "parse.h"
#include "utils.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 #ifndef O_PATH
#define O_PATH 010000000 #define O_PATH 010000000
#endif #endif
...@@ -1372,110 +1347,6 @@ char *get_template_path(const char *t) ...@@ -1372,110 +1347,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'. * @path: a pathname where / replaced with '\0'.
* @offsetp: pointer to int showing which path segment was last seen. * @offsetp: pointer to int showing which path segment was last seen.
* Updated on return to reflect the next segment. * Updated on return to reflect the next segment.
......
...@@ -450,7 +450,6 @@ extern int print_to_file(const char *file, const char *content); ...@@ -450,7 +450,6 @@ extern int print_to_file(const char *file, const char *content);
extern bool switch_to_ns(pid_t pid, const char *ns); extern bool switch_to_ns(pid_t pid, const char *ns);
extern int is_dir(const char *path); extern int is_dir(const char *path);
extern char *get_template_path(const char *t); 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, extern int safe_mount(const char *src, const char *dest, const char *fstype,
unsigned long flags, const void *data, unsigned long flags, const void *data,
const char *rootfs); const char *rootfs);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment