Skip to content

Commit

Permalink
Merge pull request #3265 from kris7t/dbus-proxy
Browse files Browse the repository at this point in the history
Fine-grained DBus sandboxing
  • Loading branch information
kris7t authored Apr 7, 2020
2 parents 3f27e84 + e91b9ff commit 07fac58
Show file tree
Hide file tree
Showing 12 changed files with 951 additions and 218 deletions.
439 changes: 417 additions & 22 deletions src/firejail/dbus.c

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,16 @@ extern int arg_memory_deny_write_execute; // block writable and executable memor
extern int arg_notv; // --notv
extern int arg_nodvd; // --nodvd
extern int arg_nou2f; // --nou2f
extern int arg_nodbus; // -nodbus
extern int arg_deterministic_exit_code; // always exit with first child's exit status

typedef enum {
DBUS_POLICY_ALLOW, // Allow unrestricted access to the bus
DBUS_POLICY_FILTER, // Filter with xdg-dbus-proxy
DBUS_POLICY_BLOCK // Block access
} DbusPolicy;
extern DbusPolicy arg_dbus_user; // --dbus-user
extern DbusPolicy arg_dbus_system; // --dbus-system

extern int login_shell;
extern int parent_to_child_fds[2];
extern int child_to_parent_fds[2];
Expand Down Expand Up @@ -823,10 +830,13 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
#define SBOX_STDIN_FROM_FILE (1 << 6) // open file and redirect it to stdin
#define SBOX_CAPS_HIDEPID (1 << 7) // hidepid caps filter for running firemon
#define SBOX_CAPS_NET_SERVICE (1 << 8) // caps filter for programs running network services
#define SBOX_KEEP_FDS (1 << 9) // keep file descriptors open
#define FIREJAIL_MAX_FD 20 // getdtablesize() is overkill for a firejail process

// run sbox
int sbox_run(unsigned filter, int num, ...);
int sbox_run_v(unsigned filter, char * const arg[]);
void sbox_exec_v(unsigned filter, char * const arg[]);

// run_files.c
void delete_run_files(pid_t pid);
Expand All @@ -836,7 +846,11 @@ void set_x11_run_file(pid_t pid, int display);
void set_profile_run_file(pid_t pid, const char *fname);

// dbus.c
void dbus_disable(void);
int dbus_check_name(const char *name);
void dbus_check_profile(void);
void dbus_proxy_start(void);
void dbus_proxy_stop(void);
void dbus_apply_policy(void);

// dhcp.c
extern pid_t dhclient4_pid;
Expand Down
1 change: 1 addition & 0 deletions src/firejail/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ void fs_blacklist(void) {
// whitelist commands handled by fs_whitelist()
if (strncmp(entry->data, "whitelist ", 10) == 0 ||
strncmp(entry->data, "nowhitelist ", 12) == 0 ||
strncmp(entry->data, "dbus-", 5) == 0 ||
*entry->data == '\0') {
entry = entry->next;
continue;
Expand Down
80 changes: 77 additions & 3 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,9 +144,10 @@ int arg_noprofile = 0; // use default.profile if none other found/specified
int arg_memory_deny_write_execute = 0; // block writable and executable memory
int arg_notv = 0; // --notv
int arg_nodvd = 0; // --nodvd
int arg_nodbus = 0; // -nodbus
int arg_nou2f = 0; // --nou2f
int arg_deterministic_exit_code = 0; // always exit with first child's exit status
DbusPolicy arg_dbus_user = DBUS_POLICY_ALLOW; // --dbus-user
DbusPolicy arg_dbus_system = DBUS_POLICY_ALLOW; // --dbus-system
int login_shell = 0;

//**********************************************************************************
Expand Down Expand Up @@ -180,6 +181,7 @@ static void myexit(int rv) {


// delete sandbox files in shared memory
dbus_proxy_stop();
EUID_ROOT();
delete_run_files(sandbox_pid);
appimage_clear();
Expand Down Expand Up @@ -2053,8 +2055,70 @@ int main(int argc, char **argv, char **envp) {
arg_nodvd = 1;
else if (strcmp(argv[i], "--nou2f") == 0)
arg_nou2f = 1;
else if (strcmp(argv[i], "--nodbus") == 0)
arg_nodbus = 1;
else if (strcmp(argv[i], "--nodbus") == 0) {
arg_dbus_user = DBUS_POLICY_BLOCK;
arg_dbus_system = DBUS_POLICY_BLOCK;
}
else if (strncmp("--dbus-user=", argv[i], 12) == 0) {
if (strcmp("filter", argv[i] + 12) == 0) {
if (arg_dbus_user == DBUS_POLICY_BLOCK) {
fprintf(stderr, "Error: Cannot relax --dbus-user policy, it is already set to block\n");
exit(1);
}
arg_dbus_user = DBUS_POLICY_FILTER;
} else if (strcmp("none", argv[i] + 12) == 0) {
arg_dbus_user = DBUS_POLICY_BLOCK;
} else {
fprintf(stderr, "Unknown dbus-user policy: %s\n", argv[i] + 12);
exit(1);
}
}
else if (strncmp(argv[i], "--dbus-user.talk=", 17) == 0) {
char *line;
if (asprintf(&line, "dbus-user.talk %s", argv[i] + 17) == -1)
errExit("asprintf");

profile_check_line(line, 0, NULL); // will exit if something wrong
profile_add(line);
}
else if (strncmp(argv[i], "--dbus-user.own=", 16) == 0) {
char *line;
if (asprintf(&line, "dbus-user.own %s", argv[i] + 16) == -1)
errExit("asprintf");

profile_check_line(line, 0, NULL); // will exit if something wrong
profile_add(line);
}
else if (strncmp("--dbus-system=", argv[i], 14) == 0) {
if (strcmp("filter", argv[i] + 14) == 0) {
if (arg_dbus_system == DBUS_POLICY_BLOCK) {
fprintf(stderr, "Error: Cannot relax --dbus-system policy, it is already set to block\n");
exit(1);
}
arg_dbus_system = DBUS_POLICY_FILTER;
} else if (strcmp("none", argv[i] + 14) == 0) {
arg_dbus_system = DBUS_POLICY_BLOCK;
} else {
fprintf(stderr, "Unknown dbus-system policy: %s\n", argv[i] + 14);
exit(1);
}
}
else if (strncmp(argv[i], "--dbus-system.talk=", 19) == 0) {
char *line;
if (asprintf(&line, "dbus-system.talk %s", argv[i] + 19) == -1)
errExit("asprintf");

profile_check_line(line, 0, NULL); // will exit if something wrong
profile_add(line);
}
else if (strncmp(argv[i], "--dbus-system.own=", 18) == 0) {
char *line;
if (asprintf(&line, "dbus-system.own %s", argv[i] + 18) == -1)
errExit("asprintf");

profile_check_line(line, 0, NULL); // will exit if something wrong
profile_add(line);
}

//*************************************
// network
Expand Down Expand Up @@ -2740,6 +2804,16 @@ int main(int argc, char **argv, char **envp) {
}
EUID_USER();

if (checkcfg(CFG_DBUS)) {
dbus_check_profile();
if (arg_dbus_user == DBUS_POLICY_FILTER ||
arg_dbus_system == DBUS_POLICY_FILTER) {
EUID_ROOT();
dbus_proxy_start();
EUID_USER();
}
}

// clone environment
int flags = CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD;

Expand Down
14 changes: 14 additions & 0 deletions src/firejail/preproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ void preproc_build_firejail_dir(void) {
create_empty_dir_as_root(RUN_FIREJAIL_X11_DIR, 0755);
}

if (stat(RUN_FIREJAIL_DBUS_DIR, &s)) {
create_empty_dir_as_root(RUN_FIREJAIL_DBUS_DIR, 0755);
if (arg_debug)
printf("Remounting the " RUN_FIREJAIL_DBUS_DIR
" directory as noexec\n");
if (mount(RUN_FIREJAIL_DBUS_DIR, RUN_FIREJAIL_DBUS_DIR, NULL,
MS_BIND, NULL) == -1)
errExit("mounting " RUN_FIREJAIL_DBUS_DIR);
if (mount(NULL, RUN_FIREJAIL_DBUS_DIR, NULL,
MS_REMOUNT | MS_BIND | MS_NOSUID | MS_NOEXEC | MS_NODEV,
"mode=755,gid=0") == -1)
errExit("remounting " RUN_FIREJAIL_DBUS_DIR);
}

if (stat(RUN_FIREJAIL_APPIMAGE_DIR, &s)) {
create_empty_dir_as_root(RUN_FIREJAIL_APPIMAGE_DIR, 0755);
}
Expand Down
67 changes: 64 additions & 3 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static int check_netoptions(void) {
}

static int check_nodbus(void) {
return arg_nodbus != 0;
return arg_dbus_user != DBUS_POLICY_ALLOW || arg_dbus_system != DBUS_POLICY_ALLOW;
}

static int check_nosound(void) {
Expand Down Expand Up @@ -432,11 +432,72 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
return 0;
}
else if (strcmp(ptr, "nodbus") == 0) {
arg_nodbus = 1;
arg_dbus_user = DBUS_POLICY_BLOCK;
arg_dbus_system = DBUS_POLICY_BLOCK;
return 0;
}
else if (strncmp("dbus-user ", ptr, 10) == 0) {
ptr += 10;
if (strcmp("filter", ptr) == 0) {
if (arg_dbus_user == DBUS_POLICY_BLOCK) {
fprintf(stderr, "Error: Cannot relax dbus-user policy, it is already set to block\n");
exit(1);
}
arg_dbus_user = DBUS_POLICY_FILTER;
} else if (strcmp("none", ptr) == 0) {
arg_dbus_user = DBUS_POLICY_BLOCK;
} else {
fprintf(stderr, "Unknown dbus-user policy: %s\n", ptr);
exit(1);
}
return 0;
}
else if (strncmp(ptr, "dbus-user.talk ", 15) == 0) {
if (!dbus_check_name(ptr + 15)) {
printf("Invalid dbus-user.talk name: %s\n", ptr + 15);
exit(1);
}
return 1;
}
else if (strncmp(ptr, "dbus-user.own ", 14) == 0) {
if (!dbus_check_name(ptr + 14)) {
fprintf(stderr, "Invalid dbus-user.own name: %s\n", ptr + 14);
exit(1);
}
return 1;
}
else if (strncmp("dbus-system ", ptr, 12) == 0) {
ptr += 12;
if (strcmp("filter", ptr) == 0) {
if (arg_dbus_system == DBUS_POLICY_BLOCK) {
fprintf(stderr, "Error: Cannot relax dbus-system policy, it is already set to block\n");
exit(1);
}
arg_dbus_system = DBUS_POLICY_FILTER;
} else if (strcmp("none", ptr) == 0) {
arg_dbus_system = DBUS_POLICY_BLOCK;
} else {
fprintf(stderr, "Unknown dbus-system policy: %s\n", ptr);
exit(1);
}
return 0;
}
else if (strncmp(ptr, "dbus-system.talk ", 17) == 0) {
if (!dbus_check_name(ptr + 17)) {
fprintf(stderr, "Invalid dbus-system.talk name: %s\n", ptr + 17);
exit(1);
}
return 1;
}
else if (strncmp(ptr, "dbus-system.own ", 16) == 0) {
if (!dbus_check_name(ptr + 16)) {
fprintf(stderr, "Invalid dbus-system.own name: %s\n", ptr + 16);
exit(1);
}
return 1;
}
else if (strcmp(ptr, "nou2f") == 0) {
arg_nou2f = 1;
arg_nou2f = 1;
return 0;
}
else if (strcmp(ptr, "netfilter") == 0) {
Expand Down
3 changes: 1 addition & 2 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -932,8 +932,7 @@ int sandbox(void* sandbox_arg) {
//****************************
// Session D-BUS
//****************************
if (arg_nodbus)
dbus_disable();
dbus_apply_policy();


//****************************
Expand Down
Loading

0 comments on commit 07fac58

Please sign in to comment.