aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2020-06-01 18:20:28 +0200
committerLibravatar GitHub <noreply@github.com>2020-06-01 18:20:28 +0200
commit18f99d17a46f84f403b49dd36bf5eeb8167a8746 (patch)
tree52c26d787fef55c05a76de3a50e3d0fda0cc2f3a /src
parentAvoid dbus-*=filter breakage (#3432) (diff)
parentTurn attempted DBus policy downgrade into warning (fixes #3408) (diff)
downloadfirejail-18f99d17a46f84f403b49dd36bf5eeb8167a8746.tar.gz
firejail-18f99d17a46f84f403b49dd36bf5eeb8167a8746.tar.zst
firejail-18f99d17a46f84f403b49dd36bf5eeb8167a8746.zip
Merge pull request #3406 from kris7t/dbus-proxy
DBus filtering enhancements
Diffstat (limited to 'src')
-rw-r--r--src/faudit/dbus.c57
-rw-r--r--src/firejail/dbus.c93
-rw-r--r--src/firejail/firejail.h4
-rw-r--r--src/firejail/main.c92
-rw-r--r--src/firejail/profile.c58
-rw-r--r--src/firejail/usage.c9
-rw-r--r--src/man/firejail-profile.txt18
-rw-r--r--src/man/firejail.txt136
8 files changed, 444 insertions, 23 deletions
diff --git a/src/faudit/dbus.c b/src/faudit/dbus.c
index 8c26c5271..beaa5ac46 100644
--- a/src/faudit/dbus.c
+++ b/src/faudit/dbus.c
@@ -18,6 +18,8 @@
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/ 19*/
20#include "faudit.h" 20#include "faudit.h"
21#include "../include/rundefs.h"
22#include <stdarg.h>
21#include <sys/socket.h> 23#include <sys/socket.h>
22#include <sys/un.h> 24#include <sys/un.h>
23 25
@@ -46,9 +48,10 @@ int check_unix(const char *sockfile) {
46 return rv; 48 return rv;
47} 49}
48 50
49void dbus_test(void) { 51static char *test_dbus_env(char *env_var_name) {
50 // check the session bus 52 // check the session bus
51 char *str = getenv("DBUS_SESSION_BUS_ADDRESS"); 53 char *str = getenv(env_var_name);
54 char *found = NULL;
52 if (str) { 55 if (str) {
53 int rv = 0; 56 int rv = 0;
54 char *bus = strdup(str); 57 char *bus = strdup(str);
@@ -74,19 +77,55 @@ void dbus_test(void) {
74 if (ptr) 77 if (ptr)
75 *ptr = '\0'; 78 *ptr = '\0';
76 rv = check_unix(sockfile); 79 rv = check_unix(sockfile);
77 if (rv == 0) 80 if (rv == 0) {
78 printf("MAYBE: D-Bus socket %s is available\n", sockfile); 81 if (strcmp(RUN_DBUS_USER_SOCKET, sockfile) == 0 ||
82 strcmp(RUN_DBUS_SYSTEM_SOCKET, sockfile) == 0) {
83 printf("GOOD: D-Bus filtering is active on %s\n", sockfile);
84 } else {
85 printf("MAYBE: D-Bus socket %s is available\n", sockfile);
86 }
87 }
79 else if (rv == -1) 88 else if (rv == -1)
80 printf("GOOD: cannot connect to D-Bus socket %s\n", sockfile); 89 printf("GOOD: cannot connect to D-Bus socket %s\n", sockfile);
90 found = strdup(sockfile);
91 if (!found)
92 errExit("strdup");
81 } 93 }
82 else if ((sockfile = strstr(bus, "tcp:host=")) != NULL) 94 else if ((sockfile = strstr(bus, "tcp:host=")) != NULL)
83 printf("UGLY: session bus configured for TCP communication.\n"); 95 printf("UGLY: %s bus configured for TCP communication.\n", env_var_name);
84 else 96 else
85 printf("GOOD: cannot find a D-Bus socket\n"); 97 printf("GOOD: cannot find a %s D-Bus socket\n", env_var_name);
86
87
88 free(bus); 98 free(bus);
89 } 99 }
90 else 100 else
91 printf("GOOD: DBUS_SESSION_BUS_ADDRESS environment variable not configured."); 101 printf("MAYBE: %s environment variable not configured.\n", env_var_name);
102 return found;
103}
104
105static void test_default_socket(const char *found, const char *format, ...) {
106 va_list ap;
107 va_start(ap, format);
108 char *sockfile;
109 if (vasprintf(&sockfile, format, ap) == -1)
110 errExit("vasprintf");
111 va_end(ap);
112 if (found != NULL && strcmp(found, sockfile) == 0)
113 goto end;
114 int rv = check_unix(sockfile);
115 if (rv == 0)
116 printf("MAYBE: D-Bus socket %s is available\n", sockfile);
117end:
118 free(sockfile);
119}
120
121void dbus_test(void) {
122 char *found_user = test_dbus_env("DBUS_SESSION_BUS_ADDRESS");
123 test_default_socket(found_user, "/run/user/%d/bus", (int) getuid());
124 test_default_socket(found_user, "/run/user/%d/dbus/user_bus_socket", (int) getuid());
125 if (found_user != NULL)
126 free(found_user);
127 char *found_system = test_dbus_env("DBUS_SYSTEM_BUS_ADDRESS");
128 test_default_socket(found_system, "/run/dbus/system_bus_socket");
129 if (found_system != NULL)
130 free(found_system);
92} 131}
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c
index 0f4f18c57..18576612d 100644
--- a/src/firejail/dbus.c
+++ b/src/firejail/dbus.c
@@ -48,7 +48,7 @@ static int dbus_proxy_status_fd = -1;
48static char *dbus_user_proxy_socket = NULL; 48static char *dbus_user_proxy_socket = NULL;
49static char *dbus_system_proxy_socket = NULL; 49static char *dbus_system_proxy_socket = NULL;
50 50
51int dbus_check_name(const char *name) { 51static int check_bus_or_interface_name(const char *name, int hyphens_allowed) {
52 unsigned long length = strlen(name); 52 unsigned long length = strlen(name);
53 if (length == 0 || length > DBUS_MAX_NAME_LENGTH) 53 if (length == 0 || length > DBUS_MAX_NAME_LENGTH)
54 return 0; 54 return 0;
@@ -62,14 +62,48 @@ int dbus_check_name(const char *name) {
62 if (*p == '.') { 62 if (*p == '.') {
63 ++segments; 63 ++segments;
64 in_segment = 0; 64 in_segment = 0;
65 } else if (!alpha && !digit && *p != '_' && *p != '-') { 65 } else if (!alpha && !digit && *p != '_' && (!hyphens_allowed || *p != '-')) {
66 return 0;
67 }
68 }
69 else {
70 if (*p == '*') {
71 return *(p + 1) == '\0';
72 } else if (!alpha && *p != '_' && (!hyphens_allowed || *p != '-')) {
73 return 0;
74 }
75 in_segment = 1;
76 }
77 ++p;
78 }
79 return in_segment && segments >= 2;
80}
81
82static int check_object_path(const char *path) {
83 unsigned long length = strlen(path);
84 if (length == 0 || path[0] != '/')
85 return 0;
86 // The root path "/" is the only path allowed to have a trailing slash.
87 if (length == 1)
88 return 1;
89 const char *p = path + 1;
90 int segments = 1;
91 int in_segment = 0;
92 while (*p) {
93 int alpha = (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z');
94 int digit = *p >= '0' && *p <= '9';
95 if (in_segment) {
96 if (*p == '/') {
97 ++segments;
98 in_segment = 0;
99 } else if (!alpha && !digit && *p != '_') {
66 return 0; 100 return 0;
67 } 101 }
68 } 102 }
69 else { 103 else {
70 if (*p == '*') { 104 if (*p == '*') {
71 return *(p + 1) == '\0'; 105 return *(p + 1) == '\0';
72 } else if (!alpha && *p != '_' && *p != '-') { 106 } else if (!alpha && *p != '_') {
73 return 0; 107 return 0;
74 } 108 }
75 in_segment = 1; 109 in_segment = 1;
@@ -79,6 +113,38 @@ int dbus_check_name(const char *name) {
79 return in_segment && segments >= 2; 113 return in_segment && segments >= 2;
80} 114}
81 115
116int dbus_check_name(const char *name) {
117 return check_bus_or_interface_name(name, 1);
118}
119
120int dbus_check_call_rule(const char *rule) {
121 char buf[DBUS_MAX_NAME_LENGTH + 1];
122 char *name_end = strchr(rule, '=');
123 if (name_end == NULL)
124 return 0;
125 size_t name_length = (size_t) (name_end - rule);
126 if (name_length > DBUS_MAX_NAME_LENGTH)
127 return 0;
128 strncpy(buf, rule, (size_t) name_length);
129 buf[name_length] = '\0';
130 if (!dbus_check_name(buf))
131 return 0;
132 ++name_end;
133 char *interface_end = strchr(name_end, '@');
134 if (interface_end == NULL)
135 return check_bus_or_interface_name(name_end, 0);
136 size_t interface_length = (size_t) (interface_end - name_end);
137 if (interface_length > DBUS_MAX_NAME_LENGTH)
138 return 0;
139 if (interface_length > 0) {
140 strncpy(buf, name_end, interface_length);
141 buf[interface_length] = '\0';
142 if (!check_bus_or_interface_name(buf, 0))
143 return 0;
144 }
145 return check_object_path(interface_end + 1);
146}
147
82static void dbus_check_bus_profile(char const *prefix, DbusPolicy *policy) { 148static void dbus_check_bus_profile(char const *prefix, DbusPolicy *policy) {
83 if (*policy == DBUS_POLICY_FILTER) { 149 if (*policy == DBUS_POLICY_FILTER) {
84 struct stat s; 150 struct stat s;
@@ -219,6 +285,8 @@ static char *find_user_socket(void) {
219void dbus_proxy_start(void) { 285void dbus_proxy_start(void) {
220 dbus_create_user_dir(); 286 dbus_create_user_dir();
221 287
288 EUID_USER();
289
222 int status_pipe[2]; 290 int status_pipe[2];
223 if (pipe(status_pipe) == -1) 291 if (pipe(status_pipe) == -1)
224 errExit("pipe"); 292 errExit("pipe");
@@ -233,10 +301,21 @@ void dbus_proxy_start(void) {
233 errExit("fork"); 301 errExit("fork");
234 if (dbus_proxy_pid == 0) { 302 if (dbus_proxy_pid == 0) {
235 int i; 303 int i;
236 for (i = 3; i < FIREJAIL_MAX_FD; i++) { 304 for (i = STDERR_FILENO + 1; i < FIREJAIL_MAX_FD; i++) {
237 if (i != status_pipe[1] && i != args_pipe[0]) 305 if (i != status_pipe[1] && i != args_pipe[0])
238 close(i); // close open files 306 close(i); // close open files
239 } 307 }
308 if (arg_dbus_log_file != NULL) {
309 int output_fd = creat(arg_dbus_log_file, 0666);
310 if (output_fd < 0)
311 errExit("creat");
312 if (output_fd != STDOUT_FILENO) {
313 if (dup2(output_fd, STDOUT_FILENO) != STDOUT_FILENO)
314 errExit("dup2");
315 close(output_fd);
316 }
317 }
318 close(STDIN_FILENO);
240 char *args[4] = {XDG_DBUS_PROXY_PATH, NULL, NULL, NULL}; 319 char *args[4] = {XDG_DBUS_PROXY_PATH, NULL, NULL, NULL};
241 if (asprintf(&args[1], "--fd=%d", status_pipe[1]) == -1 320 if (asprintf(&args[1], "--fd=%d", status_pipe[1]) == -1
242 || asprintf(&args[2], "--args=%d", args_pipe[0]) == -1) 321 || asprintf(&args[2], "--args=%d", args_pipe[0]) == -1)
@@ -262,6 +341,9 @@ void dbus_proxy_start(void) {
262 (int) getuid(), (int) getpid()) == -1) 341 (int) getuid(), (int) getpid()) == -1)
263 errExit("asprintf"); 342 errExit("asprintf");
264 write_arg(args_pipe[1], "%s", dbus_user_proxy_socket); 343 write_arg(args_pipe[1], "%s", dbus_user_proxy_socket);
344 if (arg_dbus_log_user) {
345 write_arg(args_pipe[1], "--log");
346 }
265 write_arg(args_pipe[1], "--filter"); 347 write_arg(args_pipe[1], "--filter");
266 write_profile(args_pipe[1], "dbus-user."); 348 write_profile(args_pipe[1], "dbus-user.");
267 } 349 }
@@ -278,6 +360,9 @@ void dbus_proxy_start(void) {
278 (int) getuid(), (int) getpid()) == -1) 360 (int) getuid(), (int) getpid()) == -1)
279 errExit("asprintf"); 361 errExit("asprintf");
280 write_arg(args_pipe[1], "%s", dbus_system_proxy_socket); 362 write_arg(args_pipe[1], "%s", dbus_system_proxy_socket);
363 if (arg_dbus_log_system) {
364 write_arg(args_pipe[1], "--log");
365 }
281 write_arg(args_pipe[1], "--filter"); 366 write_arg(args_pipe[1], "--filter");
282 write_profile(args_pipe[1], "dbus-system."); 367 write_profile(args_pipe[1], "dbus-system.");
283 } 368 }
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 9b288b1b9..1ef4887ea 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -349,6 +349,9 @@ typedef enum {
349} DbusPolicy; 349} DbusPolicy;
350extern DbusPolicy arg_dbus_user; // --dbus-user 350extern DbusPolicy arg_dbus_user; // --dbus-user
351extern DbusPolicy arg_dbus_system; // --dbus-system 351extern DbusPolicy arg_dbus_system; // --dbus-system
352extern int arg_dbus_log_user;
353extern int arg_dbus_log_system;
354extern const char *arg_dbus_log_file;
352 355
353extern int login_shell; 356extern int login_shell;
354extern int parent_to_child_fds[2]; 357extern int parent_to_child_fds[2];
@@ -847,6 +850,7 @@ void set_profile_run_file(pid_t pid, const char *fname);
847 850
848// dbus.c 851// dbus.c
849int dbus_check_name(const char *name); 852int dbus_check_name(const char *name);
853int dbus_check_call_rule(const char *name);
850void dbus_check_profile(void); 854void dbus_check_profile(void);
851void dbus_proxy_start(void); 855void dbus_proxy_start(void);
852void dbus_proxy_stop(void); 856void dbus_proxy_stop(void);
diff --git a/src/firejail/main.c b/src/firejail/main.c
index dc213b988..958374c43 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -148,6 +148,9 @@ int arg_nou2f = 0; // --nou2f
148int arg_deterministic_exit_code = 0; // always exit with first child's exit status 148int arg_deterministic_exit_code = 0; // always exit with first child's exit status
149DbusPolicy arg_dbus_user = DBUS_POLICY_ALLOW; // --dbus-user 149DbusPolicy arg_dbus_user = DBUS_POLICY_ALLOW; // --dbus-user
150DbusPolicy arg_dbus_system = DBUS_POLICY_ALLOW; // --dbus-system 150DbusPolicy arg_dbus_system = DBUS_POLICY_ALLOW; // --dbus-system
151const char *arg_dbus_log_file = NULL;
152int arg_dbus_log_user = 0;
153int arg_dbus_log_system = 0;
151int login_shell = 0; 154int login_shell = 0;
152 155
153//********************************************************************************** 156//**********************************************************************************
@@ -2062,17 +2065,29 @@ int main(int argc, char **argv, char **envp) {
2062 else if (strncmp("--dbus-user=", argv[i], 12) == 0) { 2065 else if (strncmp("--dbus-user=", argv[i], 12) == 0) {
2063 if (strcmp("filter", argv[i] + 12) == 0) { 2066 if (strcmp("filter", argv[i] + 12) == 0) {
2064 if (arg_dbus_user == DBUS_POLICY_BLOCK) { 2067 if (arg_dbus_user == DBUS_POLICY_BLOCK) {
2065 fprintf(stderr, "Error: Cannot relax --dbus-user policy, it is already set to block\n"); 2068 fprintf(stderr, "Warning: Cannot relax --dbus-user policy, it is already set to block\n");
2066 exit(1); 2069 } else {
2070 arg_dbus_user = DBUS_POLICY_FILTER;
2067 } 2071 }
2068 arg_dbus_user = DBUS_POLICY_FILTER;
2069 } else if (strcmp("none", argv[i] + 12) == 0) { 2072 } else if (strcmp("none", argv[i] + 12) == 0) {
2073 if (arg_dbus_log_user) {
2074 fprintf(stderr, "Error: --dbus-user.log requires --dbus-user=filter\n");
2075 exit(1);
2076 }
2070 arg_dbus_user = DBUS_POLICY_BLOCK; 2077 arg_dbus_user = DBUS_POLICY_BLOCK;
2071 } else { 2078 } else {
2072 fprintf(stderr, "Unknown dbus-user policy: %s\n", argv[i] + 12); 2079 fprintf(stderr, "Unknown dbus-user policy: %s\n", argv[i] + 12);
2073 exit(1); 2080 exit(1);
2074 } 2081 }
2075 } 2082 }
2083 else if (strncmp(argv[i], "--dbus-user.see=", 16) == 0) {
2084 char *line;
2085 if (asprintf(&line, "dbus-user.see %s", argv[i] + 16) == -1)
2086 errExit("asprintf");
2087
2088 profile_check_line(line, 0, NULL); // will exit if something wrong
2089 profile_add(line);
2090 }
2076 else if (strncmp(argv[i], "--dbus-user.talk=", 17) == 0) { 2091 else if (strncmp(argv[i], "--dbus-user.talk=", 17) == 0) {
2077 char *line; 2092 char *line;
2078 if (asprintf(&line, "dbus-user.talk %s", argv[i] + 17) == -1) 2093 if (asprintf(&line, "dbus-user.talk %s", argv[i] + 17) == -1)
@@ -2089,20 +2104,48 @@ int main(int argc, char **argv, char **envp) {
2089 profile_check_line(line, 0, NULL); // will exit if something wrong 2104 profile_check_line(line, 0, NULL); // will exit if something wrong
2090 profile_add(line); 2105 profile_add(line);
2091 } 2106 }
2107 else if (strncmp(argv[i], "--dbus-user.call=", 17) == 0) {
2108 char *line;
2109 if (asprintf(&line, "dbus-user.call %s", argv[i] + 17) == -1)
2110 errExit("asprintf");
2111
2112 profile_check_line(line, 0, NULL); // will exit if something wrong
2113 profile_add(line);
2114 }
2115 else if (strncmp(argv[i], "--dbus-user.broadcast=", 22) == 0) {
2116 char *line;
2117 if (asprintf(&line, "dbus-user.broadcast %s", argv[i] + 22) == -1)
2118 errExit("asprintf");
2119
2120 profile_check_line(line, 0, NULL); // will exit if something wrong
2121 profile_add(line);
2122 }
2092 else if (strncmp("--dbus-system=", argv[i], 14) == 0) { 2123 else if (strncmp("--dbus-system=", argv[i], 14) == 0) {
2093 if (strcmp("filter", argv[i] + 14) == 0) { 2124 if (strcmp("filter", argv[i] + 14) == 0) {
2094 if (arg_dbus_system == DBUS_POLICY_BLOCK) { 2125 if (arg_dbus_system == DBUS_POLICY_BLOCK) {
2095 fprintf(stderr, "Error: Cannot relax --dbus-system policy, it is already set to block\n"); 2126 fprintf(stderr, "Warning: Cannot relax --dbus-system policy, it is already set to block\n");
2096 exit(1); 2127 } else {
2128 arg_dbus_system = DBUS_POLICY_FILTER;
2097 } 2129 }
2098 arg_dbus_system = DBUS_POLICY_FILTER;
2099 } else if (strcmp("none", argv[i] + 14) == 0) { 2130 } else if (strcmp("none", argv[i] + 14) == 0) {
2131 if (arg_dbus_log_system) {
2132 fprintf(stderr, "Error: --dbus-system.log requires --dbus-system=filter\n");
2133 exit(1);
2134 }
2100 arg_dbus_system = DBUS_POLICY_BLOCK; 2135 arg_dbus_system = DBUS_POLICY_BLOCK;
2101 } else { 2136 } else {
2102 fprintf(stderr, "Unknown dbus-system policy: %s\n", argv[i] + 14); 2137 fprintf(stderr, "Unknown dbus-system policy: %s\n", argv[i] + 14);
2103 exit(1); 2138 exit(1);
2104 } 2139 }
2105 } 2140 }
2141 else if (strncmp(argv[i], "--dbus-system.see=", 18) == 0) {
2142 char *line;
2143 if (asprintf(&line, "dbus-system.see %s", argv[i] + 18) == -1)
2144 errExit("asprintf");
2145
2146 profile_check_line(line, 0, NULL); // will exit if something wrong
2147 profile_add(line);
2148 }
2106 else if (strncmp(argv[i], "--dbus-system.talk=", 19) == 0) { 2149 else if (strncmp(argv[i], "--dbus-system.talk=", 19) == 0) {
2107 char *line; 2150 char *line;
2108 if (asprintf(&line, "dbus-system.talk %s", argv[i] + 19) == -1) 2151 if (asprintf(&line, "dbus-system.talk %s", argv[i] + 19) == -1)
@@ -2119,6 +2162,43 @@ int main(int argc, char **argv, char **envp) {
2119 profile_check_line(line, 0, NULL); // will exit if something wrong 2162 profile_check_line(line, 0, NULL); // will exit if something wrong
2120 profile_add(line); 2163 profile_add(line);
2121 } 2164 }
2165 else if (strncmp(argv[i], "--dbus-system.call=", 19) == 0) {
2166 char *line;
2167 if (asprintf(&line, "dbus-system.call %s", argv[i] + 19) == -1)
2168 errExit("asprintf");
2169
2170 profile_check_line(line, 0, NULL); // will exit if something wrong
2171 profile_add(line);
2172 }
2173 else if (strncmp(argv[i], "--dbus-system.broadcast=", 24) == 0) {
2174 char *line;
2175 if (asprintf(&line, "dbus-system.broadcast %s", argv[i] + 24) == -1)
2176 errExit("asprintf");
2177
2178 profile_check_line(line, 0, NULL); // will exit if something wrong
2179 profile_add(line);
2180 }
2181 else if (strncmp(argv[i], "--dbus-log=", 11) == 0) {
2182 if (arg_dbus_log_file != NULL) {
2183 fprintf(stderr, "Error: --dbus-log option already specified\n");
2184 exit(1);
2185 }
2186 arg_dbus_log_file = argv[i] + 11;
2187 }
2188 else if (strcmp(argv[i], "--dbus-user.log") == 0) {
2189 if (arg_dbus_user != DBUS_POLICY_FILTER) {
2190 fprintf(stderr, "Error: --dbus-user.log requires --dbus-user=filter\n");
2191 exit(1);
2192 }
2193 arg_dbus_log_user = 1;
2194 }
2195 else if (strcmp(argv[i], "--dbus-system.log") == 0) {
2196 if (arg_dbus_system != DBUS_POLICY_FILTER) {
2197 fprintf(stderr, "Error: --dbus-system.log requires --dbus-system=filter\n");
2198 exit(1);
2199 }
2200 arg_dbus_log_system = 1;
2201 }
2122 2202
2123 //************************************* 2203 //*************************************
2124 // network 2204 // network
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 0be119903..a87222824 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -441,10 +441,14 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
441 if (strcmp("filter", ptr) == 0) { 441 if (strcmp("filter", ptr) == 0) {
442 if (arg_dbus_user == DBUS_POLICY_BLOCK) { 442 if (arg_dbus_user == DBUS_POLICY_BLOCK) {
443 fprintf(stderr, "Error: Cannot relax dbus-user policy, it is already set to block\n"); 443 fprintf(stderr, "Error: Cannot relax dbus-user policy, it is already set to block\n");
444 exit(1); 444 } else {
445 arg_dbus_user = DBUS_POLICY_FILTER;
445 } 446 }
446 arg_dbus_user = DBUS_POLICY_FILTER;
447 } else if (strcmp("none", ptr) == 0) { 447 } else if (strcmp("none", ptr) == 0) {
448 if (arg_dbus_log_user) {
449 fprintf(stderr, "Error: --dbus-user.log requires --dbus-user=filter\n");
450 exit(1);
451 }
448 arg_dbus_user = DBUS_POLICY_BLOCK; 452 arg_dbus_user = DBUS_POLICY_BLOCK;
449 } else { 453 } else {
450 fprintf(stderr, "Unknown dbus-user policy: %s\n", ptr); 454 fprintf(stderr, "Unknown dbus-user policy: %s\n", ptr);
@@ -452,6 +456,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
452 } 456 }
453 return 0; 457 return 0;
454 } 458 }
459 else if (strncmp(ptr, "dbus-user.see ", 14) == 0) {
460 if (!dbus_check_name(ptr + 14)) {
461 printf("Invalid dbus-user.see name: %s\n", ptr + 15);
462 exit(1);
463 }
464 return 1;
465 }
455 else if (strncmp(ptr, "dbus-user.talk ", 15) == 0) { 466 else if (strncmp(ptr, "dbus-user.talk ", 15) == 0) {
456 if (!dbus_check_name(ptr + 15)) { 467 if (!dbus_check_name(ptr + 15)) {
457 printf("Invalid dbus-user.talk name: %s\n", ptr + 15); 468 printf("Invalid dbus-user.talk name: %s\n", ptr + 15);
@@ -466,15 +477,33 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
466 } 477 }
467 return 1; 478 return 1;
468 } 479 }
480 else if (strncmp(ptr, "dbus-user.call ", 15) == 0) {
481 if (!dbus_check_call_rule(ptr + 15)) {
482 fprintf(stderr, "Invalid dbus-user.call rule: %s\n", ptr + 15);
483 exit(1);
484 }
485 return 1;
486 }
487 else if (strncmp(ptr, "dbus-user.broadcast ", 20) == 0) {
488 if (!dbus_check_call_rule(ptr + 20)) {
489 fprintf(stderr, "Invalid dbus-user.broadcast rule: %s\n", ptr + 20);
490 exit(1);
491 }
492 return 1;
493 }
469 else if (strncmp("dbus-system ", ptr, 12) == 0) { 494 else if (strncmp("dbus-system ", ptr, 12) == 0) {
470 ptr += 12; 495 ptr += 12;
471 if (strcmp("filter", ptr) == 0) { 496 if (strcmp("filter", ptr) == 0) {
472 if (arg_dbus_system == DBUS_POLICY_BLOCK) { 497 if (arg_dbus_system == DBUS_POLICY_BLOCK) {
473 fprintf(stderr, "Error: Cannot relax dbus-system policy, it is already set to block\n"); 498 fprintf(stderr, "Error: Cannot relax dbus-system policy, it is already set to block\n");
474 exit(1); 499 } else {
500 arg_dbus_system = DBUS_POLICY_FILTER;
475 } 501 }
476 arg_dbus_system = DBUS_POLICY_FILTER;
477 } else if (strcmp("none", ptr) == 0) { 502 } else if (strcmp("none", ptr) == 0) {
503 if (arg_dbus_log_system) {
504 fprintf(stderr, "Error: --dbus-system.log requires --dbus-system=filter\n");
505 exit(1);
506 }
478 arg_dbus_system = DBUS_POLICY_BLOCK; 507 arg_dbus_system = DBUS_POLICY_BLOCK;
479 } else { 508 } else {
480 fprintf(stderr, "Unknown dbus-system policy: %s\n", ptr); 509 fprintf(stderr, "Unknown dbus-system policy: %s\n", ptr);
@@ -482,6 +511,13 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
482 } 511 }
483 return 0; 512 return 0;
484 } 513 }
514 else if (strncmp(ptr, "dbus-system.see ", 16) == 0) {
515 if (!dbus_check_name(ptr + 16)) {
516 fprintf(stderr, "Invalid dbus-system.see name: %s\n", ptr + 17);
517 exit(1);
518 }
519 return 1;
520 }
485 else if (strncmp(ptr, "dbus-system.talk ", 17) == 0) { 521 else if (strncmp(ptr, "dbus-system.talk ", 17) == 0) {
486 if (!dbus_check_name(ptr + 17)) { 522 if (!dbus_check_name(ptr + 17)) {
487 fprintf(stderr, "Invalid dbus-system.talk name: %s\n", ptr + 17); 523 fprintf(stderr, "Invalid dbus-system.talk name: %s\n", ptr + 17);
@@ -496,6 +532,20 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
496 } 532 }
497 return 1; 533 return 1;
498 } 534 }
535 else if (strncmp(ptr, "dbus-system.call ", 17) == 0) {
536 if (!dbus_check_call_rule(ptr + 17)) {
537 fprintf(stderr, "Invalid dbus-system.call rule: %s\n", ptr + 17);
538 exit(1);
539 }
540 return 1;
541 }
542 else if (strncmp(ptr, "dbus-system.broadcast ", 22) == 0) {
543 if (!dbus_check_call_rule(ptr + 22)) {
544 fprintf(stderr, "Invalid dbus-system.broadcast rule: %s\n", ptr + 22);
545 exit(1);
546 }
547 return 1;
548 }
499 else if (strcmp(ptr, "nou2f") == 0) { 549 else if (strcmp(ptr, "nou2f") == 0) {
500 arg_nou2f = 1; 550 arg_nou2f = 1;
501 return 0; 551 return 0;
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 08546fa51..4ab464289 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -53,11 +53,20 @@ static char *usage_str =
53#endif 53#endif
54 " --cpu=cpu-number,cpu-number - set cpu affinity.\n" 54 " --cpu=cpu-number,cpu-number - set cpu affinity.\n"
55 " --cpu.print=name|pid - print the cpus in use.\n" 55 " --cpu.print=name|pid - print the cpus in use.\n"
56 " --dbus-log=file - set DBus log file location.\n"
56 " --dbus-system=filter|none - set system DBus access policy.\n" 57 " --dbus-system=filter|none - set system DBus access policy.\n"
58 " --dbus-system.broadcast=rule - allow signals on the system DBus according to rule.\n"
59 " --dbus-system.call=rule - allow calls on the system DBus according to rule.\n"
60 " --dbus-system.log - turn on logging for the system DBus."
57 " --dbus-system.own=name - allow ownership of name on the system DBus.\n" 61 " --dbus-system.own=name - allow ownership of name on the system DBus.\n"
62 " --dbus-system.see=name - allow seeing name on the system DBus.\n"
58 " --dbus-system.talk=name - allow talking to name on the system DBus.\n" 63 " --dbus-system.talk=name - allow talking to name on the system DBus.\n"
59 " --dbus-user=filter|none - set session DBus access policy.\n" 64 " --dbus-user=filter|none - set session DBus access policy.\n"
65 " --dbus-user.broadcast=rule - allow signals on the session DBus according to rule.\n"
66 " --dbus-user.call=rule - allow calls on the session DBus according to rule.\n"
67 " --dbus-user.log - turn on logging for the user DBus."
60 " --dbus-user.own=name - allow ownership of name on the session DBus.\n" 68 " --dbus-user.own=name - allow ownership of name on the session DBus.\n"
69 " --dbus-user.see=name - allow seeing name on the session DBus.\n"
61 " --dbus-user.talk=name - allow talking to name on the session DBus.\n" 70 " --dbus-user.talk=name - allow talking to name on the session DBus.\n"
62 " --debug - print sandbox debug messages.\n" 71 " --debug - print sandbox debug messages.\n"
63 " --debug-blacklists - debug blacklisting.\n" 72 " --debug-blacklists - debug blacklisting.\n"
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index df2d2a2e8..198f33c00 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -491,6 +491,15 @@ Allow the application to own the name org.gnome.ghex and all names underneath in
491\fBdbus-system.talk org.freedesktop.Notifications 491\fBdbus-system.talk org.freedesktop.Notifications
492Allow the application to talk to the name org.freedesktop.Notifications on the system DBus. 492Allow the application to talk to the name org.freedesktop.Notifications on the system DBus.
493.TP 493.TP
494\fBdbus-system.see org.freedesktop.Notifications
495Allow the application to see but not talk to the name org.freedesktop.Notifications on the system DBus.
496.TP
497\fBdbus-system.call org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
498Allow the application to call methods of the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus.
499.TP
500\fBdbus-system.broadcast org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
501Allow the application to recieve broadcast signals from the the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the system DBus.
502.TP
494\fBdbus-user filter 503\fBdbus-user filter
495Enable filtered access to the session DBus. Filters can be specified with the dbus-user.talk and dbus-user.own commands. 504Enable filtered access to the session DBus. Filters can be specified with the dbus-user.talk and dbus-user.own commands.
496.TP 505.TP
@@ -503,6 +512,15 @@ Allow the application to own the name org.gnome.ghex and all names underneath in
503\fBdbus-user.talk org.freedesktop.Notifications 512\fBdbus-user.talk org.freedesktop.Notifications
504Allow the application to talk to the name org.freedesktop.Notifications on the session DBus. 513Allow the application to talk to the name org.freedesktop.Notifications on the session DBus.
505.TP 514.TP
515\fBdbus-user.see org.freedesktop.Notifications
516Allow the application to see but not talk to the name org.freedesktop.Notifications on the session DBus.
517.TP
518\fBdbus-user.call org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
519Allow the application to call methods of the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the session DBus.
520.TP
521\fBdbus-user.broadcast org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
522Allow the application to recieve broadcast signals from the the interface org.freedesktop.Notifications of the object exposed at the path /org/freedesktop/Notifications by the client owning the bus name org.freedesktop.Notifications on the session DBus.
523.TP
506\fBnodbus \fR(deprecated) 524\fBnodbus \fR(deprecated)
507Disable D-Bus access (both system and session buses). Equivalent to dbus-system none and dbus-user none. 525Disable D-Bus access (both system and session buses). Equivalent to dbus-system none and dbus-user none.
508.TP 526.TP
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index fae97ceb7..982b40d89 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -326,6 +326,22 @@ $ firejail \-\-list
326$ firejail \-\-cpu.print=3272 326$ firejail \-\-cpu.print=3272
327 327
328.TP 328.TP
329\fB\-\-dbus-log=file
330Specify the location for the DBus log file.
331.br
332
333.br
334The log file contains events for both the system and session buses if both of
335the --dbus-sysem.log and --dbus-user.log options are specified. If no log file
336path is given, logs are written to the standard output instead.
337.br
338
339.br
340Example:
341.br
342$ firejail --dbus-system=filter --dbus-system.log --dbus-log=dbus.txt
343
344.TP
329\fB\-\-dbus-system=filter|none 345\fB\-\-dbus-system=filter|none
330Set system DBus sandboxing policy. 346Set system DBus sandboxing policy.
331.br 347.br
@@ -353,6 +369,52 @@ Example:
353$ firejail \-\-dbus-system=none 369$ firejail \-\-dbus-system=none
354 370
355.TP 371.TP
372\fB\-\-dbus-system.broadcast=name=[member][@path]
373Allows the application to receive broadcast signals from theindicated interface
374member at the indicated object path exposed by the indicated bus name on the
375system DBus.
376The name may have a .* suffix to match all names underneath it, including
377itself.
378The interface member may have a .* to match all members of an interface, or be * to match all interfaces.
379The path may have a /* suffix to indicate all objects underneath it, including
380itself.
381Omitting the interface member or the object path will match all members and
382object paths, respectively.
383.br
384
385.br
386Example:
387.br
388$ firejail --dbus-system=filter --dbus-system.broadcast=org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
389
390.TP
391\fB\-\-dbus-system.call=name=[member][@path]
392Allows the application to call the indicated interface member at the indicated
393object path exposed by the indicated bus name on the system DBus.
394The name may have a .* suffix to match all names underneath it, including
395itself.
396The interface member may have a .* to match all members of an interface, or be * to match all interfaces.
397The path may have a /* suffix to indicate all objects underneath it, including
398itself.
399Omitting the interface member or the object path will match all members and
400object paths, respectively.
401.br
402
403.br
404Example:
405.br
406$ firejail --dbus-system=filter --dbus-system.call=org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
407
408.TP
409\fB\-\-dbus-system.log
410Turn on DBus logging for the system DBus. This option requires --dbus-system=log.
411
412.br
413Example:
414.br
415$ firejail --dbus-system=filter --dbus-system.log
416
417.TP
356\fB\-\-dbus-system.own=name 418\fB\-\-dbus-system.own=name
357Allows the application to own the specified well-known name on the system DBus. 419Allows the application to own the specified well-known name on the system DBus.
358The name may have a .* suffix to match all names underneath it, including itself 420The name may have a .* suffix to match all names underneath it, including itself
@@ -366,6 +428,20 @@ Example:
366$ firejail --dbus-system=filter --dbus-system.own=org.gnome.ghex.* 428$ firejail --dbus-system=filter --dbus-system.own=org.gnome.ghex.*
367 429
368.TP 430.TP
431\fB\-\-dbus-system.see=name
432Allows the application to see, but not talk to the specified well-known name on
433the system DBus.
434The name may have a .* suffix to match all names underneath it, including itself
435(e.g. "foo.bar.*" matches "foo.bar", "foo.bar.baz" and "foo.bar.baz.quux", but
436not "foobar").
437.br
438
439.br
440Example:
441.br
442$ firejail --dbus-system=filter --dbus-system.see=org.freedesktop.Notifications
443
444.TP
369\fB\-\-dbus-system.talk=name 445\fB\-\-dbus-system.talk=name
370Allows the application to talk to the specified well-known name on the system DBus. 446Allows the application to talk to the specified well-known name on the system DBus.
371The name may have a .* suffix to match all names underneath it, including itself 447The name may have a .* suffix to match all names underneath it, including itself
@@ -406,6 +482,52 @@ Example:
406$ firejail \-\-dbus-user=none 482$ firejail \-\-dbus-user=none
407 483
408.TP 484.TP
485\fB\-\-dbus-user.broadcast=name=[member][@path]
486Allows the application to receive broadcast signals from theindicated interface
487member at the indicated object path exposed by the indicated bus name on the
488session DBus.
489The name may have a .* suffix to match all names underneath it, including
490itself.
491The interface member may have a .* to match all members of an interface, or be * to match all interfaces.
492The path may have a /* suffix to indicate all objects underneath it, including
493itself.
494Omitting the interface member or the object path will match all members and
495object paths, respectively.
496.br
497
498.br
499Example:
500.br
501$ firejail --dbus-user=filter --dbus-user.broadcast=org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
502
503.TP
504\fB\-\-dbus-user.call=name=[member][@path]
505Allows the application to call the indicated interface member at the indicated
506object path exposed by the indicated bus name on the session DBus.
507The name may have a .* suffix to match all names underneath it, including
508itself.
509The interface member may have a .* to match all members of an interface, or be * to match all interfaces.
510The path may have a /* suffix to indicate all objects underneath it, including
511itself.
512Omitting the interface member or the object path will match all members and
513object paths, respectively.
514.br
515
516.br
517Example:
518.br
519$ firejail --dbus-user=filter --dbus-user.call=org.freedesktop.Notifications=org.freedesktop.Notifications.*@/org/freedesktop/Notifications
520
521.TP
522\fB\-\-dbus-user.log
523Turn on DBus logging for the session DBus. This option requires --dbus-user=log.
524
525.br
526Example:
527.br
528$ firejail --dbus-user=filter --dbus-user.log
529
530.TP
409\fB\-\-dbus-user.own=name 531\fB\-\-dbus-user.own=name
410Allows the application to own the specified well-known name on the session DBus. 532Allows the application to own the specified well-known name on the session DBus.
411The name may have a .* suffix to match all names underneath it, including itself 533The name may have a .* suffix to match all names underneath it, including itself
@@ -432,6 +554,20 @@ Example:
432$ firejail --dbus-user=filter --dbus-user.talk=org.freedesktop.Notifications 554$ firejail --dbus-user=filter --dbus-user.talk=org.freedesktop.Notifications
433 555
434.TP 556.TP
557\fB\-\-dbus-user.see=name
558Allows the application to see, but not talk to the specified well-known name on
559the session DBus.
560The name may have a .* suffix to match all names underneath it, including itself
561(e.g. "foo.bar.*" matches "foo.bar", "foo.bar.baz" and "foo.bar.baz.quux", but
562not "foobar").
563.br
564
565.br
566Example:
567.br
568$ firejail --dbus-user=filter --dbus-user.see=org.freedesktop.Notifications
569
570.TP
435\fB\-\-debug\fR 571\fB\-\-debug\fR
436Print debug messages. 572Print debug messages.
437.br 573.br