diff options
author | Kristóf Marussy <kris7topher@gmail.com> | 2020-02-28 20:59:15 +0100 |
---|---|---|
committer | Kristóf Marussy <kris7topher@gmail.com> | 2020-04-06 21:26:41 +0200 |
commit | 31df60f61d2c286674d7a062797fba494d1fd47c (patch) | |
tree | 2f85182069cff035bf73aeff0338e8fa6643897f /src/firejail/dbus.c | |
parent | Add xdg-dbus-proxy support (diff) | |
download | firejail-31df60f61d2c286674d7a062797fba494d1fd47c.tar.gz firejail-31df60f61d2c286674d7a062797fba494d1fd47c.tar.zst firejail-31df60f61d2c286674d7a062797fba494d1fd47c.zip |
Add dbus filter options
The options --dbus-user.talk, --dbus-user.own, --dbus-system.talk, and
--dbus-system.own control which names can be accessed and owned on the user and
system buses.
Diffstat (limited to 'src/firejail/dbus.c')
-rw-r--r-- | src/firejail/dbus.c | 93 |
1 files changed, 91 insertions, 2 deletions
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c index 5cdd4b372..bf1ae9a1e 100644 --- a/src/firejail/dbus.c +++ b/src/firejail/dbus.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
25 | #include <unistd.h> | 25 | #include <unistd.h> |
26 | #include <fcntl.h> | 26 | #include <fcntl.h> |
27 | #include <string.h> | ||
27 | 28 | ||
28 | #define DBUS_SOCKET_PATH_PREFIX "unix:path=" | 29 | #define DBUS_SOCKET_PATH_PREFIX "unix:path=" |
29 | #define DBUS_USER_SOCKET_FORMAT "/run/user/%d/bus" | 30 | #define DBUS_USER_SOCKET_FORMAT "/run/user/%d/bus" |
@@ -33,12 +34,82 @@ | |||
33 | #define DBUS_SESSION_BUS_ADDRESS_ENV "DBUS_SESSION_BUS_ADDRESS" | 34 | #define DBUS_SESSION_BUS_ADDRESS_ENV "DBUS_SESSION_BUS_ADDRESS" |
34 | #define DBUS_USER_PROXY_SOCKET_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d-user" | 35 | #define DBUS_USER_PROXY_SOCKET_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d-user" |
35 | #define DBUS_SYSTEM_PROXY_SOCKET_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d-system" | 36 | #define DBUS_SYSTEM_PROXY_SOCKET_FORMAT RUN_FIREJAIL_DBUS_DIR "/%d-system" |
37 | #define DBUS_MAX_NAME_LENGTH 255 | ||
36 | 38 | ||
37 | static pid_t dbus_proxy_pid = 0; | 39 | static pid_t dbus_proxy_pid = 0; |
38 | static int dbus_proxy_status_fd = -1; | 40 | static int dbus_proxy_status_fd = -1; |
39 | static char *dbus_user_proxy_socket = NULL; | 41 | static char *dbus_user_proxy_socket = NULL; |
40 | static char *dbus_system_proxy_socket = NULL; | 42 | static char *dbus_system_proxy_socket = NULL; |
41 | 43 | ||
44 | int dbus_check_name(const char *name) { | ||
45 | unsigned long length = strlen(name); | ||
46 | if (length == 0 || length > DBUS_MAX_NAME_LENGTH) | ||
47 | return 0; | ||
48 | const char *p = name; | ||
49 | int segments = 1; | ||
50 | int in_segment = 0; | ||
51 | while (*p) { | ||
52 | int alpha = (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z'); | ||
53 | int digit = *p >= '0' && *p <= '9'; | ||
54 | if (in_segment) { | ||
55 | if (*p == '.') { | ||
56 | ++segments; | ||
57 | in_segment = 0; | ||
58 | } else if (!alpha && !digit && *p != '_' && *p != '-') { | ||
59 | return 0; | ||
60 | } | ||
61 | } | ||
62 | else { | ||
63 | if (*p == '*') { | ||
64 | return *(p + 1) == '\0'; | ||
65 | } else if (!alpha && *p != '_' && *p != '-') { | ||
66 | return 0; | ||
67 | } | ||
68 | in_segment = 1; | ||
69 | } | ||
70 | ++p; | ||
71 | } | ||
72 | return in_segment && segments >= 2; | ||
73 | } | ||
74 | |||
75 | static void dbus_check_bus_profile(char const *prefix, DbusPolicy policy) { | ||
76 | size_t prefix_length = strlen(prefix); | ||
77 | ProfileEntry *it = cfg.profile; | ||
78 | while (it) { | ||
79 | char *data = it->data; | ||
80 | it = it->next; | ||
81 | if (strncmp(prefix, data, prefix_length) == 0) { | ||
82 | switch (policy) { | ||
83 | case DBUS_POLICY_ALLOW: | ||
84 | // We should never get here, because profile parsing will fail earlier. | ||
85 | fprintf(stderr, | ||
86 | "Error: %s filter rule configured, but the bus is not " | ||
87 | "set to filter.\n", | ||
88 | prefix); | ||
89 | exit(1); | ||
90 | break; | ||
91 | case DBUS_POLICY_FILTER: | ||
92 | // All good. | ||
93 | break; | ||
94 | case DBUS_POLICY_BLOCK: | ||
95 | fwarning("%s filter rule configured, but the bus is blocked.\n", prefix); | ||
96 | fwarning("Ignoring \"%s\" and any other %s filter rules.\n", data, prefix); | ||
97 | break; | ||
98 | default: | ||
99 | fprintf(stderr, "Error: Unknown %s policy.\n", prefix); | ||
100 | exit(1); | ||
101 | break; | ||
102 | } | ||
103 | break; | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | void dbus_check_profile(void) { | ||
109 | dbus_check_bus_profile("dbus-user", arg_dbus_user); | ||
110 | dbus_check_bus_profile("dbus-system", arg_dbus_system); | ||
111 | } | ||
112 | |||
42 | static void write_arg(int fd, char const *format, ...) { | 113 | static void write_arg(int fd, char const *format, ...) { |
43 | va_list ap; | 114 | va_list ap; |
44 | va_start(ap, format); | 115 | va_start(ap, format); |
@@ -55,6 +126,24 @@ static void write_arg(int fd, char const *format, ...) { | |||
55 | free(arg); | 126 | free(arg); |
56 | } | 127 | } |
57 | 128 | ||
129 | static void write_profile(int fd, char const *prefix) { | ||
130 | size_t prefix_length = strlen(prefix); | ||
131 | ProfileEntry *it = cfg.profile; | ||
132 | while (it) { | ||
133 | char *data = it->data; | ||
134 | it = it->next; | ||
135 | if (strncmp(prefix, data, prefix_length) != 0) | ||
136 | continue; | ||
137 | data += prefix_length; | ||
138 | int arg_length = 0; | ||
139 | while (data[arg_length] != '\0' && data[arg_length] != ' ') | ||
140 | arg_length++; | ||
141 | if (data[arg_length] != ' ') | ||
142 | continue; | ||
143 | write_arg(fd, "--%.*s=%s", arg_length, data, &data[arg_length + 1]); | ||
144 | } | ||
145 | } | ||
146 | |||
58 | void dbus_proxy_start(void) { | 147 | void dbus_proxy_start(void) { |
59 | int status_pipe[2]; | 148 | int status_pipe[2]; |
60 | if (pipe(status_pipe) == -1) | 149 | if (pipe(status_pipe) == -1) |
@@ -96,7 +185,7 @@ void dbus_proxy_start(void) { | |||
96 | errExit("asprintf"); | 185 | errExit("asprintf"); |
97 | write_arg(args_pipe[1], dbus_user_proxy_socket); | 186 | write_arg(args_pipe[1], dbus_user_proxy_socket); |
98 | write_arg(args_pipe[1], "--filter"); | 187 | write_arg(args_pipe[1], "--filter"); |
99 | // TODO Write filter rules to pipe | 188 | write_profile(args_pipe[1], "dbus-user."); |
100 | } | 189 | } |
101 | 190 | ||
102 | if (arg_dbus_system == DBUS_POLICY_FILTER) { | 191 | if (arg_dbus_system == DBUS_POLICY_FILTER) { |
@@ -105,7 +194,7 @@ void dbus_proxy_start(void) { | |||
105 | errExit("asprintf"); | 194 | errExit("asprintf"); |
106 | write_arg(args_pipe[1], dbus_system_proxy_socket); | 195 | write_arg(args_pipe[1], dbus_system_proxy_socket); |
107 | write_arg(args_pipe[1], "--filter"); | 196 | write_arg(args_pipe[1], "--filter"); |
108 | // TODO Write filter rules to pipe | 197 | write_profile(args_pipe[1], "dbus-system."); |
109 | } | 198 | } |
110 | 199 | ||
111 | if (close(args_pipe[1]) == -1) | 200 | if (close(args_pipe[1]) == -1) |