diff options
author | 2016-02-23 08:43:05 -0500 | |
---|---|---|
committer | 2016-02-23 08:43:05 -0500 | |
commit | 4e86686da02b39e650edbb80e2fc837d2ccd3a33 (patch) | |
tree | 64de359a6637aad926ad5a9b398365d99aab408f /src | |
parent | Merge pull request #315 from vn971/master (diff) | |
download | firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.gz firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.zst firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.zip |
x11 work
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/firejail.h | 5 | ||||
-rw-r--r-- | src/firejail/main.c | 4 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 4 | ||||
-rw-r--r-- | src/firejail/x11.c | 217 |
4 files changed, 229 insertions, 1 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 4babc58e7..acb49d246 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -46,6 +46,7 @@ | |||
46 | #define RUN_PULSE_DIR "/run/firejail/mnt/pulse" | 46 | #define RUN_PULSE_DIR "/run/firejail/mnt/pulse" |
47 | #define RUN_DEVLOG_FILE "/run/firejail/mnt/devlog" | 47 | #define RUN_DEVLOG_FILE "/run/firejail/mnt/devlog" |
48 | 48 | ||
49 | #define RUN_WHITELIST_X11_DIR "/run/firejail/mnt/orig-x11" | ||
49 | #define RUN_WHITELIST_HOME_DIR "/run/firejail/mnt/orig-home" // default home directory masking | 50 | #define RUN_WHITELIST_HOME_DIR "/run/firejail/mnt/orig-home" // default home directory masking |
50 | #define RUN_WHITELIST_HOME_USER_DIR "/run/firejail/mnt/orig-home-user" // home directory whitelisting | 51 | #define RUN_WHITELIST_HOME_USER_DIR "/run/firejail/mnt/orig-home-user" // home directory whitelisting |
51 | #define RUN_WHITELIST_TMP_DIR "/run/firejail/mnt/orig-tmp" | 52 | #define RUN_WHITELIST_TMP_DIR "/run/firejail/mnt/orig-tmp" |
@@ -520,5 +521,9 @@ char **build_paths(void); | |||
520 | // fs_mkdir.c | 521 | // fs_mkdir.c |
521 | void fs_mkdir(const char *name); | 522 | void fs_mkdir(const char *name); |
522 | 523 | ||
524 | // x11.c | ||
525 | void fs_x11(void); | ||
526 | void x11_start(int argc, char **argv); | ||
527 | |||
523 | #endif | 528 | #endif |
524 | 529 | ||
diff --git a/src/firejail/main.c b/src/firejail/main.c index f02da66aa..2a5ded984 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -263,6 +263,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
263 | #endif | 263 | #endif |
264 | exit(0); | 264 | exit(0); |
265 | } | 265 | } |
266 | else if (strcmp(argv[i], "--x11") == 0) { | ||
267 | x11_start(argc, argv); | ||
268 | exit(0); | ||
269 | } | ||
266 | #ifdef HAVE_NETWORK | 270 | #ifdef HAVE_NETWORK |
267 | else if (strncmp(argv[i], "--bandwidth=", 12) == 0) { | 271 | else if (strncmp(argv[i], "--bandwidth=", 12) == 0) { |
268 | logargs(argc, argv); | 272 | logargs(argc, argv); |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 1ba655301..d43e1dac1 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -588,13 +588,15 @@ int sandbox(void* sandbox_arg) { | |||
588 | errno = 0; | 588 | errno = 0; |
589 | int rv = nice(cfg.nice); | 589 | int rv = nice(cfg.nice); |
590 | (void) rv; | 590 | (void) rv; |
591 | printf("nice rv %d\n", rv); | ||
592 | if (errno) { | 591 | if (errno) { |
593 | fprintf(stderr, "Warning: cannot set nice value\n"); | 592 | fprintf(stderr, "Warning: cannot set nice value\n"); |
594 | errno = 0; | 593 | errno = 0; |
595 | } | 594 | } |
596 | } | 595 | } |
597 | 596 | ||
597 | // clean /tmp/.X11-unix sockets | ||
598 | fs_x11(); | ||
599 | |||
598 | //**************************** | 600 | //**************************** |
599 | // set security filters | 601 | // set security filters |
600 | //**************************** | 602 | //**************************** |
diff --git a/src/firejail/x11.c b/src/firejail/x11.c new file mode 100644 index 000000000..5e8fb9bbd --- /dev/null +++ b/src/firejail/x11.c | |||
@@ -0,0 +1,217 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2016 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firejail.h" | ||
21 | #include <sys/types.h> | ||
22 | #include <sys/stat.h> | ||
23 | #include <unistd.h> | ||
24 | #include <signal.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <dirent.h> | ||
27 | #include <sys/mount.h> | ||
28 | |||
29 | void fs_x11(void) { | ||
30 | // extract display | ||
31 | char *d = getenv("DISPLAY"); | ||
32 | if (!d) | ||
33 | return; | ||
34 | |||
35 | int display; | ||
36 | int rv = sscanf(d, ":%d", &display); | ||
37 | if (rv != 1) | ||
38 | return; | ||
39 | if (arg_debug) | ||
40 | printf("DISPLAY %s, %d\n", d, display); | ||
41 | |||
42 | char *x11file; | ||
43 | if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1) | ||
44 | errExit("asprintf"); | ||
45 | struct stat s; | ||
46 | if (stat(x11file, &s) == -1) | ||
47 | return; | ||
48 | |||
49 | // keep a copy of real /tmp/.X11-unix directory in WHITELIST_TMP_DIR | ||
50 | rv = mkdir(RUN_WHITELIST_X11_DIR, 1777); | ||
51 | if (rv == -1) | ||
52 | errExit("mkdir"); | ||
53 | if (chown(RUN_WHITELIST_X11_DIR, 0, 0) < 0) | ||
54 | errExit("chown"); | ||
55 | if (chmod(RUN_WHITELIST_X11_DIR, 1777) < 0) | ||
56 | errExit("chmod"); | ||
57 | |||
58 | if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
59 | errExit("mount bind"); | ||
60 | |||
61 | // mount tmpfs on /tmp/.X11-unix | ||
62 | if (arg_debug || arg_debug_whitelists) | ||
63 | printf("Mounting tmpfs on /tmp/.X11-unix directory\n"); | ||
64 | if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=1777,gid=0") < 0) | ||
65 | errExit("mounting tmpfs on /tmp"); | ||
66 | fs_logger("mount tmpfs on /tmp/.X11-unix"); | ||
67 | |||
68 | // create an empty file | ||
69 | FILE *fp = fopen(x11file, "w"); | ||
70 | if (!fp) { | ||
71 | fprintf(stderr, "Error: cannot create empty file in x11 directory\n"); | ||
72 | exit(1); | ||
73 | } | ||
74 | fclose(fp); | ||
75 | |||
76 | // set file properties | ||
77 | if (chown(x11file, s.st_uid, s.st_gid) < 0) | ||
78 | errExit("chown"); | ||
79 | if (chmod(x11file, s.st_mode) < 0) | ||
80 | errExit("chmod"); | ||
81 | |||
82 | // mount | ||
83 | char *wx11file; | ||
84 | if (asprintf(&wx11file, "%s/X%d", RUN_WHITELIST_X11_DIR, display) == -1) | ||
85 | errExit("asprintf"); | ||
86 | if (mount(wx11file, x11file, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
87 | errExit("mount bind"); | ||
88 | fs_logger2("whitelist", x11file); | ||
89 | |||
90 | free(x11file); | ||
91 | free(wx11file); | ||
92 | |||
93 | // block access to RUN_WHITELIST_X11_DIR | ||
94 | if (mount(RUN_RO_DIR, RUN_WHITELIST_X11_DIR, "none", MS_BIND, "mode=400,gid=0") == -1) | ||
95 | errExit("mount"); | ||
96 | fs_logger2("blacklist", RUN_WHITELIST_X11_DIR); | ||
97 | } | ||
98 | |||
99 | |||
100 | void x11_start(int argc, char **argv) { | ||
101 | EUID_ASSERT(); | ||
102 | int i; | ||
103 | struct stat s; | ||
104 | pid_t client = 0; | ||
105 | pid_t server = 0; | ||
106 | |||
107 | // check xpra | ||
108 | if (stat("/usr/bin/xpra", &s) == -1) { | ||
109 | fprintf(stderr, "\nError: Xpra program was not found in /usr/bin directory, please install it:\n"); | ||
110 | fprintf(stderr, " Arch: sudo pacman -S xpra\n"); | ||
111 | fprintf(stderr, " Debian/Ubuntu/Mint: sudo apt-get install xpra\n"); | ||
112 | fprintf(stderr, " Fedora/CentOS: sudo yum install xpra\n"); | ||
113 | fprintf(stderr, " Gentoo: sudo emerge xpra\n\n"); | ||
114 | exit(0); | ||
115 | } | ||
116 | |||
117 | int display; | ||
118 | int found = 1; | ||
119 | for (i = 0; i < 100; i++) { | ||
120 | display = rand() % 1024; | ||
121 | char *fname; | ||
122 | if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) | ||
123 | errExit("asprintf"); | ||
124 | if (stat(fname, &s) == -1) { | ||
125 | found = 1; | ||
126 | break; | ||
127 | } | ||
128 | } | ||
129 | if (!found) { | ||
130 | fprintf(stderr, "Error: cannot pick up a random X11 display number, exiting...\n"); | ||
131 | exit(1); | ||
132 | } | ||
133 | |||
134 | // build the start command | ||
135 | int len = 50; // xpra start... | ||
136 | for (i = 0; i < argc; i++) { | ||
137 | len += strlen(argv[i]) + 1; // + ' ' | ||
138 | } | ||
139 | |||
140 | char *cmd1 = malloc(len + 1); // + '\0' | ||
141 | if (!cmd1) | ||
142 | errExit("malloc"); | ||
143 | |||
144 | sprintf(cmd1, "xpra start :%d --exit-with-children --start-child=\"", display); | ||
145 | char *ptr = cmd1 + strlen(cmd1); | ||
146 | for (i = 0; i < argc; i++) { | ||
147 | if (strcmp(argv[i], "--x11") == 0) | ||
148 | continue; | ||
149 | ptr += sprintf(ptr, "%s ", argv[i]); | ||
150 | } | ||
151 | sprintf(ptr, "\""); | ||
152 | if (arg_debug) | ||
153 | printf("xpra server: %s\n", cmd1); | ||
154 | |||
155 | // build the attach command | ||
156 | char *cmd2; | ||
157 | if (asprintf(&cmd2, "xpra attach :%d", display) == -1) | ||
158 | errExit("asprintf"); | ||
159 | if (arg_debug) | ||
160 | printf("xpra client: %s\n", cmd2); | ||
161 | |||
162 | signal(SIGHUP,SIG_IGN); // fix sleep(1`) below | ||
163 | server = fork(); | ||
164 | if (server < 0) | ||
165 | errExit("fork"); | ||
166 | if (server == 0) { | ||
167 | if (arg_debug) | ||
168 | printf("Starting xpra...\n"); | ||
169 | |||
170 | char *a[4]; | ||
171 | a[0] = "/bin/bash"; | ||
172 | a[1] = "-c"; | ||
173 | a[2] = cmd1; | ||
174 | a[3] = NULL; | ||
175 | |||
176 | execvp(a[0], a); | ||
177 | perror("execvp"); | ||
178 | exit(1); | ||
179 | } | ||
180 | sleep(1); | ||
181 | if (arg_debug) { | ||
182 | printf("X11 sockets: "); fflush(0); | ||
183 | int rv = system("ls /tmp/.X11-unix"); | ||
184 | (void) rv; | ||
185 | } | ||
186 | |||
187 | // check X11 socket | ||
188 | char *fname; | ||
189 | if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1) | ||
190 | errExit("asprintf"); | ||
191 | if (stat(fname, &s) == -1) { | ||
192 | fprintf(stderr, "Error: failed to start xpra\n"); | ||
193 | exit(1); | ||
194 | } | ||
195 | |||
196 | // run attach command | ||
197 | client = fork(); | ||
198 | if (client < 0) | ||
199 | errExit("fork"); | ||
200 | if (client == 0) { | ||
201 | printf("\n*** Attaching to xpra display %d ***\n\n", display); | ||
202 | char *a[4]; | ||
203 | a[0] = "/bin/bash"; | ||
204 | a[1] = "-c"; | ||
205 | a[2] = cmd2; | ||
206 | a[3] = NULL; | ||
207 | |||
208 | execvp(a[0], a); | ||
209 | perror("execvp"); | ||
210 | exit(1); | ||
211 | } | ||
212 | sleep(1); | ||
213 | |||
214 | if (!arg_quiet) | ||
215 | printf("Xpra server pid %d, client pid %d\n", server, client); | ||
216 | exit(0); | ||
217 | } | ||