blob: 449cbe237cba362d6060fa56f90b5a927b2f338f [file] [log] [blame]
Elly Jonese58176c2012-01-23 11:46:17 -05001/* Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
Elly Jonescd7a9042011-07-22 13:56:51 -04002 * Use of this source code is governed by a BSD-style license that can be
Will Drewry32ac9f52011-08-18 21:36:27 -05003 * found in the LICENSE file.
4 */
Elly Jonescd7a9042011-07-22 13:56:51 -04005
Jorge Lucangeli Obes4b2d5ee2014-01-09 15:47:47 -08006#include <dlfcn.h>
Elly Jonescd7a9042011-07-22 13:56:51 -04007#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <unistd.h>
11
12#include "libminijail.h"
Will Drewry32ac9f52011-08-18 21:36:27 -050013#include "libsyscalls.h"
Elly Jonescd7a9042011-07-22 13:56:51 -040014
Lee Campbell1e4fc6a2014-06-06 17:40:02 -070015#include "elfparse.h"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070016#include "util.h"
17
Elly Jonese1749eb2011-10-07 13:54:59 -040018static void set_user(struct minijail *j, const char *arg)
19{
20 char *end = NULL;
21 int uid = strtod(arg, &end);
22 if (!*end && *arg) {
23 minijail_change_uid(j, uid);
24 return;
25 }
Elly Jonescd7a9042011-07-22 13:56:51 -040026
Elly Jonese1749eb2011-10-07 13:54:59 -040027 if (minijail_change_user(j, arg)) {
28 fprintf(stderr, "Bad user: '%s'\n", arg);
29 exit(1);
30 }
Elly Jonescd7a9042011-07-22 13:56:51 -040031}
32
Elly Jonese1749eb2011-10-07 13:54:59 -040033static void set_group(struct minijail *j, const char *arg)
34{
35 char *end = NULL;
36 int gid = strtod(arg, &end);
37 if (!*end && *arg) {
38 minijail_change_gid(j, gid);
39 return;
40 }
Elly Jonescd7a9042011-07-22 13:56:51 -040041
Elly Jonese1749eb2011-10-07 13:54:59 -040042 if (minijail_change_group(j, arg)) {
43 fprintf(stderr, "Bad group: '%s'\n", arg);
44 exit(1);
45 }
Elly Jonescd7a9042011-07-22 13:56:51 -040046}
47
Elly Jonese1749eb2011-10-07 13:54:59 -040048static void use_caps(struct minijail *j, const char *arg)
49{
50 uint64_t caps;
51 char *end = NULL;
52 caps = strtoull(arg, &end, 16);
53 if (*end) {
54 fprintf(stderr, "Invalid cap set: '%s'\n", arg);
55 exit(1);
56 }
57 minijail_use_caps(j, caps);
Elly Jonescd7a9042011-07-22 13:56:51 -040058}
59
Jorge Lucangeli Obesc8b21e12014-06-13 14:26:16 -070060static void add_binding(struct minijail *j, char *arg)
61{
Elly Jones51a5b6c2011-10-12 19:09:26 -040062 char *src = strtok(arg, ",");
Elly Jones5ba42b52011-12-07 13:31:43 -050063 char *dest = strtok(NULL, ",");
64 char *flags = strtok(NULL, ",");
Elly Jones51a5b6c2011-10-12 19:09:26 -040065 if (!src || !dest) {
66 fprintf(stderr, "Bad binding: %s %s\n", src, dest);
67 exit(1);
68 }
69 if (minijail_bind(j, src, dest, flags ? atoi(flags) : 0)) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -080070 fprintf(stderr, "minijail_bind failed.\n");
Elly Jones51a5b6c2011-10-12 19:09:26 -040071 exit(1);
72 }
73}
74
Dylan Reid648b2202015-10-23 00:50:00 -070075static void add_mount(struct minijail *j, char *arg)
76{
77 char *src = strtok(arg, ",");
78 char *dest = strtok(NULL, ",");
79 char *type = strtok(NULL, ",");
80 char *flags = strtok(NULL, ",");
Dylan Reid81e23972016-05-18 14:06:35 -070081 char *data = strtok(NULL, ",");
Dylan Reid648b2202015-10-23 00:50:00 -070082 if (!src || !dest || !type) {
83 fprintf(stderr, "Bad mount: %s %s %s\n", src, dest, type);
84 exit(1);
85 }
Dylan Reid81e23972016-05-18 14:06:35 -070086 if (minijail_mount_with_data(j, src, dest, type,
87 flags ? strtoul(flags, NULL, 16) : 0, data)) {
Dylan Reid648b2202015-10-23 00:50:00 -070088 fprintf(stderr, "minijail_mount failed.\n");
89 exit(1);
90 }
91}
92
Elly Jonese1749eb2011-10-07 13:54:59 -040093static void usage(const char *progn)
94{
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070095 size_t i;
96
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -080097 printf("Usage: %s [-GhiIlnprstUv]\n"
98 " [-b <src>,<dest>[,<writeable>]] [-f <file>]"
99 " [-c <caps>] [-C <dir>] [-g <group>] [-u <user>]\n"
Dylan Reid81e23972016-05-18 14:06:35 -0700100 " [-S <file>] [-k <src>,<dest>,<type>[,<flags>][,<data>]] [-T <type>]\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800101 " [-m \"<uid> <loweruid> <count>[,<uid> <loweruid> <count>]\"]\n"
102 " [-M \"<gid> <lowergid> <count>[,<uid> <loweruid> <count>]\"]\n"
103 " <program> [args...]\n"
104 " -a <table>: Use alternate syscall table <table>.\n"
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800105 " -b: Bind <src> to <dest> in chroot.\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800106 " Multiple instances allowed.\n"
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800107 " -k: Mount <src> at <dest> in chroot.\n"
Dylan Reid81e23972016-05-18 14:06:35 -0700108 " <flags> and <data> can be specified as in mount(2).\n"
109 " Multiple instances allowed.\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800110 " -c <caps>: Restrict caps to <caps>.\n"
111 " -C <dir>: chroot(2) to <dir>.\n"
112 " Not compatible with -P.\n"
113 " -e[file]: Enter new network namespace, or existing one if 'file' is provided.\n"
114 " -f <file>: Write the pid of the jailed process to <file>.\n"
115 " -G: Inherit supplementary groups from uid.\n"
116 " -g <group>: Change gid to <group>.\n"
117 " -h: Help (this message).\n"
118 " -H: Seccomp filter help message.\n"
119 " -i: Exit immediately after fork (do not act as init).\n"
120 " Not compatible with -p.\n"
121 " -I: Run <program> as init (pid 1) inside a new pid namespace (implies -p).\n"
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800122 " -K: Don't mark all existing mounts as MS_PRIVATE.\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800123 " -l: Enter new IPC namespace.\n"
124 " -L: Report blocked syscalls to syslog when using seccomp filter.\n"
Kees Cook03b2af22014-12-18 17:11:13 -0800125 " Forces the following syscalls to be allowed:\n"
126 " ", progn);
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700127 for (i = 0; i < log_syscalls_len; i++)
128 printf("%s ", log_syscalls[i]);
129
130 printf("\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800131 " -m: Set the uid mapping of a user namespace (implies -pU).\n"
Yu-Hsi Chiang1912c5b2015-08-31 18:59:49 +0800132 " Same arguments as newuidmap(1), multiple mappings should be separated by ',' (comma).\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800133 " Not compatible with -b without the 'writable' option.\n"
134 " -M: Set the gid mapping of a user namespace (implies -pU).\n"
Yu-Hsi Chiang1912c5b2015-08-31 18:59:49 +0800135 " Same arguments as newgidmap(1), multiple mappings should be separated by ',' (comma).\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800136 " Not compatible with -b without the 'writable' option.\n"
137 " -n: Set no_new_privs.\n"
Dylan Reid4cbc2a52016-06-17 19:06:07 -0700138 " -N: Enter a new cgroup namespace.\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800139 " -p: Enter new pid namespace (implies -vr).\n"
140 " -P <dir>: pivot_root(2) to <dir> (implies -v).\n"
141 " Not compatible with -C.\n"
142 " -r: Remount /proc read-only (implies -v).\n"
143 " -s: Use seccomp.\n"
144 " -S <file>: Set seccomp filter using <file>.\n"
145 " E.g., '-S /usr/share/filters/<prog>.$(uname -m)'.\n"
146 " Requires -n when not running as root.\n"
147 " -t: Mount tmpfs at /tmp inside chroot.\n"
Jorge Lucangeli Obes768d42b2016-02-17 10:28:25 -0800148 " -T <type>: Don't access <program> before execve(2), assume <type> ELF binary.\n"
149 " <type> must be 'static' or 'dynamic'.\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800150 " -u <user>: Change uid to <user>.\n"
Brian Norris3b5841b2016-03-16 16:43:49 -0700151 " -U: Enter new user namespace (implies -p).\n"
Jorge Lucangeli Obes9dd256e2016-02-16 15:31:02 -0800152 " -v: Enter new mount namespace.\n"
153 " -V <file>: Enter specified mount namespace.\n");
Elly Jonescd7a9042011-07-22 13:56:51 -0400154}
155
Elly Jonese1749eb2011-10-07 13:54:59 -0400156static void seccomp_filter_usage(const char *progn)
157{
158 const struct syscall_entry *entry = syscall_table;
159 printf("Usage: %s -S <policy.file> <program> [args...]\n\n"
160 "System call names supported:\n", progn);
161 for (; entry->name && entry->nr >= 0; ++entry)
162 printf(" %s [%d]\n", entry->name, entry->nr);
163 printf("\nSee minijail0(5) for example policies.\n");
Will Drewry32ac9f52011-08-18 21:36:27 -0500164}
165
Christopher Wiley88f76a72013-11-01 14:12:56 -0700166static int parse_args(struct minijail *j, int argc, char *argv[],
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800167 int *exit_immediately, ElfType *elftype)
Elly Jonese1749eb2011-10-07 13:54:59 -0400168{
Elly Jonese1749eb2011-10-07 13:54:59 -0400169 int opt;
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700170 int use_seccomp_filter = 0;
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800171 int binding = 0;
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800172 int pivot_root = 0, chroot = 0;
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800173 int mount_ns = 0, skip_remount = 0;
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700174 const size_t path_max = 4096;
175 const char *filter_path;
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500176 if (argc > 1 && argv[1][0] != '-')
177 return 1;
Jorge Lucangeli Obes54714502015-09-30 10:08:45 -0700178 while ((opt = getopt(argc, argv,
Dylan Reid4cbc2a52016-06-17 19:06:07 -0700179 "u:g:sS:c:C:P:b:V:f:m:M:k:a:e::T:vrGhHinNplLtIUK"))
Dylan Reid648b2202015-10-23 00:50:00 -0700180 != -1) {
Elly Jonese1749eb2011-10-07 13:54:59 -0400181 switch (opt) {
182 case 'u':
183 set_user(j, optarg);
184 break;
185 case 'g':
186 set_group(j, optarg);
187 break;
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -0700188 case 'n':
189 minijail_no_new_privs(j);
Jorge Lucangeli Obes0341d6c2012-07-16 15:27:31 -0700190 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400191 case 's':
192 minijail_use_seccomp(j);
193 break;
194 case 'S':
Elly Jonese1749eb2011-10-07 13:54:59 -0400195 minijail_use_seccomp_filter(j);
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700196 if (strlen(optarg) >= path_max) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800197 fprintf(stderr, "Filter path is too long.\n");
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700198 exit(1);
199 }
200 filter_path = strndup(optarg, path_max);
201 if (!filter_path) {
202 fprintf(stderr,
203 "Could not strndup(3) filter path.\n");
204 exit(1);
205 }
206 use_seccomp_filter = 1;
Elly Jonese1749eb2011-10-07 13:54:59 -0400207 break;
Dylan Reidf7942472015-11-18 17:55:26 -0800208 case 'l':
209 minijail_namespace_ipc(j);
210 break;
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700211 case 'L':
212 minijail_log_seccomp_filter_failures(j);
213 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400214 case 'b':
215 add_binding(j, optarg);
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800216 binding = 1;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400217 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400218 case 'c':
219 use_caps(j, optarg);
220 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400221 case 'C':
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800222 if (pivot_root) {
223 fprintf(stderr, "Could not set chroot because "
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800224 "'-P' was specified.\n");
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800225 exit(1);
226 }
Jorge Lucangeli Obes1563b5b2014-07-10 07:01:53 -0700227 if (0 != minijail_enter_chroot(j, optarg)) {
228 fprintf(stderr, "Could not set chroot.\n");
Lee Campbell11af0622014-05-22 12:36:04 -0700229 exit(1);
Jorge Lucangeli Obes1563b5b2014-07-10 07:01:53 -0700230 }
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800231 chroot = 1;
232 break;
Dylan Reid648b2202015-10-23 00:50:00 -0700233 case 'k':
234 add_mount(j, optarg);
235 break;
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800236 case 'K':
237 minijail_skip_remount_private(j);
238 skip_remount = 1;
239 break;
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800240 case 'P':
241 if (chroot) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800242 fprintf(stderr,
243 "Could not set pivot_root because "
244 "'-C' was specified.\n");
Yu-Hsi Chiang64d65a72015-08-13 17:43:27 +0800245 exit(1);
246 }
247 if (0 != minijail_enter_pivot_root(j, optarg)) {
248 fprintf(stderr, "Could not set pivot_root.\n");
249 exit(1);
250 }
251 minijail_namespace_vfs(j);
252 pivot_root = 1;
Lee Campbell11af0622014-05-22 12:36:04 -0700253 break;
Yu-Hsi Chiang3cc05ea2015-08-11 11:23:17 +0800254 case 'f':
255 if (0 != minijail_write_pid_file(j, optarg)) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800256 fprintf(stderr,
257 "Could not prepare pid file path.\n");
Yu-Hsi Chiang3cc05ea2015-08-11 11:23:17 +0800258 exit(1);
259 }
260 break;
Lee Campbell11af0622014-05-22 12:36:04 -0700261 case 't':
262 minijail_mount_tmp(j);
Elly Jones51a5b6c2011-10-12 19:09:26 -0400263 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400264 case 'v':
265 minijail_namespace_vfs(j);
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800266 mount_ns = 1;
Elly Jonese1749eb2011-10-07 13:54:59 -0400267 break;
Jorge Lucangeli Obes1563b5b2014-07-10 07:01:53 -0700268 case 'V':
269 minijail_namespace_enter_vfs(j, optarg);
270 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400271 case 'r':
Dylan Reid791f5772015-09-14 20:02:42 -0700272 minijail_remount_proc_readonly(j);
Elly Jonese1749eb2011-10-07 13:54:59 -0400273 break;
274 case 'G':
275 minijail_inherit_usergroups(j);
276 break;
Dylan Reid4cbc2a52016-06-17 19:06:07 -0700277 case 'N':
278 minijail_namespace_cgroups(j);
279 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400280 case 'p':
281 minijail_namespace_pids(j);
282 break;
Elly Fong-Jones6c086302013-03-20 17:15:28 -0400283 case 'e':
Dylan Reid1102f5a2015-09-15 11:52:20 -0700284 if (optarg)
285 minijail_namespace_enter_net(j, optarg);
286 else
287 minijail_namespace_net(j);
Elly Fong-Jones6c086302013-03-20 17:15:28 -0400288 break;
Christopher Wiley88f76a72013-11-01 14:12:56 -0700289 case 'i':
Christopher Wiley88f76a72013-11-01 14:12:56 -0700290 *exit_immediately = 1;
291 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400292 case 'H':
293 seccomp_filter_usage(argv[0]);
294 exit(1);
Yu-Hsi Chiang3e954ec2015-07-28 16:48:14 +0800295 case 'I':
296 minijail_namespace_pids(j);
297 minijail_run_as_init(j);
298 break;
Yu-Hsi Chiang10e91232015-08-05 14:40:45 +0800299 case 'U':
300 minijail_namespace_user(j);
301 minijail_namespace_pids(j);
302 break;
303 case 'm':
304 minijail_namespace_user(j);
305 minijail_namespace_pids(j);
306 if (0 != minijail_uidmap(j, optarg)) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800307 fprintf(stderr, "Could not set uidmap.\n");
Yu-Hsi Chiang10e91232015-08-05 14:40:45 +0800308 exit(1);
309 }
310 break;
311 case 'M':
312 minijail_namespace_user(j);
313 minijail_namespace_pids(j);
314 if (0 != minijail_gidmap(j, optarg)) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800315 fprintf(stderr, "Could not set gidmap.\n");
Yu-Hsi Chiang10e91232015-08-05 14:40:45 +0800316 exit(1);
317 }
318 break;
Andrew Brestickereac28942015-11-11 16:04:46 -0800319 case 'a':
320 if (0 != minijail_use_alt_syscall(j, optarg)) {
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800321 fprintf(stderr,
322 "Could not set alt-syscall table.\n");
Andrew Brestickereac28942015-11-11 16:04:46 -0800323 exit(1);
324 }
325 break;
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800326 case 'T':
327 if (!strcmp(optarg, "static"))
328 *elftype = ELFSTATIC;
329 else if (!strcmp(optarg, "dynamic"))
330 *elftype = ELFDYNAMIC;
331 else {
Jorge Lucangeli Obes768d42b2016-02-17 10:28:25 -0800332 fprintf(stderr, "ELF type must be 'static' or "
333 "'dynamic'.\n");
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800334 exit(1);
335 }
336 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400337 default:
338 usage(argv[0]);
339 exit(1);
340 }
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500341 if (optind < argc && argv[optind][0] != '-')
Lee Campbell11af0622014-05-22 12:36:04 -0700342 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400343 }
Elly Jonescd7a9042011-07-22 13:56:51 -0400344
Jorge Lucangeli Obes2b12ba42016-01-26 10:37:51 -0800345 /* Only allow bind mounts when entering a chroot or using pivot_root. */
346 if (binding && !(chroot || pivot_root)) {
347 fprintf(stderr, "Can't add bind mounts without chroot or"
348 " pivot_root.\n");
349 exit(1);
350 }
351
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700352 /*
Jorge Lucangeli Obesa521bee2016-03-03 13:47:57 -0800353 * Remounting / as MS_PRIVATE only happens when entering a new mount
354 * namespace, so skipping it only applies in that case.
355 */
356 if (skip_remount && !mount_ns) {
357 fprintf(stderr, "Can't skip marking mounts as MS_PRIVATE"
358 " without mount namespaces.\n");
359 exit(1);
360 }
361
362 /*
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700363 * We parse seccomp filters here to make sure we've collected all
364 * cmdline options.
365 */
366 if (use_seccomp_filter) {
367 minijail_parse_seccomp_filters(j, filter_path);
368 free((void*)filter_path);
369 }
370
Elly Jonese1749eb2011-10-07 13:54:59 -0400371 if (argc == optind) {
372 usage(argv[0]);
373 exit(1);
374 }
Lee Campbell11af0622014-05-22 12:36:04 -0700375
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500376 return optind;
377}
Elly Jonescd7a9042011-07-22 13:56:51 -0400378
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500379int main(int argc, char *argv[])
380{
381 struct minijail *j = minijail_new();
Jorge Lucangeli Obesd99a40d2016-01-26 13:50:44 -0800382 const char *dl_mesg = NULL;
Christopher Wiley88f76a72013-11-01 14:12:56 -0700383 int exit_immediately = 0;
Lee Campbell1e4fc6a2014-06-06 17:40:02 -0700384 ElfType elftype = ELFERROR;
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800385 int consumed = parse_args(j, argc, argv, &exit_immediately, &elftype);
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500386 argc -= consumed;
387 argv += consumed;
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700388
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800389 if (elftype == ELFERROR) {
390 /*
391 * -T was not specified.
392 * Get the path to the program adjusted for changing root.
393 */
394 char *program_path = minijail_get_original_path(j, argv[0]);
Dylan Reid08946cc2015-09-16 19:10:57 -0700395
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800396 /* Check that we can access the target program. */
397 if (access(program_path, X_OK)) {
398 fprintf(stderr,
399 "Target program '%s' is not accessible.\n",
400 argv[0]);
401 return 1;
402 }
403
404 /* Check if target is statically or dynamically linked. */
405 elftype = get_elf_linkage(program_path);
406 free(program_path);
Elly Fong-Jones6d717852013-03-19 16:29:03 -0400407 }
Jorge Lucangeli Obes482cb9d2014-07-23 15:16:04 -0700408
Lee Campbell1e4fc6a2014-06-06 17:40:02 -0700409 if (elftype == ELFSTATIC) {
Jorge Lucangeli Obes54714502015-09-30 10:08:45 -0700410 /*
411 * Target binary is statically linked so we cannot use
412 * libminijailpreload.so.
413 */
414 minijail_run_no_preload(j, argv[0], argv);
Lee Campbell1e4fc6a2014-06-06 17:40:02 -0700415 } else if (elftype == ELFDYNAMIC) {
416 /*
417 * Target binary is dynamically linked so we can
418 * inject libminijailpreload.so into it.
419 */
420
421 /* Check that we can dlopen() libminijailpreload.so. */
422 if (!dlopen(PRELOADPATH, RTLD_LAZY | RTLD_LOCAL)) {
Matthew Dempsky2ed09122016-02-11 09:43:37 -0800423 dl_mesg = dlerror();
424 fprintf(stderr, "dlopen(): %s\n", dl_mesg);
425 return 1;
Lee Campbell1e4fc6a2014-06-06 17:40:02 -0700426 }
427 minijail_run(j, argv[0], argv);
428 } else {
Jorge Lucangeli Obes2f61ee42014-06-16 11:08:18 -0700429 fprintf(stderr,
430 "Target program '%s' is not a valid ELF file.\n",
431 argv[0]);
Jorge Lucangeli Obes4b2d5ee2014-01-09 15:47:47 -0800432 return 1;
433 }
Lee Campbell1e4fc6a2014-06-06 17:40:02 -0700434
Christopher Wiley88f76a72013-11-01 14:12:56 -0700435 if (exit_immediately) {
436 info("not running init loop, exiting immediately");
437 return 0;
438 }
Elly Jonese1749eb2011-10-07 13:54:59 -0400439 return minijail_wait(j);
Elly Jonescd7a9042011-07-22 13:56:51 -0400440}