aboutsummaryrefslogtreecommitdiffstats
path: root/src
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 /src
parentMerge pull request #315 from vn971/master (diff)
downloadfirejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.gz
firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.tar.zst
firejail-4e86686da02b39e650edbb80e2fc837d2ccd3a33.zip
x11 work
Diffstat (limited to 'src')
-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
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
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}