blob: 6d9233c9cbb3b192ab05f84e85cf15350a669847 [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
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10
11#include "libminijail.h"
Will Drewry32ac9f52011-08-18 21:36:27 -050012#include "libsyscalls.h"
Elly Jonescd7a9042011-07-22 13:56:51 -040013
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070014#include "util.h"
15
Elly Jonese1749eb2011-10-07 13:54:59 -040016static void set_user(struct minijail *j, const char *arg)
17{
18 char *end = NULL;
19 int uid = strtod(arg, &end);
20 if (!*end && *arg) {
21 minijail_change_uid(j, uid);
22 return;
23 }
Elly Jonescd7a9042011-07-22 13:56:51 -040024
Elly Jonese1749eb2011-10-07 13:54:59 -040025 if (minijail_change_user(j, arg)) {
26 fprintf(stderr, "Bad user: '%s'\n", arg);
27 exit(1);
28 }
Elly Jonescd7a9042011-07-22 13:56:51 -040029}
30
Elly Jonese1749eb2011-10-07 13:54:59 -040031static void set_group(struct minijail *j, const char *arg)
32{
33 char *end = NULL;
34 int gid = strtod(arg, &end);
35 if (!*end && *arg) {
36 minijail_change_gid(j, gid);
37 return;
38 }
Elly Jonescd7a9042011-07-22 13:56:51 -040039
Elly Jonese1749eb2011-10-07 13:54:59 -040040 if (minijail_change_group(j, arg)) {
41 fprintf(stderr, "Bad group: '%s'\n", arg);
42 exit(1);
43 }
Elly Jonescd7a9042011-07-22 13:56:51 -040044}
45
Elly Jonese1749eb2011-10-07 13:54:59 -040046static void use_caps(struct minijail *j, const char *arg)
47{
48 uint64_t caps;
49 char *end = NULL;
50 caps = strtoull(arg, &end, 16);
51 if (*end) {
52 fprintf(stderr, "Invalid cap set: '%s'\n", arg);
53 exit(1);
54 }
55 minijail_use_caps(j, caps);
Elly Jonescd7a9042011-07-22 13:56:51 -040056}
57
Elly Jones51a5b6c2011-10-12 19:09:26 -040058static void add_binding(struct minijail *j, char *arg) {
59 char *src = strtok(arg, ",");
Elly Jones5ba42b52011-12-07 13:31:43 -050060 char *dest = strtok(NULL, ",");
61 char *flags = strtok(NULL, ",");
Elly Jones51a5b6c2011-10-12 19:09:26 -040062 if (!src || !dest) {
63 fprintf(stderr, "Bad binding: %s %s\n", src, dest);
64 exit(1);
65 }
66 if (minijail_bind(j, src, dest, flags ? atoi(flags) : 0)) {
67 fprintf(stderr, "Bind failure\n");
68 exit(1);
69 }
70}
71
Elly Jonese1749eb2011-10-07 13:54:59 -040072static void usage(const char *progn)
73{
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070074 size_t i;
75
Christopher Wiley88f76a72013-11-01 14:12:56 -070076 printf("Usage: %s [-Ghinprsv] [-b <src>,<dest>[,<writeable>]] "
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -070077 "[-c <caps>] [-C <dir>] [-g <group>] [-S <file>] [-u <user>] "
78 "<program> [args...]\n"
Elly Jonesa8d1e1b2011-10-21 15:38:00 -040079 " -b: binds <src> to <dest> in chroot. Multiple "
80 "instances allowed\n"
Elly Jonese1749eb2011-10-07 13:54:59 -040081 " -c <caps>: restrict caps to <caps>\n"
Elly Jonesa8d1e1b2011-10-21 15:38:00 -040082 " -C <dir>: chroot to <dir>\n"
Christopher Wiley88f76a72013-11-01 14:12:56 -070083 " -e enter a network namespace\n"
Elly Jonese1749eb2011-10-07 13:54:59 -040084 " -G: inherit secondary groups from uid\n"
85 " -g <group>: change gid to <group>\n"
86 " -h: help (this message)\n"
87 " -H: seccomp filter help message\n"
Christopher Wiley88f76a72013-11-01 14:12:56 -070088 " -i: exit immediately after fork (do not act as init)\n"
89 " Not compatible with -p\n"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070090 " -L: log blocked syscalls when using seccomp filter. "
91 "Forces the following syscalls to be allowed:\n"
92 " ", progn);
93 for (i = 0; i < log_syscalls_len; i++)
94 printf("%s ", log_syscalls[i]);
95
96 printf("\n"
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -070097 " -n: set no_new_privs\n"
Elly Jonese58176c2012-01-23 11:46:17 -050098 " -p: use pid namespace (implies -vr)\n"
Elly Jonesfdd5f2d2012-01-23 13:27:43 -050099 " -r: remount /proc readonly (implies -v)\n"
Elly Jonese1749eb2011-10-07 13:54:59 -0400100 " -s: use seccomp\n"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700101 " -S <file>: set seccomp filter using <file>\n"
Elly Jonese1749eb2011-10-07 13:54:59 -0400102 " E.g., -S /usr/share/filters/<prog>.$(uname -m)\n"
103 " -u <user>: change uid to <user>\n"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700104 " -v: use vfs namespace\n");
Elly Jonescd7a9042011-07-22 13:56:51 -0400105}
106
Elly Jonese1749eb2011-10-07 13:54:59 -0400107static void seccomp_filter_usage(const char *progn)
108{
109 const struct syscall_entry *entry = syscall_table;
110 printf("Usage: %s -S <policy.file> <program> [args...]\n\n"
111 "System call names supported:\n", progn);
112 for (; entry->name && entry->nr >= 0; ++entry)
113 printf(" %s [%d]\n", entry->name, entry->nr);
114 printf("\nSee minijail0(5) for example policies.\n");
Will Drewry32ac9f52011-08-18 21:36:27 -0500115}
116
Christopher Wiley88f76a72013-11-01 14:12:56 -0700117static int parse_args(struct minijail *j, int argc, char *argv[],
118 int *exit_immediately)
Elly Jonese1749eb2011-10-07 13:54:59 -0400119{
Elly Jonese1749eb2011-10-07 13:54:59 -0400120 int opt;
Christopher Wiley88f76a72013-11-01 14:12:56 -0700121 int use_pid_ns = 0;
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500122 if (argc > 1 && argv[1][0] != '-')
123 return 1;
Christopher Wiley88f76a72013-11-01 14:12:56 -0700124 while ((opt = getopt(argc, argv, "u:g:sS:c:C:b:vrGhHinpLe")) != -1) {
Elly Jonese1749eb2011-10-07 13:54:59 -0400125 switch (opt) {
126 case 'u':
127 set_user(j, optarg);
128 break;
129 case 'g':
130 set_group(j, optarg);
131 break;
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -0700132 case 'n':
133 minijail_no_new_privs(j);
Jorge Lucangeli Obes0341d6c2012-07-16 15:27:31 -0700134 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400135 case 's':
136 minijail_use_seccomp(j);
137 break;
138 case 'S':
139 minijail_parse_seccomp_filters(j, optarg);
140 minijail_use_seccomp_filter(j);
141 break;
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700142 case 'L':
143 minijail_log_seccomp_filter_failures(j);
144 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400145 case 'b':
146 add_binding(j, optarg);
147 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400148 case 'c':
149 use_caps(j, optarg);
150 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400151 case 'C':
152 minijail_enter_chroot(j, optarg);
153 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400154 case 'v':
155 minijail_namespace_vfs(j);
156 break;
157 case 'r':
158 minijail_remount_readonly(j);
159 break;
160 case 'G':
161 minijail_inherit_usergroups(j);
162 break;
163 case 'p':
Christopher Wiley88f76a72013-11-01 14:12:56 -0700164 if (*exit_immediately) {
165 fprintf(stderr,
166 "Could not enter pid namespace because "
167 "'-i' was specified.");
168 exit(1);
169 }
170 use_pid_ns = 1;
Elly Jonese1749eb2011-10-07 13:54:59 -0400171 minijail_namespace_pids(j);
172 break;
Elly Fong-Jones6c086302013-03-20 17:15:28 -0400173 case 'e':
174 minijail_namespace_net(j);
175 break;
Christopher Wiley88f76a72013-11-01 14:12:56 -0700176 case 'i':
177 if (use_pid_ns) {
178 fprintf(stderr,
179 "Could not disable init loop because "
180 "'-p' was specified.");
181 exit(1);
182 }
183 *exit_immediately = 1;
184 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400185 case 'H':
186 seccomp_filter_usage(argv[0]);
187 exit(1);
188 default:
189 usage(argv[0]);
190 exit(1);
191 }
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500192 if (optind < argc && argv[optind][0] != '-')
193 return optind;
Elly Jonese1749eb2011-10-07 13:54:59 -0400194 }
Elly Jonescd7a9042011-07-22 13:56:51 -0400195
Elly Jonese1749eb2011-10-07 13:54:59 -0400196 if (argc == optind) {
197 usage(argv[0]);
198 exit(1);
199 }
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500200 return optind;
201}
Elly Jonescd7a9042011-07-22 13:56:51 -0400202
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500203int main(int argc, char *argv[])
204{
205 struct minijail *j = minijail_new();
Christopher Wiley88f76a72013-11-01 14:12:56 -0700206 int exit_immediately = 0;
207 int consumed = parse_args(j, argc, argv, &exit_immediately);
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500208 argc -= consumed;
209 argv += consumed;
Elly Fong-Jones6d717852013-03-19 16:29:03 -0400210 if (access(argv[0], X_OK)) {
211 fprintf(stderr, "Target program '%s' not accessible\n",
212 argv[0]);
213 return 1;
214 }
Elly Jonese1749eb2011-10-07 13:54:59 -0400215 minijail_run(j, argv[0], argv);
Christopher Wiley88f76a72013-11-01 14:12:56 -0700216 if (exit_immediately) {
217 info("not running init loop, exiting immediately");
218 return 0;
219 }
Elly Jonese1749eb2011-10-07 13:54:59 -0400220 return minijail_wait(j);
Elly Jonescd7a9042011-07-22 13:56:51 -0400221}