Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fine-grained DBus sandboxing #3265

Merged
merged 9 commits into from
Apr 7, 2020
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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