aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/no_sandbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/no_sandbox.c')
-rw-r--r--src/firejail/no_sandbox.c217
1 files changed, 181 insertions, 36 deletions
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index a9242f035..aae490c34 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -23,6 +23,65 @@
23#include <unistd.h> 23#include <unistd.h>
24#include <grp.h> 24#include <grp.h>
25 25
26#define MAX_BUF 4096
27
28int is_container(const char *str) {
29 assert(str);
30 if (strcmp(str, "lxc") == 0 ||
31 strcmp(str, "docker") == 0 ||
32 strcmp(str, "lxc-libvirt") == 0 ||
33 strcmp(str, "systemd-nspawn") == 0 ||
34 strcmp(str, "rkt") == 0)
35 return 1;
36 return 0;
37}
38
39// returns 1 if we are running under LXC
40int check_namespace_virt(void) {
41 EUID_ASSERT();
42
43 // check container environment variable
44 char *str = getenv("container");
45 if (str && is_container(str))
46 return 1;
47
48 // check PID 1 container environment variable
49 EUID_ROOT();
50 FILE *fp = fopen("/proc/1/environ", "r");
51 if (fp) {
52 int c = 0;
53 while (c != EOF) {
54 // read one line
55 char buf[MAX_BUF];
56 int i = 0;
57 while ((c = fgetc(fp)) != EOF) {
58 if (c == 0)
59 break;
60 buf[i] = (char) c;
61 if (++i == (MAX_BUF - 1))
62 break;
63 }
64 buf[i] = '\0';
65
66 // check env var name
67 if (strncmp(buf, "container=", 10) == 0) {
68 // found it
69 if (is_container(buf + 10)) {
70 fclose(fp);
71 EUID_USER();
72 return 1;
73 }
74 }
75// printf("i %d c %d, buf #%s#\n", i, c, buf);
76 }
77
78 fclose(fp);
79 }
80
81 EUID_USER();
82 return 0;
83}
84
26// check process space for kernel processes 85// check process space for kernel processes
27// return 1 if found, 0 if not found 86// return 1 if found, 0 if not found
28int check_kernel_procs(void) { 87int check_kernel_procs(void) {
@@ -103,44 +162,130 @@ int check_kernel_procs(void) {
103void run_no_sandbox(int argc, char **argv) { 162void run_no_sandbox(int argc, char **argv) {
104 EUID_ASSERT(); 163 EUID_ASSERT();
105 164
106 // build command 165 // process limited subset of options
107 char *command = NULL; 166 int i;
108 int allocated = 0; 167 for (i = 0; i < argc; i++) {
109 if (argc == 1) 168 if (strcmp(argv[i], "--csh") == 0) {
110 command = "/bin/bash"; 169 if (arg_shell_none) {
111 else { 170 fprintf(stderr, "Error: --shell=none was already specified.\n");
112 // calculate length 171 exit(1);
113 int len = 0; 172 }
114 int i; 173 if (cfg.shell) {
115 for (i = 1; i < argc; i++) { 174 fprintf(stderr, "Error: only one default user shell can be specified\n");
116 if (*argv[i] == '-') 175 exit(1);
117 continue; 176 }
177 cfg.shell = "/bin/csh";
178 }
179 else if (strcmp(argv[i], "--zsh") == 0) {
180 if (arg_shell_none) {
181 fprintf(stderr, "Error: --shell=none was already specified.\n");
182 exit(1);
183 }
184 if (cfg.shell) {
185 fprintf(stderr, "Error: only one default user shell can be specified\n");
186 exit(1);
187 }
188 cfg.shell = "/bin/zsh";
189 }
190 else if (strcmp(argv[i], "--shell=none") == 0) {
191 arg_shell_none = 1;
192 if (cfg.shell) {
193 fprintf(stderr, "Error: a shell was already specified\n");
194 exit(1);
195 }
196 }
197 else if (strncmp(argv[i], "--shell=", 8) == 0) {
198 if (arg_shell_none) {
199 fprintf(stderr, "Error: --shell=none was already specified.\n");
200 exit(1);
201 }
202 invalid_filename(argv[i] + 8);
203
204 if (cfg.shell) {
205 fprintf(stderr, "Error: only one user shell can be specified\n");
206 exit(1);
207 }
208 cfg.shell = argv[i] + 8;
209
210 if (is_dir(cfg.shell) || strstr(cfg.shell, "..")) {
211 fprintf(stderr, "Error: invalid shell\n");
212 exit(1);
213 }
214
215 // access call checks as real UID/GID, not as effective UID/GID
216 if(cfg.chrootdir) {
217 char *shellpath;
218 if (asprintf(&shellpath, "%s%s", cfg.chrootdir, cfg.shell) == -1)
219 errExit("asprintf");
220 if (access(shellpath, R_OK)) {
221 fprintf(stderr, "Error: cannot access shell file in chroot\n");
222 exit(1);
223 }
224 free(shellpath);
225 } else if (access(cfg.shell, R_OK)) {
226 fprintf(stderr, "Error: cannot access shell file\n");
227 exit(1);
228 }
229 }
230 }
231
232 // use $SHELL to get shell used in sandbox
233 if (!arg_shell_none && !cfg.shell) {
234 char *shell = getenv("SHELL");
235 if (access(shell, R_OK) == 0)
236 cfg.shell = shell;
237 }
238 // guess shell otherwise
239 if (!arg_shell_none && !cfg.shell) {
240 cfg.shell = guess_shell();
241 if (arg_debug)
242 printf("Autoselecting %s as shell\n", cfg.shell);
243 }
244 if (!arg_shell_none && !cfg.shell) {
245 fprintf(stderr, "Error: unable to guess your shell, please set explicitly by using --shell option.\n");
246 exit(1);
247 }
248
249 int prog_index = 0;
250 // find first non option arg:
251 // - first argument not starting wiht --,
252 // - whatever follows after -c (example: firejail -c ls)
253 for (i = 1; i < argc; i++) {
254 if (strcmp(argv[i], "-c") == 0) {
255 prog_index = i + 1;
256 if (prog_index == argc) {
257 fprintf(stderr, "Error: option -c requires an argument\n");
258 exit(1);
259 }
118 break; 260 break;
119 } 261 }
120 int start_index = i; 262 // check first argument not starting with --
121 for (i = start_index; i < argc; i++) 263 if (strncmp(argv[i],"--",2) != 0) {
122 len += strlen(argv[i]) + 1; 264 prog_index = i;
123 265 break;
124 // allocate
125 command = malloc(len + 1);
126 if (!command)
127 errExit("malloc");
128 memset(command, 0, len + 1);
129 allocated = 1;
130
131 // copy
132 for (i = start_index; i < argc; i++) {
133 strcat(command, argv[i]);
134 strcat(command, " ");
135 } 266 }
136 } 267 }
137 268
138 // start the program in /bin/sh 269 if (!arg_shell_none) {
139 fprintf(stderr, "Warning: an existing sandbox was detected. " 270 if (prog_index == 0) {
140 "%s will run without any additional sandboxing features in a /bin/sh shell\n", command); 271 cfg.command_line = cfg.shell;
141 int rv = system(command); 272 cfg.window_title = cfg.shell;
142 (void) rv; 273 } else {
143 if (allocated) 274 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
144 free(command); 275 }
145 exit(1); 276 }
277
278 cfg.original_argv = argv;
279 cfg.original_program_index = prog_index;
280
281 char *command;
282 if (prog_index == 0)
283 command = cfg.shell;
284 else
285 command = argv[prog_index];
286 if (!arg_quiet)
287 fprintf(stderr, "Warning: an existing sandbox was detected. "
288 "%s will run without any additional sandboxing features\n", command);
289
290 start_application();
146} 291}