mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-22 14:15:46 -06:00
x11 work
This commit is contained in:
parent
84a8e7e8d4
commit
4e86686da0
9 changed files with 476 additions and 1 deletions
|
|
@ -46,6 +46,7 @@
|
|||
#define RUN_PULSE_DIR "/run/firejail/mnt/pulse"
|
||||
#define RUN_DEVLOG_FILE "/run/firejail/mnt/devlog"
|
||||
|
||||
#define RUN_WHITELIST_X11_DIR "/run/firejail/mnt/orig-x11"
|
||||
#define RUN_WHITELIST_HOME_DIR "/run/firejail/mnt/orig-home" // default home directory masking
|
||||
#define RUN_WHITELIST_HOME_USER_DIR "/run/firejail/mnt/orig-home-user" // home directory whitelisting
|
||||
#define RUN_WHITELIST_TMP_DIR "/run/firejail/mnt/orig-tmp"
|
||||
|
|
@ -520,5 +521,9 @@ char **build_paths(void);
|
|||
// fs_mkdir.c
|
||||
void fs_mkdir(const char *name);
|
||||
|
||||
// x11.c
|
||||
void fs_x11(void);
|
||||
void x11_start(int argc, char **argv);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -263,6 +263,10 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
|
|||
#endif
|
||||
exit(0);
|
||||
}
|
||||
else if (strcmp(argv[i], "--x11") == 0) {
|
||||
x11_start(argc, argv);
|
||||
exit(0);
|
||||
}
|
||||
#ifdef HAVE_NETWORK
|
||||
else if (strncmp(argv[i], "--bandwidth=", 12) == 0) {
|
||||
logargs(argc, argv);
|
||||
|
|
|
|||
|
|
@ -588,13 +588,15 @@ int sandbox(void* sandbox_arg) {
|
|||
errno = 0;
|
||||
int rv = nice(cfg.nice);
|
||||
(void) rv;
|
||||
printf("nice rv %d\n", rv);
|
||||
if (errno) {
|
||||
fprintf(stderr, "Warning: cannot set nice value\n");
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// clean /tmp/.X11-unix sockets
|
||||
fs_x11();
|
||||
|
||||
//****************************
|
||||
// set security filters
|
||||
//****************************
|
||||
|
|
|
|||
217
src/firejail/x11.c
Normal file
217
src/firejail/x11.c
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2016 Firejail Authors
|
||||
*
|
||||
* This file is part of firejail project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
#include "firejail.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/mount.h>
|
||||
|
||||
void fs_x11(void) {
|
||||
// extract display
|
||||
char *d = getenv("DISPLAY");
|
||||
if (!d)
|
||||
return;
|
||||
|
||||
int display;
|
||||
int rv = sscanf(d, ":%d", &display);
|
||||
if (rv != 1)
|
||||
return;
|
||||
if (arg_debug)
|
||||
printf("DISPLAY %s, %d\n", d, display);
|
||||
|
||||
char *x11file;
|
||||
if (asprintf(&x11file, "/tmp/.X11-unix/X%d", display) == -1)
|
||||
errExit("asprintf");
|
||||
struct stat s;
|
||||
if (stat(x11file, &s) == -1)
|
||||
return;
|
||||
|
||||
// keep a copy of real /tmp/.X11-unix directory in WHITELIST_TMP_DIR
|
||||
rv = mkdir(RUN_WHITELIST_X11_DIR, 1777);
|
||||
if (rv == -1)
|
||||
errExit("mkdir");
|
||||
if (chown(RUN_WHITELIST_X11_DIR, 0, 0) < 0)
|
||||
errExit("chown");
|
||||
if (chmod(RUN_WHITELIST_X11_DIR, 1777) < 0)
|
||||
errExit("chmod");
|
||||
|
||||
if (mount("/tmp/.X11-unix", RUN_WHITELIST_X11_DIR, NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind");
|
||||
|
||||
// mount tmpfs on /tmp/.X11-unix
|
||||
if (arg_debug || arg_debug_whitelists)
|
||||
printf("Mounting tmpfs on /tmp/.X11-unix directory\n");
|
||||
if (mount("tmpfs", "/tmp/.X11-unix", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=1777,gid=0") < 0)
|
||||
errExit("mounting tmpfs on /tmp");
|
||||
fs_logger("mount tmpfs on /tmp/.X11-unix");
|
||||
|
||||
// create an empty file
|
||||
FILE *fp = fopen(x11file, "w");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error: cannot create empty file in x11 directory\n");
|
||||
exit(1);
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
// set file properties
|
||||
if (chown(x11file, s.st_uid, s.st_gid) < 0)
|
||||
errExit("chown");
|
||||
if (chmod(x11file, s.st_mode) < 0)
|
||||
errExit("chmod");
|
||||
|
||||
// mount
|
||||
char *wx11file;
|
||||
if (asprintf(&wx11file, "%s/X%d", RUN_WHITELIST_X11_DIR, display) == -1)
|
||||
errExit("asprintf");
|
||||
if (mount(wx11file, x11file, NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind");
|
||||
fs_logger2("whitelist", x11file);
|
||||
|
||||
free(x11file);
|
||||
free(wx11file);
|
||||
|
||||
// block access to RUN_WHITELIST_X11_DIR
|
||||
if (mount(RUN_RO_DIR, RUN_WHITELIST_X11_DIR, "none", MS_BIND, "mode=400,gid=0") == -1)
|
||||
errExit("mount");
|
||||
fs_logger2("blacklist", RUN_WHITELIST_X11_DIR);
|
||||
}
|
||||
|
||||
|
||||
void x11_start(int argc, char **argv) {
|
||||
EUID_ASSERT();
|
||||
int i;
|
||||
struct stat s;
|
||||
pid_t client = 0;
|
||||
pid_t server = 0;
|
||||
|
||||
// check xpra
|
||||
if (stat("/usr/bin/xpra", &s) == -1) {
|
||||
fprintf(stderr, "\nError: Xpra program was not found in /usr/bin directory, please install it:\n");
|
||||
fprintf(stderr, " Arch: sudo pacman -S xpra\n");
|
||||
fprintf(stderr, " Debian/Ubuntu/Mint: sudo apt-get install xpra\n");
|
||||
fprintf(stderr, " Fedora/CentOS: sudo yum install xpra\n");
|
||||
fprintf(stderr, " Gentoo: sudo emerge xpra\n\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int display;
|
||||
int found = 1;
|
||||
for (i = 0; i < 100; i++) {
|
||||
display = rand() % 1024;
|
||||
char *fname;
|
||||
if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1)
|
||||
errExit("asprintf");
|
||||
if (stat(fname, &s) == -1) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fprintf(stderr, "Error: cannot pick up a random X11 display number, exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// build the start command
|
||||
int len = 50; // xpra start...
|
||||
for (i = 0; i < argc; i++) {
|
||||
len += strlen(argv[i]) + 1; // + ' '
|
||||
}
|
||||
|
||||
char *cmd1 = malloc(len + 1); // + '\0'
|
||||
if (!cmd1)
|
||||
errExit("malloc");
|
||||
|
||||
sprintf(cmd1, "xpra start :%d --exit-with-children --start-child=\"", display);
|
||||
char *ptr = cmd1 + strlen(cmd1);
|
||||
for (i = 0; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--x11") == 0)
|
||||
continue;
|
||||
ptr += sprintf(ptr, "%s ", argv[i]);
|
||||
}
|
||||
sprintf(ptr, "\"");
|
||||
if (arg_debug)
|
||||
printf("xpra server: %s\n", cmd1);
|
||||
|
||||
// build the attach command
|
||||
char *cmd2;
|
||||
if (asprintf(&cmd2, "xpra attach :%d", display) == -1)
|
||||
errExit("asprintf");
|
||||
if (arg_debug)
|
||||
printf("xpra client: %s\n", cmd2);
|
||||
|
||||
signal(SIGHUP,SIG_IGN); // fix sleep(1`) below
|
||||
server = fork();
|
||||
if (server < 0)
|
||||
errExit("fork");
|
||||
if (server == 0) {
|
||||
if (arg_debug)
|
||||
printf("Starting xpra...\n");
|
||||
|
||||
char *a[4];
|
||||
a[0] = "/bin/bash";
|
||||
a[1] = "-c";
|
||||
a[2] = cmd1;
|
||||
a[3] = NULL;
|
||||
|
||||
execvp(a[0], a);
|
||||
perror("execvp");
|
||||
exit(1);
|
||||
}
|
||||
sleep(1);
|
||||
if (arg_debug) {
|
||||
printf("X11 sockets: "); fflush(0);
|
||||
int rv = system("ls /tmp/.X11-unix");
|
||||
(void) rv;
|
||||
}
|
||||
|
||||
// check X11 socket
|
||||
char *fname;
|
||||
if (asprintf(&fname, "/tmp/.X11-unix/X%d", display) == -1)
|
||||
errExit("asprintf");
|
||||
if (stat(fname, &s) == -1) {
|
||||
fprintf(stderr, "Error: failed to start xpra\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// run attach command
|
||||
client = fork();
|
||||
if (client < 0)
|
||||
errExit("fork");
|
||||
if (client == 0) {
|
||||
printf("\n*** Attaching to xpra display %d ***\n\n", display);
|
||||
char *a[4];
|
||||
a[0] = "/bin/bash";
|
||||
a[1] = "-c";
|
||||
a[2] = cmd2;
|
||||
a[3] = NULL;
|
||||
|
||||
execvp(a[0], a);
|
||||
perror("execvp");
|
||||
exit(1);
|
||||
}
|
||||
sleep(1);
|
||||
|
||||
if (!arg_quiet)
|
||||
printf("Xpra server pid %d, client pid %d\n", server, client);
|
||||
exit(0);
|
||||
}
|
||||
75
test/chromium-x11.exp
Executable file
75
test/chromium-x11.exp
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/expect -f
|
||||
|
||||
set timeout 10
|
||||
spawn $env(SHELL)
|
||||
match_max 100000
|
||||
|
||||
send -- "firejail --name=test --x11 --net=br0 chromium www.gentoo.org\r"
|
||||
sleep 10
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firejail --list\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3.1\n";exit}
|
||||
"chromium"
|
||||
}
|
||||
sleep 1
|
||||
|
||||
send -- "firejail --name=blablabla\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 4\n";exit}
|
||||
"Child process initialized"
|
||||
}
|
||||
sleep 2
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firemon --seccomp\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.0\n";exit}
|
||||
"chromium"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1\n";exit}
|
||||
"Seccomp: 0"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firemon --caps\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.0\n";exit}
|
||||
"chromium"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.1\n";exit}
|
||||
"CapBnd:"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.2\n";exit}
|
||||
"fffffffff"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.3\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firejail --shutdown=test\r"
|
||||
sleep 3
|
||||
|
||||
|
||||
puts "\nall done\n"
|
||||
|
||||
68
test/firefox-x11.exp
Executable file
68
test/firefox-x11.exp
Executable file
|
|
@ -0,0 +1,68 @@
|
|||
#!/usr/bin/expect -f
|
||||
|
||||
set timeout 10
|
||||
spawn $env(SHELL)
|
||||
match_max 100000
|
||||
|
||||
send -- "firejail --name=test --x11 --net=br0 firefox www.gentoo.org\r"
|
||||
sleep 10
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firejail --list\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3.1\n";exit}
|
||||
"firefox" {puts "firefox detected\n";}
|
||||
"iceweasel" {puts "iceweasel detected\n";}
|
||||
}
|
||||
sleep 1
|
||||
send -- "firejail --name=blablabla\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 4\n";exit}
|
||||
"Child process initialized"
|
||||
}
|
||||
sleep 2
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firemon --seccomp\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5\n";exit}
|
||||
" firefox" {puts "firefox detected\n";}
|
||||
" iceweasel" {puts "iceweasel detected\n";}
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
|
||||
"Seccomp: 2"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firemon --caps\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6\n";exit}
|
||||
" firefox" {puts "firefox detected\n";}
|
||||
" iceweasel" {puts "iceweasel detected\n";}
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.1\n";exit}
|
||||
"CapBnd:"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.2\n";exit}
|
||||
"0000000000000000"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.3\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firejail --shutdown=test\r"
|
||||
sleep 3
|
||||
|
||||
puts "\nall done\n"
|
||||
|
||||
29
test/test-apps-x11.sh
Executable file
29
test/test-apps-x11.sh
Executable file
|
|
@ -0,0 +1,29 @@
|
|||
#!/bin/bash
|
||||
|
||||
which firefox
|
||||
if [ "$?" -eq 0 ];
|
||||
then
|
||||
echo "TESTING: firefox x11"
|
||||
./firefox-x11.exp
|
||||
else
|
||||
echo "TESTING: firefox not found"
|
||||
fi
|
||||
|
||||
which chromium
|
||||
if [ "$?" -eq 0 ];
|
||||
then
|
||||
echo "TESTING: chromium x11"
|
||||
./chromium-x11.exp
|
||||
else
|
||||
echo "TESTING: chromium not found"
|
||||
fi
|
||||
|
||||
which transmission-gtk
|
||||
if [ "$?" -eq 0 ];
|
||||
then
|
||||
echo "TESTING: transmission-gtk x11"
|
||||
./transmission-gtk.exp
|
||||
else
|
||||
echo "TESTING: transmission-gtk not found"
|
||||
fi
|
||||
|
||||
|
|
@ -166,6 +166,7 @@ else
|
|||
fi
|
||||
|
||||
./test-apps.sh
|
||||
./test-apps-x11.sh
|
||||
|
||||
echo "TESTING: PID (pid.exp)"
|
||||
./pid.exp
|
||||
|
|
|
|||
74
test/transmission-gtk-x11.exp
Executable file
74
test/transmission-gtk-x11.exp
Executable file
|
|
@ -0,0 +1,74 @@
|
|||
#!/usr/bin/expect -f
|
||||
|
||||
set timeout 10
|
||||
spawn $env(SHELL)
|
||||
match_max 100000
|
||||
|
||||
send -- "firejail --name=test --net=br0 --x11 transmission-gtk\r"
|
||||
sleep 10
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firejail --list\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 3.1\n";exit}
|
||||
"transmission-gtk"
|
||||
}
|
||||
sleep 1
|
||||
|
||||
send -- "firejail --name=blablabla\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 4\n";exit}
|
||||
"Child process initialized"
|
||||
}
|
||||
sleep 2
|
||||
|
||||
spawn $env(SHELL)
|
||||
send -- "firemon --seccomp\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.0\n";exit}
|
||||
"transmission-gtk"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1 (seccomp)\n";exit}
|
||||
"Seccomp: 2"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 5.1\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firemon --caps\r"
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6\n";exit}
|
||||
":firejail"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.0\n";exit}
|
||||
"transmission-gtk"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.1\n";exit}
|
||||
"CapBnd"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.2\n";exit}
|
||||
"0000000000000000"
|
||||
}
|
||||
expect {
|
||||
timeout {puts "TESTING ERROR 6.3\n";exit}
|
||||
"name=blablabla"
|
||||
}
|
||||
sleep 1
|
||||
send -- "firejail --shutdown=test\r"
|
||||
sleep 3
|
||||
|
||||
puts "\nall done\n"
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue