blob: a71811e7c8e44a6ea48f830d3e40c40e46abcfe6 [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
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -070076 printf("Usage: %s [-Ghnprsv] [-b <src>,<dest>[,<writeable>]] "
77 "[-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"
Elly Fong-Jones6c086302013-03-20 17:15:28 -040083 " -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"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070088 " -L: log blocked syscalls when using seccomp filter. "
89 "Forces the following syscalls to be allowed:\n"
90 " ", progn);
91 for (i = 0; i < log_syscalls_len; i++)
92 printf("%s ", log_syscalls[i]);
93
94 printf("\n"
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -070095 " -n: set no_new_privs\n"
Elly Jonese58176c2012-01-23 11:46:17 -050096 " -p: use pid namespace (implies -vr)\n"
Elly Jonesfdd5f2d2012-01-23 13:27:43 -050097 " -r: remount /proc readonly (implies -v)\n"
Elly Jonese1749eb2011-10-07 13:54:59 -040098 " -s: use seccomp\n"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -070099 " -S <file>: set seccomp filter using <file>\n"
Elly Jonese1749eb2011-10-07 13:54:59 -0400100 " E.g., -S /usr/share/filters/<prog>.$(uname -m)\n"
101 " -u <user>: change uid to <user>\n"
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700102 " -v: use vfs namespace\n");
Elly Jonescd7a9042011-07-22 13:56:51 -0400103}
104
Elly Jonese1749eb2011-10-07 13:54:59 -0400105static void seccomp_filter_usage(const char *progn)
106{
107 const struct syscall_entry *entry = syscall_table;
108 printf("Usage: %s -S <policy.file> <program> [args...]\n\n"
109 "System call names supported:\n", progn);
110 for (; entry->name && entry->nr >= 0; ++entry)
111 printf(" %s [%d]\n", entry->name, entry->nr);
112 printf("\nSee minijail0(5) for example policies.\n");
Will Drewry32ac9f52011-08-18 21:36:27 -0500113}
114
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500115static int parse_args(struct minijail *j, int argc, char *argv[])
Elly Jonese1749eb2011-10-07 13:54:59 -0400116{
Elly Jonese1749eb2011-10-07 13:54:59 -0400117 int opt;
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500118 if (argc > 1 && argv[1][0] != '-')
119 return 1;
Elly Fong-Jones6c086302013-03-20 17:15:28 -0400120 while ((opt = getopt(argc, argv, "u:g:sS:c:C:b:vrGhHnpLe")) != -1) {
Elly Jonese1749eb2011-10-07 13:54:59 -0400121 switch (opt) {
122 case 'u':
123 set_user(j, optarg);
124 break;
125 case 'g':
126 set_group(j, optarg);
127 break;
Jorge Lucangeli Obesc2c9bcc2012-05-01 09:30:24 -0700128 case 'n':
129 minijail_no_new_privs(j);
Jorge Lucangeli Obes0341d6c2012-07-16 15:27:31 -0700130 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400131 case 's':
132 minijail_use_seccomp(j);
133 break;
134 case 'S':
135 minijail_parse_seccomp_filters(j, optarg);
136 minijail_use_seccomp_filter(j);
137 break;
Jorge Lucangeli Obesbda833c2012-07-31 16:25:56 -0700138 case 'L':
139 minijail_log_seccomp_filter_failures(j);
140 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400141 case 'b':
142 add_binding(j, optarg);
143 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400144 case 'c':
145 use_caps(j, optarg);
146 break;
Elly Jones51a5b6c2011-10-12 19:09:26 -0400147 case 'C':
148 minijail_enter_chroot(j, optarg);
149 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400150 case 'v':
151 minijail_namespace_vfs(j);
152 break;
153 case 'r':
154 minijail_remount_readonly(j);
155 break;
156 case 'G':
157 minijail_inherit_usergroups(j);
158 break;
159 case 'p':
160 minijail_namespace_pids(j);
161 break;
Elly Fong-Jones6c086302013-03-20 17:15:28 -0400162 case 'e':
163 minijail_namespace_net(j);
164 break;
Elly Jonese1749eb2011-10-07 13:54:59 -0400165 case 'H':
166 seccomp_filter_usage(argv[0]);
167 exit(1);
168 default:
169 usage(argv[0]);
170 exit(1);
171 }
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500172 if (optind < argc && argv[optind][0] != '-')
173 return optind;
Elly Jonese1749eb2011-10-07 13:54:59 -0400174 }
Elly Jonescd7a9042011-07-22 13:56:51 -0400175
Elly Jonese1749eb2011-10-07 13:54:59 -0400176 if (argc == optind) {
177 usage(argv[0]);
178 exit(1);
179 }
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500180 return optind;
181}
Elly Jonescd7a9042011-07-22 13:56:51 -0400182
Elly Fong-Jonesf65c9fe2013-01-22 13:55:02 -0500183int main(int argc, char *argv[])
184{
185 struct minijail *j = minijail_new();
186 int consumed = parse_args(j, argc, argv);
187 argc -= consumed;
188 argv += consumed;
Elly Fong-Jones6d717852013-03-19 16:29:03 -0400189 if (access(argv[0], X_OK)) {
190 fprintf(stderr, "Target program '%s' not accessible\n",
191 argv[0]);
192 return 1;
193 }
Elly Jonese1749eb2011-10-07 13:54:59 -0400194 minijail_run(j, argv[0], argv);
195 return minijail_wait(j);
Elly Jonescd7a9042011-07-22 13:56:51 -0400196}