diff options
author | 2020-05-03 20:43:32 +0200 | |
---|---|---|
committer | 2020-05-07 01:56:40 +0200 | |
commit | 8e719e0257bb92c143f56e9765e196c35fd57368 (patch) | |
tree | 3e0b0049926214ec4f320bcc80e955bed7d2de3d | |
parent | Add --dbus-*.see options (diff) | |
download | firejail-8e719e0257bb92c143f56e9765e196c35fd57368.tar.gz firejail-8e719e0257bb92c143f56e9765e196c35fd57368.tar.zst firejail-8e719e0257bb92c143f56e9765e196c35fd57368.zip |
Add dbus-*.call and dbus-*.broadcast commands
This allows setting per-member and per-object path policies for
xdg-dbus-proxy.
-rw-r--r-- | src/firejail/dbus.c | 72 | ||||
-rw-r--r-- | src/firejail/firejail.h | 1 | ||||
-rw-r--r-- | src/firejail/main.c | 32 | ||||
-rw-r--r-- | src/firejail/profile.c | 28 |
4 files changed, 130 insertions, 3 deletions
diff --git a/src/firejail/dbus.c b/src/firejail/dbus.c index 0f4f18c57..5b47567e2 100644 --- a/src/firejail/dbus.c +++ b/src/firejail/dbus.c | |||
@@ -48,7 +48,7 @@ static int dbus_proxy_status_fd = -1; | |||
48 | static char *dbus_user_proxy_socket = NULL; | 48 | static char *dbus_user_proxy_socket = NULL; |
49 | static char *dbus_system_proxy_socket = NULL; | 49 | static char *dbus_system_proxy_socket = NULL; |
50 | 50 | ||
51 | int dbus_check_name(const char *name) { | 51 | static 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,14 @@ 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; | 66 | return 0; |
67 | } | 67 | } |
68 | } | 68 | } |
69 | else { | 69 | else { |
70 | if (*p == '*') { | 70 | if (*p == '*') { |
71 | return *(p + 1) == '\0'; | 71 | return *(p + 1) == '\0'; |
72 | } else if (!alpha && *p != '_' && *p != '-') { | 72 | } else if (!alpha && *p != '_' && (!hyphens_allowed || *p != '-')) { |
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | in_segment = 1; | 75 | in_segment = 1; |
@@ -79,6 +79,72 @@ int dbus_check_name(const char *name) { | |||
79 | return in_segment && segments >= 2; | 79 | return in_segment && segments >= 2; |
80 | } | 80 | } |
81 | 81 | ||
82 | static 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 != '_') { | ||
100 | return 0; | ||
101 | } | ||
102 | } | ||
103 | else { | ||
104 | if (*p == '*') { | ||
105 | return *(p + 1) == '\0'; | ||
106 | } else if (!alpha && *p != '_') { | ||
107 | return 0; | ||
108 | } | ||
109 | in_segment = 1; | ||
110 | } | ||
111 | ++p; | ||
112 | } | ||
113 | return in_segment && segments >= 2; | ||
114 | } | ||
115 | |||
116 | int dbus_check_name(const char *name) { | ||
117 | return check_bus_or_interface_name(name, 1); | ||
118 | } | ||
119 | |||
120 | int 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 | |||
82 | static void dbus_check_bus_profile(char const *prefix, DbusPolicy *policy) { | 148 | static 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; |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 9b288b1b9..19ec2762c 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -847,6 +847,7 @@ void set_profile_run_file(pid_t pid, const char *fname); | |||
847 | 847 | ||
848 | // dbus.c | 848 | // dbus.c |
849 | int dbus_check_name(const char *name); | 849 | int dbus_check_name(const char *name); |
850 | int dbus_check_call_rule(const char *name); | ||
850 | void dbus_check_profile(void); | 851 | void dbus_check_profile(void); |
851 | void dbus_proxy_start(void); | 852 | void dbus_proxy_start(void); |
852 | void dbus_proxy_stop(void); | 853 | void dbus_proxy_stop(void); |
diff --git a/src/firejail/main.c b/src/firejail/main.c index fa2b0e2e1..8d60d3790 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -2097,6 +2097,22 @@ int main(int argc, char **argv, char **envp) { | |||
2097 | profile_check_line(line, 0, NULL); // will exit if something wrong | 2097 | profile_check_line(line, 0, NULL); // will exit if something wrong |
2098 | profile_add(line); | 2098 | profile_add(line); |
2099 | } | 2099 | } |
2100 | else if (strncmp(argv[i], "--dbus-user.call=", 17) == 0) { | ||
2101 | char *line; | ||
2102 | if (asprintf(&line, "dbus-user.call %s", argv[i] + 17) == -1) | ||
2103 | errExit("asprintf"); | ||
2104 | |||
2105 | profile_check_line(line, 0, NULL); // will exit if something wrong | ||
2106 | profile_add(line); | ||
2107 | } | ||
2108 | else if (strncmp(argv[i], "--dbus-user.broadcast=", 22) == 0) { | ||
2109 | char *line; | ||
2110 | if (asprintf(&line, "dbus-user.broadcast %s", argv[i] + 22) == -1) | ||
2111 | errExit("asprintf"); | ||
2112 | |||
2113 | profile_check_line(line, 0, NULL); // will exit if something wrong | ||
2114 | profile_add(line); | ||
2115 | } | ||
2100 | else if (strncmp("--dbus-system=", argv[i], 14) == 0) { | 2116 | else if (strncmp("--dbus-system=", argv[i], 14) == 0) { |
2101 | if (strcmp("filter", argv[i] + 14) == 0) { | 2117 | if (strcmp("filter", argv[i] + 14) == 0) { |
2102 | if (arg_dbus_system == DBUS_POLICY_BLOCK) { | 2118 | if (arg_dbus_system == DBUS_POLICY_BLOCK) { |
@@ -2135,6 +2151,22 @@ int main(int argc, char **argv, char **envp) { | |||
2135 | profile_check_line(line, 0, NULL); // will exit if something wrong | 2151 | profile_check_line(line, 0, NULL); // will exit if something wrong |
2136 | profile_add(line); | 2152 | profile_add(line); |
2137 | } | 2153 | } |
2154 | else if (strncmp(argv[i], "--dbus-system.call=", 19) == 0) { | ||
2155 | char *line; | ||
2156 | if (asprintf(&line, "dbus-system.call %s", argv[i] + 19) == -1) | ||
2157 | errExit("asprintf"); | ||
2158 | |||
2159 | profile_check_line(line, 0, NULL); // will exit if something wrong | ||
2160 | profile_add(line); | ||
2161 | } | ||
2162 | else if (strncmp(argv[i], "--dbus-system.broadcast=", 24) == 0) { | ||
2163 | char *line; | ||
2164 | if (asprintf(&line, "dbus-system.broadcast %s", argv[i] + 24) == -1) | ||
2165 | errExit("asprintf"); | ||
2166 | |||
2167 | profile_check_line(line, 0, NULL); // will exit if something wrong | ||
2168 | profile_add(line); | ||
2169 | } | ||
2138 | 2170 | ||
2139 | //************************************* | 2171 | //************************************* |
2140 | // network | 2172 | // network |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index f2959686a..699ca4bea 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -473,6 +473,20 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
473 | } | 473 | } |
474 | return 1; | 474 | return 1; |
475 | } | 475 | } |
476 | else if (strncmp(ptr, "dbus-user.call ", 15) == 0) { | ||
477 | if (!dbus_check_call_rule(ptr + 15)) { | ||
478 | fprintf(stderr, "Invalid dbus-user.call rule: %s\n", ptr + 15); | ||
479 | exit(1); | ||
480 | } | ||
481 | return 1; | ||
482 | } | ||
483 | else if (strncmp(ptr, "dbus-user.broadcast ", 20) == 0) { | ||
484 | if (!dbus_check_call_rule(ptr + 20)) { | ||
485 | fprintf(stderr, "Invalid dbus-user.broadcast rule: %s\n", ptr + 20); | ||
486 | exit(1); | ||
487 | } | ||
488 | return 1; | ||
489 | } | ||
476 | else if (strncmp("dbus-system ", ptr, 12) == 0) { | 490 | else if (strncmp("dbus-system ", ptr, 12) == 0) { |
477 | ptr += 12; | 491 | ptr += 12; |
478 | if (strcmp("filter", ptr) == 0) { | 492 | if (strcmp("filter", ptr) == 0) { |
@@ -510,6 +524,20 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
510 | } | 524 | } |
511 | return 1; | 525 | return 1; |
512 | } | 526 | } |
527 | else if (strncmp(ptr, "dbus-system.call ", 17) == 0) { | ||
528 | if (!dbus_check_call_rule(ptr + 17)) { | ||
529 | fprintf(stderr, "Invalid dbus-system.call rule: %s\n", ptr + 17); | ||
530 | exit(1); | ||
531 | } | ||
532 | return 1; | ||
533 | } | ||
534 | else if (strncmp(ptr, "dbus-system.broadcast ", 22) == 0) { | ||
535 | if (!dbus_check_call_rule(ptr + 22)) { | ||
536 | fprintf(stderr, "Invalid dbus-system.broadcast rule: %s\n", ptr + 22); | ||
537 | exit(1); | ||
538 | } | ||
539 | return 1; | ||
540 | } | ||
513 | else if (strcmp(ptr, "nou2f") == 0) { | 541 | else if (strcmp(ptr, "nou2f") == 0) { |
514 | arg_nou2f = 1; | 542 | arg_nou2f = 1; |
515 | return 0; | 543 | return 0; |