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