]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/lxc_init.c
Makefile.am: use right .h file name for seccomp
[mirror_lxc.git] / src / lxc / lxc_init.c
CommitLineData
05f05512 1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24#include <stdio.h>
25#include <unistd.h>
26#include <stdlib.h>
27#include <errno.h>
b0a33c1e 28#include <signal.h>
8559e703 29#include <libgen.h>
0e322d22 30#include <sys/stat.h>
05f05512 31#include <sys/types.h>
32#include <sys/wait.h>
05f05512 33#define _GNU_SOURCE
34#include <getopt.h>
00b3c2e2 35
05cda563
DL
36#include "log.h"
37#include "caps.h"
38#include "error.h"
698287d8 39#include "utils.h"
8559e703
MN
40
41lxc_log_define(lxc_init, lxc);
05f05512 42
8559e703 43static int quiet;
05f05512 44
45static struct option options[] = {
8559e703
MN
46 { "quiet", no_argument, &quiet, 1 },
47 { 0, 0, 0, 0 },
05f05512 48};
49
e4b3fe58 50static int was_interrupted = 0;
51
05f05512 52int main(int argc, char *argv[])
53{
e4b3fe58 54
55 void interrupt_handler(int sig)
56 {
57 if (!was_interrupted)
58 was_interrupted = sig;
59 }
60
05f05512 61 pid_t pid;
05f05512 62 int nbargs = 0;
b0ed5e64 63 int err = -1;
05f05512 64 char **aargv;
e4b3fe58 65 sigset_t mask, omask;
6f0a4200 66 int i, shutdown = 0;
05f05512 67
68 while (1) {
69 int ret = getopt_long_only(argc, argv, "", options, NULL);
8559e703 70 if (ret == -1) {
05f05512 71 break;
8559e703 72 }
341553f7 73 if (ret == '?')
b0ed5e64 74 exit(err);
341553f7 75
05f05512 76 nbargs++;
77 }
78
05cda563
DL
79 if (lxc_caps_init())
80 exit(err);
81
341553f7 82 if (lxc_log_init(NULL, 0, basename(argv[0]), quiet))
b0ed5e64 83 exit(err);
8559e703 84
05f05512 85 if (!argv[optind]) {
8559e703 86 ERROR("missing command to launch");
b0ed5e64 87 exit(err);
05f05512 88 }
89
90 aargv = &argv[optind];
91 argc -= nbargs;
92
6f0a4200
DL
93 /*
94 * mask all the signals so we are safe to install a
95 * signal handler and to fork
96 */
e4b3fe58 97 sigfillset(&mask);
5781a74a
JX
98 sigdelset(&mask, SIGILL);
99 sigdelset(&mask, SIGSEGV);
100 sigdelset(&mask, SIGBUS);
e4b3fe58 101 sigprocmask(SIG_SETMASK, &mask, &omask);
102
103 for (i = 1; i < NSIG; i++) {
104 struct sigaction act;
105
5781a74a
JX
106 /* Exclude some signals: ILL, SEGV and BUS are likely to
107 * reveal a bug and we want a core. STOP and KILL cannot be
108 * handled anyway: they're here for documentation.
109 */
110 if (i == SIGILL ||
111 i == SIGSEGV ||
112 i == SIGBUS ||
113 i == SIGSTOP ||
114 i == SIGKILL)
115 continue;
116
e4b3fe58 117 sigfillset(&act.sa_mask);
5781a74a
JX
118 sigdelset(&act.sa_mask, SIGILL);
119 sigdelset(&act.sa_mask, SIGSEGV);
120 sigdelset(&act.sa_mask, SIGBUS);
121 sigdelset(&act.sa_mask, SIGSTOP);
122 sigdelset(&act.sa_mask, SIGKILL);
e4b3fe58 123 act.sa_flags = 0;
124 act.sa_handler = interrupt_handler;
125 sigaction(i, &act, NULL);
126 }
127
0af683cf 128 if (lxc_setup_fs())
129 exit(err);
130
05cda563 131 if (lxc_caps_reset())
0af683cf 132 exit(err);
133
05f05512 134 pid = fork();
c147356a 135
05f05512 136 if (pid < 0)
b0ed5e64 137 exit(err);
05f05512 138
139 if (!pid) {
c147356a 140
6f0a4200 141 /* restore default signal handlers */
e4b3fe58 142 for (i = 1; i < NSIG; i++)
143 signal(i, SIG_DFL);
6f0a4200 144
e4b3fe58 145 sigprocmask(SIG_SETMASK, &omask, NULL);
146
72439b9f
MN
147 NOTICE("about to exec '%s'", aargv[0]);
148
05f05512 149 execvp(aargv[0], aargv);
0af683cf 150 ERROR("failed to exec: '%s' : %m", aargv[0]);
b0ed5e64 151 exit(err);
05f05512 152 }
153
6f0a4200
DL
154 /* let's process the signals now */
155 sigdelset(&omask, SIGALRM);
e4b3fe58 156 sigprocmask(SIG_SETMASK, &omask, NULL);
157
affaa6da
MN
158 /* no need of other inherited fds but stderr */
159 close(fileno(stdin));
160 close(fileno(stdout));
161
37c3dfc9 162 err = 0;
05f05512 163 for (;;) {
164 int status;
37c3dfc9 165 int orphan = 0;
b0ed5e64
MN
166 pid_t waited_pid;
167
6fd1668e
DL
168 switch (was_interrupted) {
169
170 case 0:
171 break;
172
173 case SIGTERM:
6f0a4200
DL
174 if (!shutdown) {
175 shutdown = 1;
176 kill(-1, SIGTERM);
177 alarm(1);
178 }
179 break;
180
181 case SIGALRM:
182 kill(-1, SIGKILL);
6fd1668e
DL
183 break;
184
185 default:
e4b3fe58 186 kill(pid, was_interrupted);
6fd1668e 187 break;
e4b3fe58 188 }
189
6fd1668e 190 was_interrupted = 0;
b0ed5e64
MN
191 waited_pid = wait(&status);
192 if (waited_pid < 0) {
05f05512 193 if (errno == ECHILD)
b0ed5e64 194 goto out;
05f05512 195 if (errno == EINTR)
196 continue;
6f0a4200
DL
197
198 ERROR("failed to wait child : %s",
199 strerror(errno));
b0ed5e64 200 goto out;
05f05512 201 }
37c3dfc9 202
6f0a4200
DL
203 /* reset timer each time a process exited */
204 if (shutdown)
205 alarm(1);
206
37c3dfc9 207 /*
6f0a4200
DL
208 * keep the exit code of started application
209 * (not wrapped pid) and continue to wait for
210 * the end of the orphan group.
37c3dfc9
MN
211 */
212 if ((waited_pid != pid) || (orphan ==1))
213 continue;
214 orphan = 1;
215 err = lxc_error_set_and_log(waited_pid, status);
05f05512 216 }
b0ed5e64
MN
217out:
218 return err;
05f05512 219}