aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kris7topher@gmail.com>2020-05-03 20:43:32 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2020-05-07 01:56:40 +0200
commit8e719e0257bb92c143f56e9765e196c35fd57368 (patch)
tree3e0b0049926214ec4f320bcc80e955bed7d2de3d /src
parentAdd --dbus-*.see options (diff)
downloadfirejail-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.
Diffstat (limited to 'src')
-rw-r--r--src/firejail/dbus.c72
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/main.c32
-rw-r--r--src/firejail/profile.c28
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;
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,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
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 != '_') {
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
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;
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
849int dbus_check_name(const char *name); 849int dbus_check_name(const char *name);
850int dbus_check_call_rule(const char *name);
850void dbus_check_profile(void); 851void dbus_check_profile(void);
851void dbus_proxy_start(void); 852void dbus_proxy_start(void);
852void dbus_proxy_stop(void); 853void 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;