]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/proxy.c
bus-proxy: share policy between threads
[thirdparty/systemd.git] / src / bus-proxyd / proxy.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9 Copyright 2014 David Herrmann
10
11 systemd is free software; you can redistribute it and/or modify it
12 under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2.1 of the License, or
14 (at your option) any later version.
15
16 systemd is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
20
21 You should have received a copy of the GNU Lesser General Public License
22 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 ***/
24
25 #include <sys/socket.h>
26 #include <sys/un.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/poll.h>
33 #include <stddef.h>
34 #include <getopt.h>
35
36 #include "log.h"
37 #include "util.h"
38 #include "socket-util.h"
39 #include "sd-daemon.h"
40 #include "sd-bus.h"
41 #include "bus-internal.h"
42 #include "bus-message.h"
43 #include "bus-util.h"
44 #include "build.h"
45 #include "strv.h"
46 #include "def.h"
47 #include "capability.h"
48 #include "bus-control.h"
49 #include "smack-util.h"
50 #include "set.h"
51 #include "bus-xml-policy.h"
52 #include "driver.h"
53 #include "proxy.h"
54 #include "synthesize.h"
55
56 static int proxy_create_dest(Proxy *p, const char *dest, const char *local_sec, bool negotiate_fds) {
57 _cleanup_bus_close_unref_ sd_bus *b = NULL;
58 int r;
59
60 r = sd_bus_new(&b);
61 if (r < 0)
62 return log_error_errno(r, "Failed to allocate bus: %m");
63
64 r = sd_bus_set_description(b, "sd-proxy");
65 if (r < 0)
66 return log_error_errno(r, "Failed to set bus name: %m");
67
68 r = sd_bus_set_address(b, dest);
69 if (r < 0)
70 return log_error_errno(r, "Failed to set address to connect to: %m");
71
72 r = sd_bus_negotiate_fds(b, negotiate_fds);
73 if (r < 0)
74 return log_error_errno(r, "Failed to set FD negotiation: %m");
75
76 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
77 if (r < 0)
78 return log_error_errno(r, "Failed to set credential negotiation: %m");
79
80 if (p->local_creds.pid > 0) {
81 b->fake_pids.pid = p->local_creds.pid;
82 b->fake_pids_valid = true;
83
84 b->fake_creds.uid = p->local_creds.uid;
85 b->fake_creds.euid = UID_INVALID;
86 b->fake_creds.suid = UID_INVALID;
87 b->fake_creds.fsuid = UID_INVALID;
88 b->fake_creds.gid = p->local_creds.gid;
89 b->fake_creds.egid = GID_INVALID;
90 b->fake_creds.sgid = GID_INVALID;
91 b->fake_creds.fsgid = GID_INVALID;
92 b->fake_creds_valid = true;
93 }
94
95 if (local_sec) {
96 b->fake_label = strdup(local_sec);
97 if (!b->fake_label)
98 return log_oom();
99 }
100
101 b->manual_peer_interface = true;
102
103 r = sd_bus_start(b);
104 if (r < 0)
105 return log_error_errno(r, "Failed to start bus client: %m");
106
107 p->dest_bus = b;
108 b = NULL;
109 return 0;
110 }
111
112 static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
113 _cleanup_bus_close_unref_ sd_bus *b = NULL;
114 sd_id128_t server_id;
115 int r;
116
117 r = sd_bus_new(&b);
118 if (r < 0)
119 return log_error_errno(r, "Failed to allocate bus: %m");
120
121 r = sd_bus_set_fd(b, in_fd, out_fd);
122 if (r < 0)
123 return log_error_errno(r, "Failed to set fds: %m");
124
125 r = sd_bus_get_bus_id(p->dest_bus, &server_id);
126 if (r < 0)
127 return log_error_errno(r, "Failed to get server ID: %m");
128
129 r = sd_bus_set_server(b, 1, server_id);
130 if (r < 0)
131 return log_error_errno(r, "Failed to set server mode: %m");
132
133 r = sd_bus_negotiate_fds(b, negotiate_fds);
134 if (r < 0)
135 return log_error_errno(r, "Failed to set FD negotiation: %m");
136
137 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
138 if (r < 0)
139 return log_error_errno(r, "Failed to set credential negotiation: %m");
140
141 r = sd_bus_set_anonymous(b, true);
142 if (r < 0)
143 return log_error_errno(r, "Failed to set anonymous authentication: %m");
144
145 b->manual_peer_interface = true;
146
147 r = sd_bus_start(b);
148 if (r < 0)
149 return log_error_errno(r, "Failed to start bus client: %m");
150
151 p->local_bus = b;
152 b = NULL;
153 return 0;
154 }
155
156 static int proxy_prepare_matches(Proxy *p) {
157 _cleanup_free_ char *match = NULL;
158 const char *unique;
159 int r;
160
161 if (!p->dest_bus->is_kernel)
162 return 0;
163
164 r = sd_bus_get_unique_name(p->dest_bus, &unique);
165 if (r < 0)
166 return log_error_errno(r, "Failed to get unique name: %m");
167
168 match = strjoin("type='signal',"
169 "sender='org.freedesktop.DBus',"
170 "path='/org/freedesktop/DBus',"
171 "interface='org.freedesktop.DBus',"
172 "member='NameOwnerChanged',"
173 "arg1='",
174 unique,
175 "'",
176 NULL);
177 if (!match)
178 return log_oom();
179
180 r = sd_bus_add_match(p->dest_bus, NULL, match, NULL, NULL);
181 if (r < 0)
182 return log_error_errno(r, "Failed to add match for NameLost: %m");
183
184 free(match);
185 match = strjoin("type='signal',"
186 "sender='org.freedesktop.DBus',"
187 "path='/org/freedesktop/DBus',"
188 "interface='org.freedesktop.DBus',"
189 "member='NameOwnerChanged',"
190 "arg2='",
191 unique,
192 "'",
193 NULL);
194 if (!match)
195 return log_oom();
196
197 r = sd_bus_add_match(p->dest_bus, NULL, match, NULL, NULL);
198 if (r < 0)
199 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
200
201 return 0;
202 }
203
204 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest) {
205 _cleanup_(proxy_freep) Proxy *p = NULL;
206 _cleanup_free_ char *local_sec = NULL;
207 bool is_unix;
208 int r;
209
210 p = new0(Proxy, 1);
211 if (!p)
212 return log_oom();
213
214 p->local_in = in_fd;
215 p->local_out = out_fd;
216
217 p->owned_names = set_new(&string_hash_ops);
218 if (!p->owned_names)
219 return log_oom();
220
221 is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
222 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
223
224 if (is_unix) {
225 (void) getpeercred(in_fd, &p->local_creds);
226 (void) getpeersec(in_fd, &local_sec);
227 }
228
229 r = proxy_create_dest(p, dest, local_sec, is_unix);
230 if (r < 0)
231 return r;
232
233 r = proxy_create_local(p, in_fd, out_fd, is_unix);
234 if (r < 0)
235 return r;
236
237 r = proxy_prepare_matches(p);
238 if (r < 0)
239 return r;
240
241 *out = p;
242 p = NULL;
243 return 0;
244 }
245
246 Proxy *proxy_free(Proxy *p) {
247 if (!p)
248 return NULL;
249
250 sd_bus_close_unrefp(&p->local_bus);
251 sd_bus_close_unrefp(&p->dest_bus);
252 set_free_free(p->owned_names);
253 free(p);
254
255 return NULL;
256 }
257
258 int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
259 _cleanup_strv_free_ char **strv = NULL;
260 Policy *policy;
261 int r;
262
263 assert(p);
264 assert(sp);
265
266 /* no need to load legacy policy if destination is not kdbus */
267 if (!p->dest_bus->is_kernel)
268 return 0;
269
270 p->policy = sp;
271
272 policy = shared_policy_acquire(sp);
273 if (policy) {
274 /* policy already pre-loaded */
275 shared_policy_release(sp, policy);
276 return 0;
277 }
278
279 if (!configuration) {
280 const char *scope;
281
282 r = sd_bus_get_scope(p->dest_bus, &scope);
283 if (r < 0)
284 return log_error_errno(r, "Couldn't determine bus scope: %m");
285
286 if (streq(scope, "system"))
287 strv = strv_new("/etc/dbus-1/system.conf",
288 "/etc/dbus-1/system.d/",
289 "/etc/dbus-1/system-local.conf",
290 NULL);
291 else if (streq(scope, "user"))
292 strv = strv_new("/etc/dbus-1/session.conf",
293 "/etc/dbus-1/session.d/",
294 "/etc/dbus-1/session-local.conf",
295 NULL);
296 else
297 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
298
299 if (!strv)
300 return log_oom();
301
302 configuration = strv;
303 }
304
305 return shared_policy_preload(sp, configuration);
306 }
307
308 int proxy_hello_policy(Proxy *p, uid_t original_uid) {
309 Policy *policy;
310 int r = 0;
311
312 assert(p);
313
314 if (!p->policy)
315 return 0;
316
317 policy = shared_policy_acquire(p->policy);
318
319 if (p->local_creds.uid == original_uid)
320 log_debug("Permitting access, since bus owner matches bus client.");
321 else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
322 log_debug("Permitting access due to XML policy.");
323 else
324 r = log_error_errno(EPERM, "Policy denied connection.");
325
326 shared_policy_release(p->policy, policy);
327
328 return r;
329 }
330
331 static int proxy_wait(Proxy *p) {
332 uint64_t timeout_dest, timeout_local, t;
333 int events_dest, events_local, fd;
334 struct timespec _ts, *ts;
335 struct pollfd *pollfd;
336 int r;
337
338 assert(p);
339
340 fd = sd_bus_get_fd(p->dest_bus);
341 if (fd < 0)
342 return log_error_errno(fd, "Failed to get fd: %m");
343
344 events_dest = sd_bus_get_events(p->dest_bus);
345 if (events_dest < 0)
346 return log_error_errno(events_dest, "Failed to get events mask: %m");
347
348 r = sd_bus_get_timeout(p->dest_bus, &timeout_dest);
349 if (r < 0)
350 return log_error_errno(r, "Failed to get timeout: %m");
351
352 events_local = sd_bus_get_events(p->local_bus);
353 if (events_local < 0)
354 return log_error_errno(events_local, "Failed to get events mask: %m");
355
356 r = sd_bus_get_timeout(p->local_bus, &timeout_local);
357 if (r < 0)
358 return log_error_errno(r, "Failed to get timeout: %m");
359
360 t = timeout_dest;
361 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_dest))
362 t = timeout_local;
363
364 if (t == (uint64_t) -1)
365 ts = NULL;
366 else {
367 usec_t nw;
368
369 nw = now(CLOCK_MONOTONIC);
370 if (t > nw)
371 t -= nw;
372 else
373 t = 0;
374
375 ts = timespec_store(&_ts, t);
376 }
377
378 pollfd = (struct pollfd[3]) {
379 { .fd = fd, .events = events_dest, },
380 { .fd = p->local_in, .events = events_local & POLLIN, },
381 { .fd = p->local_out, .events = events_local & POLLOUT, },
382 };
383
384 r = ppoll(pollfd, 3, ts, NULL);
385 if (r < 0)
386 return log_error_errno(errno, "ppoll() failed: %m");
387
388 return 0;
389 }
390
391 static int handle_policy_error(sd_bus_message *m, int r) {
392 if (r == -ESRCH || r == -ENXIO)
393 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
394
395 return r;
396 }
397
398 static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
399 int r;
400
401 assert(from);
402 assert(to);
403 assert(m);
404
405 if (!policy)
406 return 0;
407
408 /*
409 * dbus-1 distinguishes expected and non-expected replies by tracking
410 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
411 * on expected replies, unless explicitly specified. But we dont track
412 * method-calls, thus, we cannot know whether a reply is expected.
413 * Fortunately, the kdbus forbids non-expected replies, so we can safely
414 * ignore any policy on those and let the kernel deal with it.
415 *
416 * TODO: To be correct, we should only ignore policy-tags that are
417 * applied on non-expected replies. However, so far we don't parse those
418 * tags so we let everything pass. I haven't seen a DENY policy tag on
419 * expected-replies, ever, so don't bother..
420 */
421 if (m->reply_cookie > 0)
422 return 0;
423
424 if (from->is_kernel) {
425 uid_t sender_uid = UID_INVALID;
426 gid_t sender_gid = GID_INVALID;
427 char **sender_names = NULL;
428 bool granted = false;
429
430 /* Driver messages are always OK */
431 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
432 return 0;
433
434 /* The message came from the kernel, and is sent to our legacy client. */
435 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
436
437 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
438 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
439
440 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
441 _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
442
443 /* If the message came from another legacy
444 * client, then the message creds will be
445 * missing, simply because on legacy clients
446 * per-message creds were unknown. In this
447 * case, query the creds of the peer
448 * instead. */
449
450 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_UID|SD_BUS_CREDS_GID, true, &sender_creds);
451 if (r < 0)
452 return handle_policy_error(m, r);
453
454 (void) sd_bus_creds_get_uid(sender_creds, &sender_uid);
455 (void) sd_bus_creds_get_gid(sender_creds, &sender_gid);
456 }
457
458 /* First check whether the sender can send the message to our name */
459 if (set_isempty(owned_names)) {
460 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member, false))
461 granted = true;
462 } else {
463 Iterator i;
464 char *n;
465
466 SET_FOREACH(n, owned_names, i)
467 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member, false)) {
468 granted = true;
469 break;
470 }
471 }
472
473 if (granted) {
474 /* Then check whether us (the recipient) can receive from the sender's name */
475 if (strv_isempty(sender_names)) {
476 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, false))
477 return 0;
478 } else {
479 char **n;
480
481 STRV_FOREACH(n, sender_names) {
482 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, false))
483 return 0;
484 }
485 }
486 }
487
488 /* Return an error back to the caller */
489 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
490 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
491
492 /* Return 1, indicating that the message shall not be processed any further */
493 return 1;
494 }
495
496 if (to->is_kernel) {
497 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
498 uid_t destination_uid = UID_INVALID;
499 gid_t destination_gid = GID_INVALID;
500 const char *destination_unique = NULL;
501 char **destination_names = NULL;
502 bool granted = false;
503
504 /* Driver messages are always OK */
505 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
506 return 0;
507
508 /* The message came from the legacy client, and is sent to kdbus. */
509 if (m->destination) {
510 r = bus_get_name_creds_kdbus(to, m->destination,
511 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
512 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
513 true, &destination_creds);
514 if (r < 0)
515 return handle_policy_error(m, r);
516
517 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
518 if (r < 0)
519 return handle_policy_error(m, r);
520
521 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
522
523 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
524 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
525 }
526
527 /* First check if we (the sender) can send to this name */
528 if (strv_isempty(destination_names)) {
529 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, true))
530 granted = true;
531 } else {
532 char **n;
533
534 STRV_FOREACH(n, destination_names) {
535 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, true)) {
536
537 /* If we made a receiver decision,
538 then remember which name's policy
539 we used, and to which unique ID it
540 mapped when we made the
541 decision. Then, let's pass this to
542 the kernel when sending the
543 message, so that it refuses the
544 operation should the name and
545 unique ID not map to each other
546 anymore. */
547
548 r = free_and_strdup(&m->destination_ptr, *n);
549 if (r < 0)
550 return r;
551
552 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
553 if (r < 0)
554 break;
555
556 granted = true;
557 break;
558 }
559 }
560 }
561
562 /* Then check if the recipient can receive from our name */
563 if (granted) {
564 if (sd_bus_message_is_signal(m, NULL, NULL)) {
565 /* If we forward a signal from dbus-1 to kdbus,
566 * we have no idea who the recipient is.
567 * Therefore, we cannot apply any dbus-1
568 * receiver policies that match on receiver
569 * credentials. We know sd-bus always sets
570 * KDBUS_MSG_SIGNAL, so the kernel applies
571 * receiver policies to the message. Therefore,
572 * skip policy checks in this case. */
573 return 0;
574 } else if (set_isempty(owned_names)) {
575 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member, true))
576 return 0;
577 } else {
578 Iterator i;
579 char *n;
580
581 SET_FOREACH(n, owned_names, i)
582 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member, true))
583 return 0;
584 }
585 }
586
587 /* Return an error back to the caller */
588 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
589 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
590
591 /* Return 1, indicating that the message shall not be processed any further */
592 return 1;
593 }
594
595 return 0;
596 }
597
598 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
599 Policy *policy;
600 int r;
601
602 assert(sp);
603
604 policy = shared_policy_acquire(sp);
605 r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
606 shared_policy_release(sp, policy);
607
608 return r;
609 }
610
611 static int process_hello(Proxy *p, sd_bus_message *m) {
612 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
613 bool is_hello;
614 int r;
615
616 assert(p);
617 assert(m);
618
619 /* As reaction to hello we need to respond with two messages:
620 * the callback reply and the NameAcquired for the unique
621 * name, since hello is otherwise obsolete on kdbus. */
622
623 is_hello =
624 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
625 streq_ptr(m->destination, "org.freedesktop.DBus");
626
627 if (!is_hello) {
628 if (p->got_hello)
629 return 0;
630
631 return log_error_errno(-EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
632 }
633
634 if (p->got_hello)
635 return log_error_errno(-EIO, "Got duplicate hello, aborting.");
636
637 p->got_hello = true;
638
639 if (!p->dest_bus->is_kernel)
640 return 0;
641
642 r = sd_bus_message_new_method_return(m, &n);
643 if (r < 0)
644 return log_error_errno(r, "Failed to generate HELLO reply: %m");
645
646 r = sd_bus_message_append(n, "s", p->dest_bus->unique_name);
647 if (r < 0)
648 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
649
650 r = bus_message_append_sender(n, "org.freedesktop.DBus");
651 if (r < 0)
652 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
653
654 r = bus_seal_synthetic_message(p->local_bus, n);
655 if (r < 0)
656 return log_error_errno(r, "Failed to seal HELLO reply: %m");
657
658 r = sd_bus_send(p->local_bus, n, NULL);
659 if (r < 0)
660 return log_error_errno(r, "Failed to send HELLO reply: %m");
661
662 n = sd_bus_message_unref(n);
663 r = sd_bus_message_new_signal(
664 p->local_bus,
665 &n,
666 "/org/freedesktop/DBus",
667 "org.freedesktop.DBus",
668 "NameAcquired");
669 if (r < 0)
670 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
671
672 r = sd_bus_message_append(n, "s", p->dest_bus->unique_name);
673 if (r < 0)
674 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
675
676 r = bus_message_append_sender(n, "org.freedesktop.DBus");
677 if (r < 0)
678 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
679
680 r = bus_seal_synthetic_message(p->local_bus, n);
681 if (r < 0)
682 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
683
684 r = sd_bus_send(p->local_bus, n, NULL);
685 if (r < 0)
686 return log_error_errno(r, "Failed to send NameAcquired message: %m");
687
688 return 1;
689 }
690
691 static int patch_sender(sd_bus *a, sd_bus_message *m) {
692 char **well_known = NULL;
693 sd_bus_creds *c;
694 int r;
695
696 assert(a);
697 assert(m);
698
699 if (!a->is_kernel)
700 return 0;
701
702 /* We will change the sender of messages from the bus driver
703 * so that they originate from the bus driver. This is a
704 * speciality originating from dbus1, where the bus driver did
705 * not have a unique id, but only the well-known name. */
706
707 c = sd_bus_message_get_creds(m);
708 if (!c)
709 return 0;
710
711 r = sd_bus_creds_get_well_known_names(c, &well_known);
712 if (r < 0)
713 return r;
714
715 if (strv_contains(well_known, "org.freedesktop.DBus"))
716 m->sender = "org.freedesktop.DBus";
717
718 return 0;
719 }
720
721 static int proxy_process_dest_to_local(Proxy *p) {
722 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
723 int r;
724
725 assert(p);
726
727 r = sd_bus_process(p->dest_bus, &m);
728 if (r < 0) {
729 /* treat 'connection reset by peer' as clean exit condition */
730 if (r != -ECONNRESET)
731 log_error_errno(r, "Failed to process destination bus: %m");
732 return r;
733 }
734
735 if (r == 0)
736 return 0;
737 if (!m)
738 return 1;
739
740 /* We officially got EOF, let's quit */
741 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
742 return -ECONNRESET;
743
744 r = synthesize_name_acquired(p->dest_bus, p->local_bus, m);
745 if (r < 0)
746 return log_error_errno(r, "Failed to synthesize message: %m");
747
748 patch_sender(p->dest_bus, m);
749
750 if (p->policy) {
751 r = process_policy(p->dest_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
752 if (r < 0)
753 return log_error_errno(r, "Failed to process policy: %m");
754 else if (r > 0)
755 return 1;
756 }
757
758 r = sd_bus_send(p->local_bus, m, NULL);
759 if (r < 0) {
760 if (r == -EPERM && m->reply_cookie > 0) {
761 /* If the peer tries to send a reply and it is rejected with EPERM
762 * by the kernel, we ignore the error. This catches cases where the
763 * original method-call didn't had EXPECT_REPLY set, but the proxy-peer
764 * still sends a reply. This is allowed in dbus1, but not in kdbus. We
765 * don't want to track reply-windows in the proxy, so we simply ignore
766 * EPERM for all replies. The only downside is, that callers are no
767 * longer notified if their replies are dropped. However, this is
768 * equivalent to the caller's timeout to expire, so this should be
769 * acceptable. Nobody sane sends replies without a matching method-call,
770 * so nobody should care. */
771 return 1;
772 } else {
773 if (r != -ECONNRESET)
774 log_error_errno(r, "Failed to send message to client: %m");
775 return r;
776 }
777 }
778
779 return 1;
780 }
781
782 static int proxy_process_local_to_dest(Proxy *p) {
783 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
784 int r;
785
786 assert(p);
787
788 r = sd_bus_process(p->local_bus, &m);
789 if (r < 0) {
790 /* treat 'connection reset by peer' as clean exit condition */
791 if (r != -ECONNRESET)
792 log_error_errno(r, "Failed to process local bus: %m");
793 return r;
794 }
795
796 if (r == 0)
797 return 0;
798 if (!m)
799 return 1;
800
801 /* We officially got EOF, let's quit */
802 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
803 return -ECONNRESET;
804
805 r = process_hello(p, m);
806 if (r < 0)
807 return log_error_errno(r, "Failed to process HELLO: %m");
808 else if (r > 0)
809 return 1;
810
811 r = bus_proxy_process_driver(p->dest_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
812 if (r < 0)
813 return log_error_errno(r, "Failed to process driver calls: %m");
814 else if (r > 0)
815 return 1;
816
817 for (;;) {
818 if (p->policy) {
819 r = process_policy(p->local_bus, p->dest_bus, m, p->policy, &p->local_creds, p->owned_names);
820 if (r < 0)
821 return log_error_errno(r, "Failed to process policy: %m");
822 else if (r > 0)
823 return 1;
824 }
825
826 r = sd_bus_send(p->dest_bus, m, NULL);
827 if (r < 0) {
828 if (r == -EREMCHG) {
829 /* The name database changed since the policy check, hence let's check again */
830 continue;
831 } else if (r == -EPERM && m->reply_cookie > 0) {
832 /* see above why EPERM is ignored for replies */
833 return 1;
834 } else {
835 if (r != -ECONNRESET)
836 log_error_errno(r, "Failed to send message to bus: %m");
837 return r;
838 }
839 }
840
841 break;
842 }
843
844 return 1;
845 }
846
847 int proxy_run(Proxy *p) {
848 int r;
849
850 assert(p);
851
852 for (;;) {
853 bool busy = false;
854
855 if (p->got_hello) {
856 /* Read messages from bus, to pass them on to our client */
857 r = proxy_process_dest_to_local(p);
858 if (r == -ECONNRESET)
859 return 0;
860 else if (r < 0)
861 return r;
862 else if (r > 0)
863 busy = true;
864 }
865
866 /* Read messages from our client, to pass them on to the bus */
867 r = proxy_process_local_to_dest(p);
868 if (r == -ECONNRESET)
869 return 0;
870 else if (r < 0)
871 return r;
872 else if (r > 0)
873 busy = true;
874
875 if (!busy) {
876 r = proxy_wait(p);
877 if (r < 0)
878 return r;
879 }
880 }
881
882 return 0;
883 }