aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-02-23 08:43:05 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2016-02-23 08:43:05 -0500
commit4e86686da02b39e650edbb80e2fc837d2ccd3a33 (patch)
tree64de359a6637aad926ad5a9b398365d99aab408f
parentMerge pull request #315 from vn971/master (diff)
downloadfirejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.gz
firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.zst
firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.zip
x11 work
-rw-r--r--src/firejail/firejail.h5
-rw-r--r--src/firejail/main.c4
-rw-r--r--src/firejail/sandbox.c4
-rw-r--r--src/firejail/x11.c217
-rwxr-xr-xtest/chromium-x11.exp75
-rwxr-xr-xtest/firefox-x11.exp68
-rwxr-xr-xtest/test-apps-x11.sh29
-rwxr-xr-xtest/test.sh1
-rwxr-xr-xtest/transmission-gtk-x11.exp74
9 files changed, 476 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
521void fs_mkdir(const char *name); 522void fs_mkdir(const char *name);
522 523
524// x11.c
525void fs_x11(void);
526void 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;
591printf("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
29void 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
100void 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}
diff --git a/test/chromium-x11.exp b/test/chromium-x11.exp
new file mode 100755
index 000000000..0d8a5dfb3
--- /dev/null
+++ b/test/chromium-x11.exp
@@ -0,0 +1,75 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=test --x11 --net=br0 chromium www.gentoo.org\r"
8sleep 10
9
10spawn $env(SHELL)
11send -- "firejail --list\r"
12expect {
13 timeout {puts "TESTING ERROR 3\n";exit}
14 ":firejail"
15}
16expect {
17 timeout {puts "TESTING ERROR 3.1\n";exit}
18 "chromium"
19}
20sleep 1
21
22send -- "firejail --name=blablabla\r"
23expect {
24 timeout {puts "TESTING ERROR 4\n";exit}
25 "Child process initialized"
26}
27sleep 2
28
29spawn $env(SHELL)
30send -- "firemon --seccomp\r"
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 ":firejail"
34}
35expect {
36 timeout {puts "TESTING ERROR 5.0\n";exit}
37 "chromium"
38}
39expect {
40 timeout {puts "TESTING ERROR 5.1\n";exit}
41 "Seccomp: 0"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1\n";exit}
45 "name=blablabla"
46}
47sleep 1
48send -- "firemon --caps\r"
49expect {
50 timeout {puts "TESTING ERROR 6\n";exit}
51 ":firejail"
52}
53expect {
54 timeout {puts "TESTING ERROR 6.0\n";exit}
55 "chromium"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd:"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "fffffffff"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70send -- "firejail --shutdown=test\r"
71sleep 3
72
73
74puts "\nall done\n"
75
diff --git a/test/firefox-x11.exp b/test/firefox-x11.exp
new file mode 100755
index 000000000..c82408896
--- /dev/null
+++ b/test/firefox-x11.exp
@@ -0,0 +1,68 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=test --x11 --net=br0 firefox www.gentoo.org\r"
8sleep 10
9
10spawn $env(SHELL)
11send -- "firejail --list\r"
12expect {
13 timeout {puts "TESTING ERROR 3\n";exit}
14 ":firejail"
15}
16expect {
17 timeout {puts "TESTING ERROR 3.1\n";exit}
18 "firefox" {puts "firefox detected\n";}
19 "iceweasel" {puts "iceweasel detected\n";}
20}
21sleep 1
22send -- "firejail --name=blablabla\r"
23expect {
24 timeout {puts "TESTING ERROR 4\n";exit}
25 "Child process initialized"
26}
27sleep 2
28
29spawn $env(SHELL)
30send -- "firemon --seccomp\r"
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 " firefox" {puts "firefox detected\n";}
34 " iceweasel" {puts "iceweasel detected\n";}
35}
36expect {
37 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
38 "Seccomp: 2"
39}
40expect {
41 timeout {puts "TESTING ERROR 5.1\n";exit}
42 "name=blablabla"
43}
44sleep 1
45send -- "firemon --caps\r"
46expect {
47 timeout {puts "TESTING ERROR 6\n";exit}
48 " firefox" {puts "firefox detected\n";}
49 " iceweasel" {puts "iceweasel detected\n";}
50}
51expect {
52 timeout {puts "TESTING ERROR 6.1\n";exit}
53 "CapBnd:"
54}
55expect {
56 timeout {puts "TESTING ERROR 6.2\n";exit}
57 "0000000000000000"
58}
59expect {
60 timeout {puts "TESTING ERROR 6.3\n";exit}
61 "name=blablabla"
62}
63sleep 1
64send -- "firejail --shutdown=test\r"
65sleep 3
66
67puts "\nall done\n"
68
diff --git a/test/test-apps-x11.sh b/test/test-apps-x11.sh
new file mode 100755
index 000000000..6521fa2b0
--- /dev/null
+++ b/test/test-apps-x11.sh
@@ -0,0 +1,29 @@
1#!/bin/bash
2
3which firefox
4if [ "$?" -eq 0 ];
5then
6 echo "TESTING: firefox x11"
7 ./firefox-x11.exp
8else
9 echo "TESTING: firefox not found"
10fi
11
12which chromium
13if [ "$?" -eq 0 ];
14then
15 echo "TESTING: chromium x11"
16 ./chromium-x11.exp
17else
18 echo "TESTING: chromium not found"
19fi
20
21which transmission-gtk
22if [ "$?" -eq 0 ];
23then
24 echo "TESTING: transmission-gtk x11"
25 ./transmission-gtk.exp
26else
27 echo "TESTING: transmission-gtk not found"
28fi
29
diff --git a/test/test.sh b/test/test.sh
index ddb8431c8..d7e9e2aed 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -166,6 +166,7 @@ else
166fi 166fi
167 167
168./test-apps.sh 168./test-apps.sh
169./test-apps-x11.sh
169 170
170echo "TESTING: PID (pid.exp)" 171echo "TESTING: PID (pid.exp)"
171./pid.exp 172./pid.exp
diff --git a/test/transmission-gtk-x11.exp b/test/transmission-gtk-x11.exp
new file mode 100755
index 000000000..6192b277c
--- /dev/null
+++ b/test/transmission-gtk-x11.exp
@@ -0,0 +1,74 @@
1#!/usr/bin/expect -f
2
3set timeout 10
4spawn $env(SHELL)
5match_max 100000
6
7send -- "firejail --name=test --net=br0 --x11 transmission-gtk\r"
8sleep 10
9
10spawn $env(SHELL)
11send -- "firejail --list\r"
12expect {
13 timeout {puts "TESTING ERROR 3\n";exit}
14 ":firejail"
15}
16expect {
17 timeout {puts "TESTING ERROR 3.1\n";exit}
18 "transmission-gtk"
19}
20sleep 1
21
22send -- "firejail --name=blablabla\r"
23expect {
24 timeout {puts "TESTING ERROR 4\n";exit}
25 "Child process initialized"
26}
27sleep 2
28
29spawn $env(SHELL)
30send -- "firemon --seccomp\r"
31expect {
32 timeout {puts "TESTING ERROR 5\n";exit}
33 ":firejail"
34}
35expect {
36 timeout {puts "TESTING ERROR 5.0\n";exit}
37 "transmission-gtk"
38}
39expect {
40 timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
41 "Seccomp: 2"
42}
43expect {
44 timeout {puts "TESTING ERROR 5.1\n";exit}
45 "name=blablabla"
46}
47sleep 1
48send -- "firemon --caps\r"
49expect {
50 timeout {puts "TESTING ERROR 6\n";exit}
51 ":firejail"
52}
53expect {
54 timeout {puts "TESTING ERROR 6.0\n";exit}
55 "transmission-gtk"
56}
57expect {
58 timeout {puts "TESTING ERROR 6.1\n";exit}
59 "CapBnd"
60}
61expect {
62 timeout {puts "TESTING ERROR 6.2\n";exit}
63 "0000000000000000"
64}
65expect {
66 timeout {puts "TESTING ERROR 6.3\n";exit}
67 "name=blablabla"
68}
69sleep 1
70send -- "firejail --shutdown=test\r"
71sleep 3
72
73puts "\nall done\n"
74