aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/dbus.c139
-rw-r--r--src/include/rundefs.h3
2 files changed, 105 insertions, 37 deletions
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c
index 9efd7bc85..e358aaa49 100644
--- a/src/firejail/dbus.c
+++ b/src/firejail/dbus.c
@@ -33,10 +33,10 @@
33 33
34#define DBUS_SOCKET_PATH_PREFIX "unix:path=" 34#define DBUS_SOCKET_PATH_PREFIX "unix:path="
35#define DBUS_USER_SOCKET_FORMAT "/run/user/%d/bus" 35#define DBUS_USER_SOCKET_FORMAT "/run/user/%d/bus"
36#define DBUS_USER_SOCKET_PATH_FORMAT DBUS_SOCKET_PATH_PREFIX DBUS_USER_SOCKET_FORMAT 36#define DBUS_USER_SOCKET_FORMAT2 "/run/user/%d/dbus/user_bus_socket"
37#define DBUS_SYSTEM_SOCKET "/run/dbus/system_bus_socket" 37#define DBUS_SYSTEM_SOCKET "/run/dbus/system_bus_socket"
38#define DBUS_SYSTEM_SOCKET_PATH DBUS_SOCKET_PATH_PREFIX DBUS_SYSTEM_SOCKET
39#define DBUS_SESSION_BUS_ADDRESS_ENV "DBUS_SESSION_BUS_ADDRESS" 38#define DBUS_SESSION_BUS_ADDRESS_ENV "DBUS_SESSION_BUS_ADDRESS"
39#define DBUS_SYSTEM_BUS_ADDRESS_ENV "DBUS_SYSTEM_BUS_ADDRESS"
40#define DBUS_USER_DIR_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d" 40#define DBUS_USER_DIR_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d"
41#define DBUS_USER_PROXY_SOCKET_FORMAT DBUS_USER_DIR_FORMAT "/%d-user" 41#define DBUS_USER_PROXY_SOCKET_FORMAT DBUS_USER_DIR_FORMAT "/%d-user"
42#define DBUS_SYSTEM_PROXY_SOCKET_FORMAT DBUS_USER_DIR_FORMAT "/%d-system" 42#define DBUS_SYSTEM_PROXY_SOCKET_FORMAT DBUS_USER_DIR_FORMAT "/%d-system"
@@ -170,6 +170,36 @@ static void dbus_create_user_dir(void) {
170 free(path); 170 free(path);
171} 171}
172 172
173static char *find_user_socket_by_format(char *format) {
174 char *dbus_user_socket;
175 if (asprintf(&dbus_user_socket, format, (int) getuid()) == -1)
176 errExit("asprintf");
177 struct stat s;
178 if (stat(dbus_user_socket, &s) == -1) {
179 if (errno == ENOENT)
180 goto fail;
181 return NULL;
182 errExit("stat");
183 }
184 if (!S_ISSOCK(s.st_mode))
185 goto fail;
186 return dbus_user_socket;
187 fail:
188 free(dbus_user_socket);
189 return NULL;
190}
191
192static char *find_user_socket(void) {
193 char *socket1 = find_user_socket_by_format(DBUS_USER_SOCKET_FORMAT);
194 if (socket1 != NULL)
195 return socket1;
196 char *socket2 = find_user_socket_by_format(DBUS_USER_SOCKET_FORMAT2);
197 if (socket2 != NULL)
198 return socket2;
199 fprintf(stderr, "DBus user socket was not found.\n");
200 exit(1);
201}
202
173void dbus_proxy_start(void) { 203void dbus_proxy_start(void) {
174 dbus_create_user_dir(); 204 dbus_create_user_dir();
175 205
@@ -203,26 +233,35 @@ void dbus_proxy_start(void) {
203 errExit("close"); 233 errExit("close");
204 234
205 if (arg_dbus_user == DBUS_POLICY_FILTER) { 235 if (arg_dbus_user == DBUS_POLICY_FILTER) {
206 char *dbus_user_path_env = getenv(DBUS_SESSION_BUS_ADDRESS_ENV); 236 char *user_env = getenv(DBUS_SESSION_BUS_ADDRESS_ENV);
207 if (dbus_user_path_env == NULL) { 237 if (user_env == NULL) {
208 write_arg(args_pipe[1], DBUS_USER_SOCKET_PATH_FORMAT, getuid()); 238 char *dbus_user_socket = find_user_socket();
239 write_arg(args_pipe[1], DBUS_SOCKET_PATH_PREFIX "%s",
240 dbus_user_socket);
241 free(dbus_user_socket);
209 } else { 242 } else {
210 write_arg(args_pipe[1], dbus_user_path_env); 243 write_arg(args_pipe[1], "%s", user_env);
211 } 244 }
212 if (asprintf(&dbus_user_proxy_socket, DBUS_USER_PROXY_SOCKET_FORMAT, 245 if (asprintf(&dbus_user_proxy_socket, DBUS_USER_PROXY_SOCKET_FORMAT,
213 (int) getuid(), (int) getpid()) == -1) 246 (int) getuid(), (int) getpid()) == -1)
214 errExit("asprintf"); 247 errExit("asprintf");
215 write_arg(args_pipe[1], dbus_user_proxy_socket); 248 write_arg(args_pipe[1], "%s", dbus_user_proxy_socket);
216 write_arg(args_pipe[1], "--filter"); 249 write_arg(args_pipe[1], "--filter");
217 write_profile(args_pipe[1], "dbus-user."); 250 write_profile(args_pipe[1], "dbus-user.");
218 } 251 }
219 252
220 if (arg_dbus_system == DBUS_POLICY_FILTER) { 253 if (arg_dbus_system == DBUS_POLICY_FILTER) {
221 write_arg(args_pipe[1], DBUS_SYSTEM_SOCKET_PATH); 254 char *system_env = getenv(DBUS_SYSTEM_BUS_ADDRESS_ENV);
255 if (system_env == NULL) {
256 write_arg(args_pipe[1],
257 DBUS_SOCKET_PATH_PREFIX DBUS_SYSTEM_SOCKET);
258 } else {
259 write_arg(args_pipe[1], "%s", system_env);
260 }
222 if (asprintf(&dbus_system_proxy_socket, DBUS_SYSTEM_PROXY_SOCKET_FORMAT, 261 if (asprintf(&dbus_system_proxy_socket, DBUS_SYSTEM_PROXY_SOCKET_FORMAT,
223 (int) getuid(), (int) getpid()) == -1) 262 (int) getuid(), (int) getpid()) == -1)
224 errExit("asprintf"); 263 errExit("asprintf");
225 write_arg(args_pipe[1], dbus_system_proxy_socket); 264 write_arg(args_pipe[1], "%s", dbus_system_proxy_socket);
226 write_arg(args_pipe[1], "--filter"); 265 write_arg(args_pipe[1], "--filter");
227 write_profile(args_pipe[1], "dbus-system."); 266 write_profile(args_pipe[1], "dbus-system.");
228 } 267 }
@@ -294,6 +333,16 @@ static void socket_overlay(char *socket_path, char *proxy_path) {
294 close(fd); 333 close(fd);
295} 334}
296 335
336static char *get_socket_env(const char *name) {
337 char *value = getenv(name);
338 if (value == NULL)
339 return NULL;
340 if (strncmp(value, DBUS_SOCKET_PATH_PREFIX,
341 strlen(DBUS_SOCKET_PATH_PREFIX)) == 0)
342 return value + strlen(DBUS_SOCKET_PATH_PREFIX);
343 return NULL;
344}
345
297static void disable_socket_dir(void) { 346static void disable_socket_dir(void) {
298 struct stat s; 347 struct stat s;
299 if (stat(RUN_FIREJAIL_DBUS_DIR, &s) == 0) 348 if (stat(RUN_FIREJAIL_DBUS_DIR, &s) == 0)
@@ -314,36 +363,41 @@ void dbus_apply_policy(void) {
314 return; 363 return;
315 } 364 }
316 365
317 char *dbus_new_user_socket_path; 366 create_empty_dir_as_root(RUN_DBUS_DIR, 0755);
318 if (asprintf(&dbus_new_user_socket_path, DBUS_USER_SOCKET_PATH_FORMAT, getuid()) == -1) 367 create_empty_file_as_root(RUN_DBUS_USER_SOCKET, 0700);
319 errExit("asprintf"); 368 create_empty_file_as_root(RUN_DBUS_SYSTEM_SOCKET, 0700);
320 char *dbus_new_user_socket = dbus_new_user_socket_path + strlen(DBUS_SOCKET_PATH_PREFIX);
321 char *dbus_user_path_env = getenv(DBUS_SESSION_BUS_ADDRESS_ENV);
322 char *dbus_orig_user_socket_path;
323 if (dbus_user_path_env != NULL
324 && strncmp(DBUS_SOCKET_PATH_PREFIX, dbus_user_path_env, strlen(DBUS_SOCKET_PATH_PREFIX)) == 0) {
325 dbus_orig_user_socket_path = dbus_user_path_env;
326 } else {
327 dbus_orig_user_socket_path = dbus_new_user_socket_path;
328 }
329 char *dbus_orig_user_socket = dbus_orig_user_socket_path + strlen(DBUS_SOCKET_PATH_PREFIX);
330 369
331 if (arg_dbus_user != DBUS_POLICY_ALLOW) { 370 if (arg_dbus_user != DBUS_POLICY_ALLOW) {
332 if (arg_dbus_user == DBUS_POLICY_FILTER) { 371 if (arg_dbus_user == DBUS_POLICY_FILTER) {
333 assert(dbus_user_proxy_socket != NULL); 372 assert(dbus_user_proxy_socket != NULL);
334 socket_overlay(dbus_new_user_socket, dbus_user_proxy_socket); 373 socket_overlay(RUN_DBUS_USER_SOCKET, dbus_user_proxy_socket);
335 free(dbus_user_proxy_socket); 374 free(dbus_user_proxy_socket);
336 } else { // arg_dbus_user == DBUS_POLICY_BLOCK
337 disable_file_or_dir(dbus_new_user_socket);
338 } 375 }
339 376
340 if (strcmp(dbus_orig_user_socket, dbus_new_user_socket) != 0) 377 char *dbus_user_socket;
341 disable_file_or_dir(dbus_orig_user_socket); 378 if (asprintf(&dbus_user_socket, DBUS_USER_SOCKET_FORMAT,
379 (int) getuid()) == -1)
380 errExit("asprintf");
381 disable_file_or_dir(dbus_user_socket);
382
383 char *dbus_user_socket2;
384 if (asprintf(&dbus_user_socket2, DBUS_USER_SOCKET_FORMAT2,
385 (int) getuid()) == -1)
386 errExit("asprintf");
387 disable_file_or_dir(dbus_user_socket2);
342 388
343 // set a new environment variable: 389 char *user_env = get_socket_env(DBUS_SESSION_BUS_ADDRESS_ENV);
344 // DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/<UID>/bus 390 if (user_env != NULL && strcmp(user_env, dbus_user_socket) != 0 &&
345 if (setenv(DBUS_SESSION_BUS_ADDRESS_ENV, dbus_new_user_socket_path, 1) == -1) { 391 strcmp(user_env, dbus_user_socket2) != 0)
346 fprintf(stderr, "Error: cannot modify " DBUS_SESSION_BUS_ADDRESS_ENV " required by --dbus-user\n"); 392 disable_file_or_dir(user_env);
393
394 free(dbus_user_socket);
395 free(dbus_user_socket2);
396
397 if (setenv(DBUS_SESSION_BUS_ADDRESS_ENV,
398 DBUS_SOCKET_PATH_PREFIX RUN_DBUS_USER_SOCKET, 1) == -1) {
399 fprintf(stderr, "Error: cannot modify " DBUS_SESSION_BUS_ADDRESS_ENV
400 " required by --dbus-user\n");
347 exit(1); 401 exit(1);
348 } 402 }
349 403
@@ -355,14 +409,25 @@ void dbus_apply_policy(void) {
355 free(path); 409 free(path);
356 } 410 }
357 411
358 free(dbus_new_user_socket_path); 412 if (arg_dbus_system != DBUS_POLICY_ALLOW) {
413 if (arg_dbus_system == DBUS_POLICY_FILTER) {
414 assert(dbus_system_proxy_socket != NULL);
415 socket_overlay(RUN_DBUS_SYSTEM_SOCKET, dbus_system_proxy_socket);
416 free(dbus_system_proxy_socket);
417 }
359 418
360 if (arg_dbus_system == DBUS_POLICY_FILTER) {
361 assert(dbus_system_proxy_socket != NULL);
362 socket_overlay(DBUS_SYSTEM_SOCKET, dbus_system_proxy_socket);
363 free(dbus_system_proxy_socket);
364 } else if (arg_dbus_system == DBUS_POLICY_BLOCK) {
365 disable_file_or_dir(DBUS_SYSTEM_SOCKET); 419 disable_file_or_dir(DBUS_SYSTEM_SOCKET);
420
421 char *system_env = get_socket_env(DBUS_SYSTEM_BUS_ADDRESS_ENV);
422 if (system_env != NULL && strcmp(system_env, DBUS_SYSTEM_SOCKET) != 0)
423 disable_file_or_dir(system_env);
424
425 if (setenv(DBUS_SYSTEM_BUS_ADDRESS_ENV,
426 DBUS_SOCKET_PATH_PREFIX RUN_DBUS_SYSTEM_SOCKET, 1) == -1) {
427 fprintf(stderr, "Error: cannot modify " DBUS_SYSTEM_BUS_ADDRESS_ENV
428 " required by --dbus-system\n");
429 exit(1);
430 }
366 } 431 }
367 432
368 // Only disable access to /run/firejail/dbus here, when the sockets have been bind-mounted. 433 // Only disable access to /run/firejail/dbus here, when the sockets have been bind-mounted.
diff --git a/src/include/rundefs.h b/src/include/rundefs.h
index 528d9e901..f8bcdec52 100644
--- a/src/include/rundefs.h
+++ b/src/include/rundefs.h
@@ -57,6 +57,9 @@
57#define RUN_DHCLIENT_4_LEASES_FILE RUN_DHCLIENT_DIR "/dhclient.leases" 57#define RUN_DHCLIENT_4_LEASES_FILE RUN_DHCLIENT_DIR "/dhclient.leases"
58#define RUN_DHCLIENT_4_PID_FILE RUN_DHCLIENT_DIR "/dhclient.pid" 58#define RUN_DHCLIENT_4_PID_FILE RUN_DHCLIENT_DIR "/dhclient.pid"
59#define RUN_DHCLIENT_6_PID_FILE RUN_DHCLIENT_DIR "/dhclient6.pid" 59#define RUN_DHCLIENT_6_PID_FILE RUN_DHCLIENT_DIR "/dhclient6.pid"
60#define RUN_DBUS_DIR RUN_MNT_DIR "/dbus"
61#define RUN_DBUS_USER_SOCKET RUN_DBUS_DIR "/user"
62#define RUN_DBUS_SYSTEM_SOCKET RUN_DBUS_DIR "/system"
60 63
61#define RUN_SECCOMP_DIR RUN_MNT_DIR "/seccomp" 64#define RUN_SECCOMP_DIR RUN_MNT_DIR "/seccomp"
62#define RUN_SECCOMP_LIST RUN_SECCOMP_DIR "/seccomp.list" // list of seccomp files installed 65#define RUN_SECCOMP_LIST RUN_SECCOMP_DIR "/seccomp.list" // list of seccomp files installed