]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/cmd/lxc_init.c
Merge pull request #2366 from 2xsec/bugfix
[mirror_lxc.git] / src / lxc / cmd / lxc_init.c
CommitLineData
05f05512 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
05f05512 8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
250b1eec 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
05f05512 22 */
23
eab15c1e 24#define _GNU_SOURCE
05f05512 25#include <errno.h>
a6f151a7 26#include <getopt.h>
8559e703 27#include <libgen.h>
b467714b 28#include <pthread.h>
a6f151a7
CB
29#include <signal.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <unistd.h>
0e322d22 34#include <sys/stat.h>
05f05512 35#include <sys/types.h>
36#include <sys/wait.h>
5ee606bc 37#include <ctype.h>
00b3c2e2 38
1574fc24 39#include <lxc/lxccontainer.h>
1194822f 40#include <lxc/version.h>
1574fc24 41
05cda563 42#include "error.h"
4295c5de 43#include "initutils.h"
a6f151a7 44#include "log.h"
0059379f 45#include "namespace.h"
1933b53f 46#include "parse.h"
5ee606bc
R
47
48/* option keys for long only options */
49#define OPT_USAGE 0x1000
0059379f 50#define OPT_VERSION OPT_USAGE - 1
8559e703 51
c379af4c
TA
52#define QUOTE(macro) #macro
53#define QUOTEVAL(macro) QUOTE(macro)
54
8559e703 55lxc_log_define(lxc_init, lxc);
05f05512 56
a8aa709c 57static sig_atomic_t was_interrupted = 0;
e4b3fe58 58
a81bad13 59static void interrupt_handler(int sig)
05f05512 60{
a81bad13
RW
61 if (!was_interrupted)
62 was_interrupted = sig;
63}
e4b3fe58 64
5ee606bc 65static struct option long_options[] = {
0059379f 66 { "name", required_argument, 0, 'n' },
78c16484 67 { "help", no_argument, 0, 'h' },
0059379f
CB
68 { "usage", no_argument, 0, OPT_USAGE },
69 { "version", no_argument, 0, OPT_VERSION },
70 { "quiet", no_argument, 0, 'q' },
71 { "logfile", required_argument, 0, 'o' },
72 { "logpriority", required_argument, 0, 'l' },
73 { "lxcpath", required_argument, 0, 'P' },
5ee606bc
R
74 { 0, 0, 0, 0 }
75 };
76static char short_options[] = "n:hqo:l:P:";
77
78struct arguments {
79 const struct option *options;
80 const char *shortopts;
81
82 const char *name;
83 char *log_file;
84 char *log_priority;
d51dde8a 85 bool quiet;
5ee606bc
R
86 const char *lxcpath;
87
88 /* remaining arguments */
89 char *const *argv;
90 int argc;
a6f151a7
CB
91};
92
5ee606bc
R
93static int arguments_parse(struct arguments *my_args, int argc,
94 char *const argv[]);
e0b0b533 95
5ee606bc
R
96static struct arguments my_args = {
97 .options = long_options,
98 .shortopts = short_options
a6f151a7
CB
99};
100
d76e3e1a
TA
101static void prevent_forking(void)
102{
103 FILE *f;
1933b53f
CB
104 size_t len = 0;
105 char *line = NULL;
106 char path[MAXPATHLEN];
d76e3e1a
TA
107
108 f = fopen("/proc/self/cgroup", "r");
1933b53f 109 if (!f)
d76e3e1a 110 return;
d76e3e1a 111
1933b53f 112 while (getline(&line, &len, f) != -1) {
d6d727af 113 int fd, ret;
1933b53f 114 char *p, *p2;
d76e3e1a 115
1933b53f
CB
116 p = strchr(line, ':');
117 if (!p)
118 continue;
119 p++;
120 p2 = strchr(p, ':');
121 if (!p2)
122 continue;
123 *p2 = '\0';
c379af4c 124
1933b53f
CB
125 /* This is a cgroup v2 entry. Skip it. */
126 if ((p2 - p) == 0)
127 continue;
d76e3e1a 128
1933b53f 129 if (strcmp(p, "pids") != 0)
d76e3e1a 130 continue;
1933b53f
CB
131 p2++;
132
133 p2 += lxc_char_left_gc(p2, strlen(p2));
134 p2[lxc_char_right_gc(p2, strlen(p2))] = '\0';
d76e3e1a 135
1933b53f
CB
136 ret = snprintf(path, sizeof(path),
137 "/sys/fs/cgroup/pids/%s/pids.max", p2);
c379af4c
TA
138 if (ret < 0 || (size_t)ret >= sizeof(path)) {
139 ERROR("Failed to create string");
1933b53f 140 goto on_error;
d76e3e1a
TA
141 }
142
1933b53f 143 fd = open(path, O_WRONLY);
d76e3e1a 144 if (fd < 0) {
1933b53f
CB
145 SYSERROR("Failed to open \"%s\"", path);
146 goto on_error;
d76e3e1a
TA
147 }
148
d6d727af
CB
149 ret = write(fd, "1", 1);
150 if (ret != 1)
1933b53f 151 SYSERROR("Failed to write to \"%s\"", path);
d76e3e1a
TA
152
153 close(fd);
154 break;
155 }
156
1933b53f 157on_error:
1933b53f 158 free(line);
d76e3e1a
TA
159 fclose(f);
160}
161
162static void kill_children(pid_t pid)
163{
164 FILE *f;
165 char path[PATH_MAX];
166 int ret;
167
168 ret = snprintf(path, sizeof(path), "/proc/%d/task/%d/children", pid, pid);
c379af4c
TA
169 if (ret < 0 || (size_t)ret >= sizeof(path)) {
170 ERROR("Failed to create string");
d76e3e1a
TA
171 return;
172 }
173
174 f = fopen(path, "r");
175 if (!f) {
c379af4c 176 SYSERROR("Failed to open %s", path);
d76e3e1a
TA
177 return;
178 }
179
180 while (!feof(f)) {
181 pid_t pid;
182
183 if (fscanf(f, "%d ", &pid) != 1) {
c379af4c 184 ERROR("Failed to retrieve pid");
d76e3e1a
TA
185 fclose(f);
186 return;
187 }
188
189 kill_children(pid);
190 kill(pid, SIGKILL);
191 }
192
193 fclose(f);
194}
195
58fb9c8e
TA
196static void remove_self(void)
197{
4d078b3c 198 int ret;
58fb9c8e 199 ssize_t n;
4d078b3c 200 char path[MAXPATHLEN] = {0};
58fb9c8e
TA
201
202 n = readlink("/proc/self/exe", path, sizeof(path));
4d078b3c 203 if (n < 0 || n >= MAXPATHLEN) {
58fb9c8e
TA
204 SYSERROR("Failed to readlink \"/proc/self/exe\"");
205 return;
206 }
4d078b3c 207 path[n] = '\0';
58fb9c8e 208
4d078b3c
CB
209 ret = umount2(path, MNT_DETACH);
210 if (ret < 0) {
58fb9c8e
TA
211 SYSERROR("Failed to unmount \"%s\"", path);
212 return;
213 }
214
4d078b3c
CB
215 ret = unlink(path);
216 if (ret < 0) {
58fb9c8e
TA
217 SYSERROR("Failed to unlink \"%s\"", path);
218 return;
219 }
220}
221
a81bad13
RW
222int main(int argc, char *argv[])
223{
a6f151a7 224 int i, ret;
f6d9b7d5 225 pid_t pid, sid;
16affc24 226 struct sigaction act;
73b910a3 227 struct lxc_log log;
a6f151a7 228 sigset_t mask, omask;
4f4530fa 229 int have_status = 0, exit_with = 1, shutdown = 0;
05f05512 230
5ee606bc 231 if (arguments_parse(&my_args, argc, argv))
a6f151a7 232 exit(EXIT_FAILURE);
05f05512 233
5ee606bc 234 log.prefix = "lxc-init";
a6f151a7
CB
235 log.name = my_args.name;
236 log.file = my_args.log_file;
237 log.level = my_args.log_priority;
a6f151a7 238 log.quiet = my_args.quiet;
5ee606bc 239 log.lxcpath = my_args.lxcpath;
73b910a3 240
a6f151a7
CB
241 ret = lxc_log_init(&log);
242 if (ret < 0)
e0b0b533 243 exit(EXIT_FAILURE);
6edbfc86 244 lxc_log_options_no_override();
8559e703 245
a6f151a7
CB
246 if (!my_args.argc) {
247 ERROR("Please specify a command to execute");
e0b0b533 248 exit(EXIT_FAILURE);
05f05512 249 }
250
a6f151a7
CB
251 /* Mask all the signals so we are safe to install a signal handler and
252 * to fork.
6f0a4200 253 */
a6f151a7
CB
254 ret = sigfillset(&mask);
255 if (ret < 0)
0291b5fa 256 exit(EXIT_FAILURE);
e4b3fe58 257
a6f151a7
CB
258 ret = sigdelset(&mask, SIGILL);
259 if (ret < 0)
16affc24 260 exit(EXIT_FAILURE);
a6f151a7
CB
261
262 ret = sigdelset(&mask, SIGSEGV);
263 if (ret < 0)
264 exit(EXIT_FAILURE);
265
266 ret = sigdelset(&mask, SIGBUS);
267 if (ret < 0)
268 exit(EXIT_FAILURE);
269
b467714b 270 ret = pthread_sigmask(SIG_SETMASK, &mask, &omask);
a6f151a7
CB
271 if (ret < 0)
272 exit(EXIT_FAILURE);
273
274 ret = sigfillset(&act.sa_mask);
275 if (ret < 0)
276 exit(EXIT_FAILURE);
277
278 ret = sigdelset(&act.sa_mask, SIGILL);
279 if (ret < 0)
280 exit(EXIT_FAILURE);
281
282 ret = sigdelset(&act.sa_mask, SIGSEGV);
283 if (ret < 0)
284 exit(EXIT_FAILURE);
285
286 ret = sigdelset(&act.sa_mask, SIGBUS);
287 if (ret < 0)
288 exit(EXIT_FAILURE);
289
290 ret = sigdelset(&act.sa_mask, SIGSTOP);
291 if (ret < 0)
292 exit(EXIT_FAILURE);
293
294 ret = sigdelset(&act.sa_mask, SIGKILL);
295 if (ret < 0)
296 exit(EXIT_FAILURE);
297
16affc24
LW
298 act.sa_flags = 0;
299 act.sa_handler = interrupt_handler;
e4b3fe58 300
16affc24 301 for (i = 1; i < NSIG; i++) {
a6f151a7
CB
302 /* Exclude some signals: ILL, SEGV and BUS are likely to reveal
303 * a bug and we want a core. STOP and KILL cannot be handled
304 * anyway: they're here for documentation. 32 and 33 are not
305 * defined.
5781a74a 306 */
a6f151a7
CB
307 if (i == SIGILL || i == SIGSEGV || i == SIGBUS ||
308 i == SIGSTOP || i == SIGKILL || i == 32 || i == 33)
5781a74a
JX
309 continue;
310
a6f151a7
CB
311 ret = sigaction(i, &act, NULL);
312 if (ret < 0) {
313 if (errno == EINVAL)
314 continue;
315
316 SYSERROR("Failed to change signal action");
0291b5fa
QH
317 exit(EXIT_FAILURE);
318 }
e4b3fe58 319 }
320
58fb9c8e
TA
321 remove_self();
322
05f05512 323 pid = fork();
05f05512 324 if (pid < 0)
e0b0b533 325 exit(EXIT_FAILURE);
05f05512 326
327 if (!pid) {
6f0a4200 328 /* restore default signal handlers */
a6f151a7
CB
329 for (i = 1; i < NSIG; i++) {
330 sighandler_t sigerr;
11c69d5e
CB
331
332 if (i == SIGILL || i == SIGSEGV || i == SIGBUS ||
333 i == SIGSTOP || i == SIGKILL || i == 32 || i == 33)
334 continue;
335
a6f151a7
CB
336 sigerr = signal(i, SIG_DFL);
337 if (sigerr == SIG_ERR) {
338 DEBUG("%s - Failed to reset to default action "
339 "for signal \"%d\": %d", strerror(errno),
340 i, pid);
341 }
342 }
6f0a4200 343
b467714b 344 ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
a6f151a7 345 if (ret < 0) {
1bfb1200 346 SYSERROR("Failed to set signal mask");
0291b5fa
QH
347 exit(EXIT_FAILURE);
348 }
e4b3fe58 349
f6d9b7d5
CB
350 sid = setsid();
351 if (sid < 0)
352 DEBUG("Failed to make child session leader");
353
0cf42edd
JC
354 if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) < 0)
355 DEBUG("Failed to set controlling terminal");
356
a6f151a7 357 NOTICE("Exec'ing \"%s\"", my_args.argv[0]);
72439b9f 358
a6f151a7
CB
359 ret = execvp(my_args.argv[0], my_args.argv);
360 ERROR("%s - Failed to exec \"%s\"", strerror(errno), my_args.argv[0]);
8130d864 361 exit(ret);
05f05512 362 }
363
a6f151a7
CB
364 INFO("Attempting to set proc title to \"init\"");
365 setproctitle("init");
366
367 /* Let's process the signals now. */
368 ret = sigdelset(&omask, SIGALRM);
369 if (ret < 0)
370 exit(EXIT_FAILURE);
371
b467714b 372 ret = pthread_sigmask(SIG_SETMASK, &omask, NULL);
a6f151a7 373 if (ret < 0) {
1bfb1200 374 SYSERROR("Failed to set signal mask");
0291b5fa
QH
375 exit(EXIT_FAILURE);
376 }
e4b3fe58 377
a6f151a7
CB
378 /* No need of other inherited fds but stderr. */
379 close(STDIN_FILENO);
380 close(STDOUT_FILENO);
affaa6da 381
05f05512 382 for (;;) {
383 int status;
b0ed5e64
MN
384 pid_t waited_pid;
385
6fd1668e 386 switch (was_interrupted) {
6fd1668e 387 case 0:
186dfb16
TA
388 /* Some applications send SIGHUP in order to get init to reload
389 * its configuration. We don't want to forward this onto the
390 * application itself, because it probably isn't expecting this
391 * signal since it was expecting init to do something with it.
392 *
393 * Instead, let's explicitly ignore it here. The actual
394 * terminal case is handled in the monitor's handler, which
395 * sends this task a SIGTERM in the case of a SIGHUP, which is
396 * what we want.
397 */
398 case SIGHUP:
6fd1668e 399 break;
5c7f03ae 400 case SIGPWR:
6fd1668e 401 case SIGTERM:
6f0a4200 402 if (!shutdown) {
0059379f 403 pid_t mypid = lxc_raw_getpid();
c379af4c 404
6f0a4200 405 shutdown = 1;
d76e3e1a 406 prevent_forking();
c379af4c
TA
407 if (mypid != 1) {
408 kill_children(mypid);
d76e3e1a
TA
409 } else {
410 ret = kill(-1, SIGTERM);
411 if (ret < 0)
412 DEBUG("%s - Failed to send SIGTERM to "
413 "all children", strerror(errno));
414 }
415 alarm(1);
416 }
417 break;
c379af4c 418 case SIGALRM: {
0059379f 419 pid_t mypid = lxc_raw_getpid();
c379af4c 420
d76e3e1a 421 prevent_forking();
c379af4c
TA
422 if (mypid != 1) {
423 kill_children(mypid);
d76e3e1a 424 } else {
60e324aa 425 ret = kill(-1, SIGKILL);
a6f151a7
CB
426 if (ret < 0)
427 DEBUG("%s - Failed to send SIGTERM to "
428 "all children", strerror(errno));
6f0a4200
DL
429 }
430 break;
c379af4c 431 }
6fd1668e 432 default:
a6f151a7
CB
433 ret = kill(pid, was_interrupted);
434 if (ret < 0)
435 DEBUG("%s - Failed to send signal \"%d\" to "
436 "%d", strerror(errno), was_interrupted, pid);
6fd1668e 437 break;
e4b3fe58 438 }
a6f151a7 439 ret = EXIT_SUCCESS;
e4b3fe58 440
6fd1668e 441 was_interrupted = 0;
b0ed5e64
MN
442 waited_pid = wait(&status);
443 if (waited_pid < 0) {
05f05512 444 if (errno == ECHILD)
b0ed5e64 445 goto out;
a6f151a7 446
05f05512 447 if (errno == EINTR)
448 continue;
6f0a4200 449
a6f151a7
CB
450 ERROR("%s - Failed to wait on child %d",
451 strerror(errno), pid);
b0ed5e64 452 goto out;
05f05512 453 }
37c3dfc9 454
a6f151a7 455 /* Reset timer each time a process exited. */
6f0a4200
DL
456 if (shutdown)
457 alarm(1);
458
a6f151a7
CB
459 /* Keep the exit code of the started application (not wrapped
460 * pid) and continue to wait for the end of the orphan group.
37c3dfc9 461 */
fe19f236 462 if (waited_pid == pid && !have_status) {
4f4530fa 463 exit_with = lxc_error_set_and_log(waited_pid, status);
fe19f236
DE
464 have_status = 1;
465 }
05f05512 466 }
b0ed5e64 467out:
a6f151a7 468 if (ret < 0)
13bc2fd2 469 exit(EXIT_FAILURE);
4f4530fa 470 exit(exit_with);
05f05512 471}
5ee606bc 472
5ee606bc
R
473static void print_usage(const struct option longopts[])
474
475{
d51dde8a
R
476 fprintf(stderr, "Usage: lxc-init [-n|--name=NAME] [-h|--help] [--usage] [--version] \n\
477 [-q|--quiet] [-o|--logfile=LOGFILE] [-l|--logpriority=LOGPRIORITY] [-P|--lxcpath=LXCPATH]\n");
5ee606bc
R
478 exit(0);
479}
480
481static void print_version()
482{
5f98011c 483 printf("%s\n", LXC_VERSION);
5ee606bc
R
484 exit(0);
485}
486
d51dde8a 487static void print_help()
5ee606bc
R
488{
489 fprintf(stderr, "\
490Usage: lxc-init --name=NAME -- COMMAND\n\
491\n\
492 lxc-init start a COMMAND as PID 2 inside a container\n\
493\n\
494Options :\n\
495 -n, --name=NAME NAME of the container\n\
496 -o, --logfile=FILE Output log to FILE instead of stderr\n\
497 -l, --logpriority=LEVEL Set log priority to LEVEL\n\
498 -q, --quiet Don't produce any output\n\
499 -P, --lxcpath=PATH Use specified container path\n\
500 -?, --help Give this help list\n\
501 --usage Give a short usage message\n\
502 --version Print the version number\n\
503\n\
504Mandatory or optional arguments to long options are also mandatory or optional\n\
505for any corresponding short options.\n\
506\n\
507See the lxc-init man page for further information.\n\n");
508
5ee606bc
R
509}
510
511static int arguments_parse(struct arguments *args, int argc,
512 char *const argv[])
513{
514 while (true) {
515 int c;
516 int index = 0;
517
518 c = getopt_long(argc, argv, args->shortopts, args->options, &index);
519 if (c == -1)
520 break;
521 switch (c) {
522 case 'n':
523 args->name = optarg;
524 break;
525 case 'o':
526 args->log_file = optarg;
527 break;
528 case 'l':
529 args->log_priority = optarg;
530 break;
531 case 'q':
d51dde8a 532 args->quiet = true;
5ee606bc
R
533 break;
534 case 'P':
535 remove_trailing_slashes(optarg);
536 args->lxcpath = optarg;
537 break;
538 case OPT_USAGE:
539 print_usage(args->options);
540 case OPT_VERSION:
541 print_version();
542 case '?':
d51dde8a
R
543 print_help();
544 exit(EXIT_FAILURE);
5ee606bc 545 case 'h':
d51dde8a
R
546 print_help();
547 exit(EXIT_SUCCESS);
5ee606bc
R
548 }
549 }
550
551 /*
552 * Reclaim the remaining command arguments
553 */
554 args->argv = &argv[optind];
555 args->argc = argc - optind;
556
557 /* If no lxcpath was given, use default */
558 if (!args->lxcpath) {
559 args->lxcpath = lxc_global_config_value("lxc.lxcpath");
560 }
561
562 /* Check the command options */
563 if (!args->name) {
564 if(!args->quiet)
565 fprintf(stderr, "lxc-init: missing container name, use --name option\n");
566 return -1;
567 }
568
569 return 0;
570}