]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/machine/machine-dbus.c
Merge pull request #9668 from poettering/open-parent
[thirdparty/systemd.git] / src / machine / machine-dbus.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include <errno.h>
4 #include <string.h>
5 #include <sys/mount.h>
6 #include <sys/wait.h>
7
8 /* When we include libgen.h because we need dirname() we immediately
9 * undefine basename() since libgen.h defines it as a macro to the POSIX
10 * version which is really broken. We prefer GNU basename(). */
11 #include <libgen.h>
12 #undef basename
13
14 #include "alloc-util.h"
15 #include "bus-common-errors.h"
16 #include "bus-internal.h"
17 #include "bus-label.h"
18 #include "bus-util.h"
19 #include "copy.h"
20 #include "env-util.h"
21 #include "fd-util.h"
22 #include "fileio.h"
23 #include "format-util.h"
24 #include "fs-util.h"
25 #include "in-addr-util.h"
26 #include "local-addresses.h"
27 #include "machine-dbus.h"
28 #include "machine.h"
29 #include "mkdir.h"
30 #include "os-util.h"
31 #include "path-util.h"
32 #include "process-util.h"
33 #include "signal-util.h"
34 #include "strv.h"
35 #include "terminal-util.h"
36 #include "user-util.h"
37
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
39 static BUS_DEFINE_PROPERTY_GET2(property_get_state, "s", Machine, machine_get_state, machine_state_to_string);
40
41 static int property_get_netif(
42 sd_bus *bus,
43 const char *path,
44 const char *interface,
45 const char *property,
46 sd_bus_message *reply,
47 void *userdata,
48 sd_bus_error *error) {
49
50 Machine *m = userdata;
51
52 assert(bus);
53 assert(reply);
54 assert(m);
55
56 assert_cc(sizeof(int) == sizeof(int32_t));
57
58 return sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
59 }
60
61 int bus_machine_method_terminate(sd_bus_message *message, void *userdata, sd_bus_error *error) {
62 Machine *m = userdata;
63 int r;
64
65 assert(message);
66 assert(m);
67
68 r = bus_verify_polkit_async(
69 message,
70 CAP_KILL,
71 "org.freedesktop.machine1.manage-machines",
72 NULL,
73 false,
74 UID_INVALID,
75 &m->manager->polkit_registry,
76 error);
77 if (r < 0)
78 return r;
79 if (r == 0)
80 return 1; /* Will call us back */
81
82 r = machine_stop(m);
83 if (r < 0)
84 return r;
85
86 return sd_bus_reply_method_return(message, NULL);
87 }
88
89 int bus_machine_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error) {
90 Machine *m = userdata;
91 const char *swho;
92 int32_t signo;
93 KillWho who;
94 int r;
95
96 assert(message);
97 assert(m);
98
99 r = sd_bus_message_read(message, "si", &swho, &signo);
100 if (r < 0)
101 return r;
102
103 if (isempty(swho))
104 who = KILL_ALL;
105 else {
106 who = kill_who_from_string(swho);
107 if (who < 0)
108 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
109 }
110
111 if (!SIGNAL_VALID(signo))
112 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
113
114 r = bus_verify_polkit_async(
115 message,
116 CAP_KILL,
117 "org.freedesktop.machine1.manage-machines",
118 NULL,
119 false,
120 UID_INVALID,
121 &m->manager->polkit_registry,
122 error);
123 if (r < 0)
124 return r;
125 if (r == 0)
126 return 1; /* Will call us back */
127
128 r = machine_kill(m, who, signo);
129 if (r < 0)
130 return r;
131
132 return sd_bus_reply_method_return(message, NULL);
133 }
134
135 int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd_bus_error *error) {
136 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
137 Machine *m = userdata;
138 int r;
139
140 assert(message);
141 assert(m);
142
143 r = sd_bus_message_new_method_return(message, &reply);
144 if (r < 0)
145 return r;
146
147 r = sd_bus_message_open_container(reply, 'a', "(iay)");
148 if (r < 0)
149 return r;
150
151 switch (m->class) {
152
153 case MACHINE_HOST: {
154 _cleanup_free_ struct local_address *addresses = NULL;
155 struct local_address *a;
156 int n, i;
157
158 n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
159 if (n < 0)
160 return n;
161
162 for (a = addresses, i = 0; i < n; a++, i++) {
163
164 r = sd_bus_message_open_container(reply, 'r', "iay");
165 if (r < 0)
166 return r;
167
168 r = sd_bus_message_append(reply, "i", addresses[i].family);
169 if (r < 0)
170 return r;
171
172 r = sd_bus_message_append_array(reply, 'y', &addresses[i].address, FAMILY_ADDRESS_SIZE(addresses[i].family));
173 if (r < 0)
174 return r;
175
176 r = sd_bus_message_close_container(reply);
177 if (r < 0)
178 return r;
179 }
180
181 break;
182 }
183
184 case MACHINE_CONTAINER: {
185 _cleanup_close_pair_ int pair[2] = { -1, -1 };
186 _cleanup_free_ char *us = NULL, *them = NULL;
187 _cleanup_close_ int netns_fd = -1;
188 const char *p;
189 pid_t child;
190
191 r = readlink_malloc("/proc/self/ns/net", &us);
192 if (r < 0)
193 return r;
194
195 p = procfs_file_alloca(m->leader, "ns/net");
196 r = readlink_malloc(p, &them);
197 if (r < 0)
198 return r;
199
200 if (streq(us, them))
201 return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
202
203 r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL, NULL);
204 if (r < 0)
205 return r;
206
207 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
208 return -errno;
209
210 r = safe_fork("(sd-addr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
211 if (r < 0)
212 return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
213 if (r == 0) {
214 _cleanup_free_ struct local_address *addresses = NULL;
215 struct local_address *a;
216 int i, n;
217
218 pair[0] = safe_close(pair[0]);
219
220 r = namespace_enter(-1, -1, netns_fd, -1, -1);
221 if (r < 0)
222 _exit(EXIT_FAILURE);
223
224 n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
225 if (n < 0)
226 _exit(EXIT_FAILURE);
227
228 for (a = addresses, i = 0; i < n; a++, i++) {
229 struct iovec iov[2] = {
230 { .iov_base = &a->family, .iov_len = sizeof(a->family) },
231 { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
232 };
233
234 r = writev(pair[1], iov, 2);
235 if (r < 0)
236 _exit(EXIT_FAILURE);
237 }
238
239 pair[1] = safe_close(pair[1]);
240
241 _exit(EXIT_SUCCESS);
242 }
243
244 pair[1] = safe_close(pair[1]);
245
246 for (;;) {
247 int family;
248 ssize_t n;
249 union in_addr_union in_addr;
250 struct iovec iov[2];
251 struct msghdr mh = {
252 .msg_iov = iov,
253 .msg_iovlen = 2,
254 };
255
256 iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
257 iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
258
259 n = recvmsg(pair[0], &mh, 0);
260 if (n < 0)
261 return -errno;
262 if ((size_t) n < sizeof(family))
263 break;
264
265 r = sd_bus_message_open_container(reply, 'r', "iay");
266 if (r < 0)
267 return r;
268
269 r = sd_bus_message_append(reply, "i", family);
270 if (r < 0)
271 return r;
272
273 switch (family) {
274
275 case AF_INET:
276 if (n != sizeof(struct in_addr) + sizeof(family))
277 return -EIO;
278
279 r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in));
280 break;
281
282 case AF_INET6:
283 if (n != sizeof(struct in6_addr) + sizeof(family))
284 return -EIO;
285
286 r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6));
287 break;
288 }
289 if (r < 0)
290 return r;
291
292 r = sd_bus_message_close_container(reply);
293 if (r < 0)
294 return r;
295 }
296
297 r = wait_for_terminate_and_check("(sd-addr)", child, 0);
298 if (r < 0)
299 return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
300 if (r != EXIT_SUCCESS)
301 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
302 break;
303 }
304
305 default:
306 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
307 }
308
309 r = sd_bus_message_close_container(reply);
310 if (r < 0)
311 return r;
312
313 return sd_bus_send(NULL, reply, NULL);
314 }
315
316 #define EXIT_NOT_FOUND 2
317
318 int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
319 _cleanup_strv_free_ char **l = NULL;
320 Machine *m = userdata;
321 int r;
322
323 assert(message);
324 assert(m);
325
326 switch (m->class) {
327
328 case MACHINE_HOST:
329 r = load_os_release_pairs(NULL, &l);
330 if (r < 0)
331 return r;
332
333 break;
334
335 case MACHINE_CONTAINER: {
336 _cleanup_close_ int mntns_fd = -1, root_fd = -1;
337 _cleanup_close_pair_ int pair[2] = { -1, -1 };
338 _cleanup_fclose_ FILE *f = NULL;
339 pid_t child;
340
341 r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
342 if (r < 0)
343 return r;
344
345 if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
346 return -errno;
347
348 r = safe_fork("(sd-osrel)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
349 if (r < 0)
350 return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
351 if (r == 0) {
352 int fd = -1;
353
354 pair[0] = safe_close(pair[0]);
355
356 r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
357 if (r < 0)
358 _exit(EXIT_FAILURE);
359
360 r = open_os_release(NULL, NULL, &fd);
361 if (r == -ENOENT)
362 _exit(EXIT_NOT_FOUND);
363 if (r < 0)
364 _exit(EXIT_FAILURE);
365
366 r = copy_bytes(fd, pair[1], (uint64_t) -1, 0);
367 if (r < 0)
368 _exit(EXIT_FAILURE);
369
370 _exit(EXIT_SUCCESS);
371 }
372
373 pair[1] = safe_close(pair[1]);
374
375 f = fdopen(pair[0], "re");
376 if (!f)
377 return -errno;
378
379 pair[0] = -1;
380
381 r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
382 if (r < 0)
383 return r;
384
385 r = wait_for_terminate_and_check("(sd-osrel)", child, 0);
386 if (r < 0)
387 return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
388 if (r == EXIT_NOT_FOUND)
389 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
390 if (r != EXIT_SUCCESS)
391 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
392
393 break;
394 }
395
396 default:
397 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
398 }
399
400 return bus_reply_pair_array(message, l);
401 }
402
403 int bus_machine_method_open_pty(sd_bus_message *message, void *userdata, sd_bus_error *error) {
404 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
405 _cleanup_free_ char *pty_name = NULL;
406 _cleanup_close_ int master = -1;
407 Machine *m = userdata;
408 int r;
409
410 assert(message);
411 assert(m);
412
413 r = bus_verify_polkit_async(
414 message,
415 CAP_SYS_ADMIN,
416 m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-open-pty" : "org.freedesktop.machine1.open-pty",
417 NULL,
418 false,
419 UID_INVALID,
420 &m->manager->polkit_registry,
421 error);
422 if (r < 0)
423 return r;
424 if (r == 0)
425 return 1; /* Will call us back */
426
427 master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
428 if (master < 0)
429 return master;
430
431 r = ptsname_namespace(master, &pty_name);
432 if (r < 0)
433 return r;
434
435 r = sd_bus_message_new_method_return(message, &reply);
436 if (r < 0)
437 return r;
438
439 r = sd_bus_message_append(reply, "hs", master, pty_name);
440 if (r < 0)
441 return r;
442
443 return sd_bus_send(NULL, reply, NULL);
444 }
445
446 static int container_bus_new(Machine *m, sd_bus_error *error, sd_bus **ret) {
447 int r;
448
449 assert(m);
450 assert(ret);
451
452 switch (m->class) {
453
454 case MACHINE_HOST:
455 *ret = NULL;
456 break;
457
458 case MACHINE_CONTAINER: {
459 _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
460 char *address;
461
462 r = sd_bus_new(&bus);
463 if (r < 0)
464 return r;
465
466 if (asprintf(&address, "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI, m->leader) < 0)
467 return -ENOMEM;
468
469 bus->address = address;
470 bus->bus_client = true;
471 bus->trusted = false;
472 bus->is_system = true;
473
474 r = sd_bus_start(bus);
475 if (r == -ENOENT)
476 return sd_bus_error_set_errnof(error, r, "There is no system bus in container %s.", m->name);
477 if (r < 0)
478 return r;
479
480 *ret = TAKE_PTR(bus);
481 break;
482 }
483
484 default:
485 return -EOPNOTSUPP;
486 }
487
488 return 0;
489 }
490
491 int bus_machine_method_open_login(sd_bus_message *message, void *userdata, sd_bus_error *error) {
492 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
493 _cleanup_free_ char *pty_name = NULL;
494 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
495 _cleanup_close_ int master = -1;
496 sd_bus *container_bus = NULL;
497 Machine *m = userdata;
498 const char *p, *getty;
499 int r;
500
501 assert(message);
502 assert(m);
503
504 r = bus_verify_polkit_async(
505 message,
506 CAP_SYS_ADMIN,
507 m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-login" : "org.freedesktop.machine1.login",
508 NULL,
509 false,
510 UID_INVALID,
511 &m->manager->polkit_registry,
512 error);
513 if (r < 0)
514 return r;
515 if (r == 0)
516 return 1; /* Will call us back */
517
518 master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
519 if (master < 0)
520 return master;
521
522 r = ptsname_namespace(master, &pty_name);
523 if (r < 0)
524 return r;
525
526 p = path_startswith(pty_name, "/dev/pts/");
527 if (!p)
528 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
529
530 r = container_bus_new(m, error, &allocated_bus);
531 if (r < 0)
532 return r;
533
534 container_bus = allocated_bus ?: m->manager->bus;
535
536 getty = strjoina("container-getty@", p, ".service");
537
538 r = sd_bus_call_method(
539 container_bus,
540 "org.freedesktop.systemd1",
541 "/org/freedesktop/systemd1",
542 "org.freedesktop.systemd1.Manager",
543 "StartUnit",
544 error, NULL,
545 "ss", getty, "replace");
546 if (r < 0)
547 return r;
548
549 r = sd_bus_message_new_method_return(message, &reply);
550 if (r < 0)
551 return r;
552
553 r = sd_bus_message_append(reply, "hs", master, pty_name);
554 if (r < 0)
555 return r;
556
557 return sd_bus_send(NULL, reply, NULL);
558 }
559
560 int bus_machine_method_open_shell(sd_bus_message *message, void *userdata, sd_bus_error *error) {
561 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL, *tm = NULL;
562 _cleanup_free_ char *pty_name = NULL;
563 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *allocated_bus = NULL;
564 sd_bus *container_bus = NULL;
565 _cleanup_close_ int master = -1, slave = -1;
566 _cleanup_strv_free_ char **env = NULL, **args_wire = NULL, **args = NULL;
567 Machine *m = userdata;
568 const char *p, *unit, *user, *path, *description, *utmp_id;
569 int r;
570
571 assert(message);
572 assert(m);
573
574 r = sd_bus_message_read(message, "ss", &user, &path);
575 if (r < 0)
576 return r;
577 user = empty_to_null(user);
578 r = sd_bus_message_read_strv(message, &args_wire);
579 if (r < 0)
580 return r;
581 if (isempty(path)) {
582 path = "/bin/sh";
583
584 args = new0(char*, 3 + 1);
585 if (!args)
586 return -ENOMEM;
587 args[0] = strdup("sh");
588 if (!args[0])
589 return -ENOMEM;
590 args[1] = strdup("-c");
591 if (!args[1])
592 return -ENOMEM;
593 r = asprintf(&args[2],
594 "shell=$(getent passwd %s 2>/dev/null | { IFS=: read _ _ _ _ _ _ x; echo \"$x\"; })\n"\
595 "exec \"${shell:-/bin/sh}\" -l", /* -l is means --login */
596 isempty(user) ? "root" : user);
597 if (r < 0) {
598 args[2] = NULL;
599 return -ENOMEM;
600 }
601 } else {
602 if (!path_is_absolute(path))
603 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path '%s' is not absolute", path);
604 args = TAKE_PTR(args_wire);
605 if (strv_isempty(args)) {
606 args = strv_free(args);
607
608 args = strv_new(path, NULL);
609 if (!args)
610 return -ENOMEM;
611 }
612 }
613
614 r = sd_bus_message_read_strv(message, &env);
615 if (r < 0)
616 return r;
617 if (!strv_env_is_valid(env))
618 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment assignments");
619
620 r = bus_verify_polkit_async(
621 message,
622 CAP_SYS_ADMIN,
623 m->class == MACHINE_HOST ? "org.freedesktop.machine1.host-shell" : "org.freedesktop.machine1.shell",
624 NULL,
625 false,
626 UID_INVALID,
627 &m->manager->polkit_registry,
628 error);
629 if (r < 0)
630 return r;
631 if (r == 0)
632 return 1; /* Will call us back */
633
634 master = machine_openpt(m, O_RDWR|O_NOCTTY|O_CLOEXEC);
635 if (master < 0)
636 return master;
637
638 r = ptsname_namespace(master, &pty_name);
639 if (r < 0)
640 return r;
641
642 p = path_startswith(pty_name, "/dev/pts/");
643 assert(p);
644
645 slave = machine_open_terminal(m, pty_name, O_RDWR|O_NOCTTY|O_CLOEXEC);
646 if (slave < 0)
647 return slave;
648
649 utmp_id = path_startswith(pty_name, "/dev/");
650 assert(utmp_id);
651
652 r = container_bus_new(m, error, &allocated_bus);
653 if (r < 0)
654 return r;
655
656 container_bus = allocated_bus ?: m->manager->bus;
657
658 r = sd_bus_message_new_method_call(
659 container_bus,
660 &tm,
661 "org.freedesktop.systemd1",
662 "/org/freedesktop/systemd1",
663 "org.freedesktop.systemd1.Manager",
664 "StartTransientUnit");
665 if (r < 0)
666 return r;
667
668 /* Name and mode */
669 unit = strjoina("container-shell@", p, ".service");
670 r = sd_bus_message_append(tm, "ss", unit, "fail");
671 if (r < 0)
672 return r;
673
674 /* Properties */
675 r = sd_bus_message_open_container(tm, 'a', "(sv)");
676 if (r < 0)
677 return r;
678
679 description = strjoina("Shell for User ", isempty(user) ? "root" : user);
680 r = sd_bus_message_append(tm,
681 "(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)(sv)",
682 "Description", "s", description,
683 "StandardInputFileDescriptor", "h", slave,
684 "StandardOutputFileDescriptor", "h", slave,
685 "StandardErrorFileDescriptor", "h", slave,
686 "SendSIGHUP", "b", true,
687 "IgnoreSIGPIPE", "b", false,
688 "KillMode", "s", "mixed",
689 "TTYReset", "b", true,
690 "UtmpIdentifier", "s", utmp_id,
691 "UtmpMode", "s", "user",
692 "PAMName", "s", "login",
693 "WorkingDirectory", "s", "-~");
694 if (r < 0)
695 return r;
696
697 r = sd_bus_message_append(tm, "(sv)", "User", "s", isempty(user) ? "root" : user);
698 if (r < 0)
699 return r;
700
701 if (!strv_isempty(env)) {
702 r = sd_bus_message_open_container(tm, 'r', "sv");
703 if (r < 0)
704 return r;
705
706 r = sd_bus_message_append(tm, "s", "Environment");
707 if (r < 0)
708 return r;
709
710 r = sd_bus_message_open_container(tm, 'v', "as");
711 if (r < 0)
712 return r;
713
714 r = sd_bus_message_append_strv(tm, env);
715 if (r < 0)
716 return r;
717
718 r = sd_bus_message_close_container(tm);
719 if (r < 0)
720 return r;
721
722 r = sd_bus_message_close_container(tm);
723 if (r < 0)
724 return r;
725 }
726
727 /* Exec container */
728 r = sd_bus_message_open_container(tm, 'r', "sv");
729 if (r < 0)
730 return r;
731
732 r = sd_bus_message_append(tm, "s", "ExecStart");
733 if (r < 0)
734 return r;
735
736 r = sd_bus_message_open_container(tm, 'v', "a(sasb)");
737 if (r < 0)
738 return r;
739
740 r = sd_bus_message_open_container(tm, 'a', "(sasb)");
741 if (r < 0)
742 return r;
743
744 r = sd_bus_message_open_container(tm, 'r', "sasb");
745 if (r < 0)
746 return r;
747
748 r = sd_bus_message_append(tm, "s", path);
749 if (r < 0)
750 return r;
751
752 r = sd_bus_message_append_strv(tm, args);
753 if (r < 0)
754 return r;
755
756 r = sd_bus_message_append(tm, "b", true);
757 if (r < 0)
758 return r;
759
760 r = sd_bus_message_close_container(tm);
761 if (r < 0)
762 return r;
763
764 r = sd_bus_message_close_container(tm);
765 if (r < 0)
766 return r;
767
768 r = sd_bus_message_close_container(tm);
769 if (r < 0)
770 return r;
771
772 r = sd_bus_message_close_container(tm);
773 if (r < 0)
774 return r;
775
776 r = sd_bus_message_close_container(tm);
777 if (r < 0)
778 return r;
779
780 /* Auxiliary units */
781 r = sd_bus_message_append(tm, "a(sa(sv))", 0);
782 if (r < 0)
783 return r;
784
785 r = sd_bus_call(container_bus, tm, 0, error, NULL);
786 if (r < 0)
787 return r;
788
789 slave = safe_close(slave);
790
791 r = sd_bus_message_new_method_return(message, &reply);
792 if (r < 0)
793 return r;
794
795 r = sd_bus_message_append(reply, "hs", master, pty_name);
796 if (r < 0)
797 return r;
798
799 return sd_bus_send(NULL, reply, NULL);
800 }
801
802 int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bus_error *error) {
803 _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
804 char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
805 bool mount_slave_created = false, mount_slave_mounted = false,
806 mount_tmp_created = false, mount_tmp_mounted = false,
807 mount_outside_created = false, mount_outside_mounted = false;
808 _cleanup_free_ char *chased_src = NULL;
809 int read_only, make_file_or_directory;
810 const char *dest, *src;
811 Machine *m = userdata;
812 struct stat st;
813 pid_t child;
814 uid_t uid;
815 int r;
816
817 assert(message);
818 assert(m);
819
820 if (m->class != MACHINE_CONTAINER)
821 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
822
823 r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_file_or_directory);
824 if (r < 0)
825 return r;
826
827 if (!path_is_absolute(src) || !path_is_normalized(src))
828 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
829
830 if (isempty(dest))
831 dest = src;
832 else if (!path_is_absolute(dest) || !path_is_normalized(dest))
833 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
834
835 r = bus_verify_polkit_async(
836 message,
837 CAP_SYS_ADMIN,
838 "org.freedesktop.machine1.manage-machines",
839 NULL,
840 false,
841 UID_INVALID,
842 &m->manager->polkit_registry,
843 error);
844 if (r < 0)
845 return r;
846 if (r == 0)
847 return 1; /* Will call us back */
848
849 r = machine_get_uid_shift(m, &uid);
850 if (r < 0)
851 return r;
852 if (uid != 0)
853 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Can't bind mount on container with user namespacing applied.");
854
855 /* One day, when bind mounting /proc/self/fd/n works across
856 * namespace boundaries we should rework this logic to make
857 * use of it... */
858
859 p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
860 if (laccess(p, F_OK) < 0)
861 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
862
863 r = chase_symlinks(src, NULL, CHASE_TRAIL_SLASH, &chased_src);
864 if (r < 0)
865 return sd_bus_error_set_errnof(error, r, "Failed to resolve source path: %m");
866
867 if (lstat(chased_src, &st) < 0)
868 return sd_bus_error_set_errnof(error, errno, "Failed to stat() source path: %m");
869 if (S_ISLNK(st.st_mode)) /* This shouldn't really happen, given that we just chased the symlinks above, but let's better be safe… */
870 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Source directory can't be a symbolic link");
871
872 /* Our goal is to install a new bind mount into the container,
873 possibly read-only. This is irritatingly complex
874 unfortunately, currently.
875
876 First, we start by creating a private playground in /tmp,
877 that we can mount MS_SLAVE. (Which is necessary, since
878 MS_MOVE cannot be applied to mounts with MS_SHARED parent
879 mounts.) */
880
881 if (!mkdtemp(mount_slave))
882 return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
883
884 mount_slave_created = true;
885
886 if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
887 r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
888 goto finish;
889 }
890
891 mount_slave_mounted = true;
892
893 if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
894 r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
895 goto finish;
896 }
897
898 /* Second, we mount the source file or directory to a directory inside of our MS_SLAVE playground. */
899 mount_tmp = strjoina(mount_slave, "/mount");
900 if (S_ISDIR(st.st_mode))
901 r = mkdir_errno_wrapper(mount_tmp, 0700);
902 else
903 r = touch(mount_tmp);
904 if (r < 0) {
905 sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
906 goto finish;
907 }
908
909 mount_tmp_created = true;
910
911 if (mount(chased_src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
912 r = sd_bus_error_set_errnof(error, errno, "Failed to mount %s: %m", chased_src);
913 goto finish;
914 }
915
916 mount_tmp_mounted = true;
917
918 /* Third, we remount the new bind mount read-only if requested. */
919 if (read_only)
920 if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
921 r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
922 goto finish;
923 }
924
925 /* Fourth, we move the new bind mount into the propagation directory. This way it will appear there read-only
926 * right-away. */
927
928 mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
929 if (S_ISDIR(st.st_mode))
930 r = mkdtemp(mount_outside) ? 0 : -errno;
931 else {
932 r = mkostemp_safe(mount_outside);
933 safe_close(r);
934 }
935 if (r < 0) {
936 sd_bus_error_set_errnof(error, errno, "Cannot create propagation file or directory %s: %m", mount_outside);
937 goto finish;
938 }
939
940 mount_outside_created = true;
941
942 if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
943 r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
944 goto finish;
945 }
946
947 mount_outside_mounted = true;
948 mount_tmp_mounted = false;
949
950 if (S_ISDIR(st.st_mode))
951 (void) rmdir(mount_tmp);
952 else
953 (void) unlink(mount_tmp);
954 mount_tmp_created = false;
955
956 (void) umount(mount_slave);
957 mount_slave_mounted = false;
958
959 (void) rmdir(mount_slave);
960 mount_slave_created = false;
961
962 if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
963 r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
964 goto finish;
965 }
966
967 r = safe_fork("(sd-bindmnt)", FORK_RESET_SIGNALS, &child);
968 if (r < 0) {
969 sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
970 goto finish;
971 }
972 if (r == 0) {
973 const char *mount_inside;
974 int mntfd;
975 const char *q;
976
977 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
978
979 q = procfs_file_alloca(m->leader, "ns/mnt");
980 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
981 if (mntfd < 0) {
982 r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
983 goto child_fail;
984 }
985
986 if (setns(mntfd, CLONE_NEWNS) < 0) {
987 r = log_error_errno(errno, "Failed to join namespace of leader: %m");
988 goto child_fail;
989 }
990
991 if (make_file_or_directory) {
992 if (S_ISDIR(st.st_mode))
993 (void) mkdir_p(dest, 0755);
994 else {
995 (void) mkdir_parents(dest, 0755);
996 safe_close(open(dest, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC|O_NOCTTY, 0600));
997 }
998 }
999
1000 /* Fifth, move the mount to the right place inside */
1001 mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
1002 if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
1003 r = log_error_errno(errno, "Failed to mount: %m");
1004 goto child_fail;
1005 }
1006
1007 _exit(EXIT_SUCCESS);
1008
1009 child_fail:
1010 (void) write(errno_pipe_fd[1], &r, sizeof(r));
1011 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
1012
1013 _exit(EXIT_FAILURE);
1014 }
1015
1016 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
1017
1018 r = wait_for_terminate_and_check("(sd-bindmnt)", child, 0);
1019 if (r < 0) {
1020 r = sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
1021 goto finish;
1022 }
1023 if (r != EXIT_SUCCESS) {
1024 if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
1025 r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
1026 else
1027 r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child failed.");
1028 goto finish;
1029 }
1030
1031 r = sd_bus_reply_method_return(message, NULL);
1032
1033 finish:
1034 if (mount_outside_mounted)
1035 (void) umount(mount_outside);
1036 if (mount_outside_created) {
1037 if (S_ISDIR(st.st_mode))
1038 (void) rmdir(mount_outside);
1039 else
1040 (void) unlink(mount_outside);
1041 }
1042
1043 if (mount_tmp_mounted)
1044 (void) umount(mount_tmp);
1045 if (mount_tmp_created) {
1046 if (S_ISDIR(st.st_mode))
1047 (void) rmdir(mount_tmp);
1048 else
1049 (void) unlink(mount_tmp);
1050 }
1051
1052 if (mount_slave_mounted)
1053 (void) umount(mount_slave);
1054 if (mount_slave_created)
1055 (void) rmdir(mount_slave);
1056
1057 return r;
1058 }
1059
1060 int bus_machine_method_copy(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1061 const char *src, *dest, *host_path, *container_path, *host_basename, *container_basename, *container_dirname;
1062 _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
1063 CopyFlags copy_flags = COPY_REFLINK|COPY_MERGE;
1064 _cleanup_close_ int hostfd = -1;
1065 Machine *m = userdata;
1066 bool copy_from;
1067 pid_t child;
1068 uid_t uid_shift;
1069 char *t;
1070 int r;
1071
1072 assert(message);
1073 assert(m);
1074
1075 if (m->manager->n_operations >= OPERATIONS_MAX)
1076 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
1077
1078 if (m->class != MACHINE_CONTAINER)
1079 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
1080
1081 r = sd_bus_message_read(message, "ss", &src, &dest);
1082 if (r < 0)
1083 return r;
1084
1085 if (!path_is_absolute(src))
1086 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute.");
1087
1088 if (isempty(dest))
1089 dest = src;
1090 else if (!path_is_absolute(dest))
1091 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute.");
1092
1093 r = bus_verify_polkit_async(
1094 message,
1095 CAP_SYS_ADMIN,
1096 "org.freedesktop.machine1.manage-machines",
1097 NULL,
1098 false,
1099 UID_INVALID,
1100 &m->manager->polkit_registry,
1101 error);
1102 if (r < 0)
1103 return r;
1104 if (r == 0)
1105 return 1; /* Will call us back */
1106
1107 r = machine_get_uid_shift(m, &uid_shift);
1108 if (r < 0)
1109 return r;
1110
1111 copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
1112
1113 if (copy_from) {
1114 container_path = src;
1115 host_path = dest;
1116 } else {
1117 host_path = src;
1118 container_path = dest;
1119 }
1120
1121 host_basename = basename(host_path);
1122
1123 container_basename = basename(container_path);
1124 t = strdupa(container_path);
1125 container_dirname = dirname(t);
1126
1127 hostfd = open_parent(host_path, O_CLOEXEC, 0);
1128 if (hostfd < 0)
1129 return sd_bus_error_set_errnof(error, hostfd, "Failed to open host directory %s: %m", host_path);
1130
1131 if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
1132 return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
1133
1134 r = safe_fork("(sd-copy)", FORK_RESET_SIGNALS, &child);
1135 if (r < 0)
1136 return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
1137 if (r == 0) {
1138 int containerfd;
1139 const char *q;
1140 int mntfd;
1141
1142 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
1143
1144 q = procfs_file_alloca(m->leader, "ns/mnt");
1145 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
1146 if (mntfd < 0) {
1147 r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
1148 goto child_fail;
1149 }
1150
1151 if (setns(mntfd, CLONE_NEWNS) < 0) {
1152 r = log_error_errno(errno, "Failed to join namespace of leader: %m");
1153 goto child_fail;
1154 }
1155
1156 containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
1157 if (containerfd < 0) {
1158 r = log_error_errno(errno, "Failed to open destination directory: %m");
1159 goto child_fail;
1160 }
1161
1162 /* Run the actual copy operation. Note that when an UID shift is set we'll either clamp the UID/GID to
1163 * 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy
1164 * the UID/GIDs as they are. */
1165 if (copy_from)
1166 r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags);
1167 else
1168 r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags);
1169
1170 hostfd = safe_close(hostfd);
1171 containerfd = safe_close(containerfd);
1172
1173 if (r < 0) {
1174 r = log_error_errno(r, "Failed to copy tree: %m");
1175 goto child_fail;
1176 }
1177
1178 _exit(EXIT_SUCCESS);
1179
1180 child_fail:
1181 (void) write(errno_pipe_fd[1], &r, sizeof(r));
1182 _exit(EXIT_FAILURE);
1183 }
1184
1185 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
1186
1187 /* Copying might take a while, hence install a watch on the child, and return */
1188
1189 r = operation_new(m->manager, m, child, message, errno_pipe_fd[0], NULL);
1190 if (r < 0) {
1191 (void) sigkill_wait(child);
1192 return r;
1193 }
1194 errno_pipe_fd[0] = -1;
1195
1196 return 1;
1197 }
1198
1199 int bus_machine_method_open_root_directory(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1200 _cleanup_close_ int fd = -1;
1201 Machine *m = userdata;
1202 int r;
1203
1204 assert(message);
1205 assert(m);
1206
1207 r = bus_verify_polkit_async(
1208 message,
1209 CAP_SYS_ADMIN,
1210 "org.freedesktop.machine1.manage-machines",
1211 NULL,
1212 false,
1213 UID_INVALID,
1214 &m->manager->polkit_registry,
1215 error);
1216 if (r < 0)
1217 return r;
1218 if (r == 0)
1219 return 1; /* Will call us back */
1220
1221 switch (m->class) {
1222
1223 case MACHINE_HOST:
1224 fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
1225 if (fd < 0)
1226 return -errno;
1227
1228 break;
1229
1230 case MACHINE_CONTAINER: {
1231 _cleanup_close_ int mntns_fd = -1, root_fd = -1;
1232 _cleanup_close_pair_ int pair[2] = { -1, -1 };
1233 pid_t child;
1234
1235 r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
1236 if (r < 0)
1237 return r;
1238
1239 if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
1240 return -errno;
1241
1242 r = safe_fork("(sd-openroot)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
1243 if (r < 0)
1244 return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
1245 if (r == 0) {
1246 _cleanup_close_ int dfd = -1;
1247
1248 pair[0] = safe_close(pair[0]);
1249
1250 r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
1251 if (r < 0)
1252 _exit(EXIT_FAILURE);
1253
1254 dfd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
1255 if (dfd < 0)
1256 _exit(EXIT_FAILURE);
1257
1258 r = send_one_fd(pair[1], dfd, 0);
1259 dfd = safe_close(dfd);
1260 if (r < 0)
1261 _exit(EXIT_FAILURE);
1262
1263 _exit(EXIT_SUCCESS);
1264 }
1265
1266 pair[1] = safe_close(pair[1]);
1267
1268 r = wait_for_terminate_and_check("(sd-openroot)", child, 0);
1269 if (r < 0)
1270 return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
1271 if (r != EXIT_SUCCESS)
1272 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
1273
1274 fd = receive_one_fd(pair[0], MSG_DONTWAIT);
1275 if (fd < 0)
1276 return fd;
1277
1278 break;
1279 }
1280
1281 default:
1282 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening the root directory is only supported on container machines.");
1283 }
1284
1285 return sd_bus_reply_method_return(message, "h", fd);
1286 }
1287
1288 int bus_machine_method_get_uid_shift(sd_bus_message *message, void *userdata, sd_bus_error *error) {
1289 Machine *m = userdata;
1290 uid_t shift = 0;
1291 int r;
1292
1293 assert(message);
1294 assert(m);
1295
1296 /* You wonder why this is a method and not a property? Well, properties are not supposed to return errors, but
1297 * we kinda have to for this. */
1298
1299 if (m->class == MACHINE_HOST)
1300 return sd_bus_reply_method_return(message, "u", UINT32_C(0));
1301
1302 if (m->class != MACHINE_CONTAINER)
1303 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "UID/GID shift may only be determined for container machines.");
1304
1305 r = machine_get_uid_shift(m, &shift);
1306 if (r == -ENXIO)
1307 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Machine %s uses a complex UID/GID mapping, cannot determine shift", m->name);
1308 if (r < 0)
1309 return r;
1310
1311 return sd_bus_reply_method_return(message, "u", (uint32_t) shift);
1312 }
1313
1314 const sd_bus_vtable machine_vtable[] = {
1315 SD_BUS_VTABLE_START(0),
1316 SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
1317 SD_BUS_PROPERTY("Id", "ay", bus_property_get_id128, offsetof(Machine, id), SD_BUS_VTABLE_PROPERTY_CONST),
1318 BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
1319 SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
1320 SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
1321 SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
1322 SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
1323 SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
1324 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
1325 SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
1326 SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
1327 SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
1328 SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
1329 SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
1330 SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
1331 SD_BUS_METHOD("GetUIDShift", NULL, "u", bus_machine_method_get_uid_shift, SD_BUS_VTABLE_UNPRIVILEGED),
1332 SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, SD_BUS_VTABLE_UNPRIVILEGED),
1333 SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED),
1334 SD_BUS_METHOD("OpenShell", "ssasas", "hs", bus_machine_method_open_shell, SD_BUS_VTABLE_UNPRIVILEGED),
1335 SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
1336 SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
1337 SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
1338 SD_BUS_METHOD("OpenRootDirectory", NULL, "h", bus_machine_method_open_root_directory, SD_BUS_VTABLE_UNPRIVILEGED),
1339 SD_BUS_VTABLE_END
1340 };
1341
1342 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
1343 Manager *m = userdata;
1344 Machine *machine;
1345 int r;
1346
1347 assert(bus);
1348 assert(path);
1349 assert(interface);
1350 assert(found);
1351 assert(m);
1352
1353 if (streq(path, "/org/freedesktop/machine1/machine/self")) {
1354 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
1355 sd_bus_message *message;
1356 pid_t pid;
1357
1358 message = sd_bus_get_current_message(bus);
1359 if (!message)
1360 return 0;
1361
1362 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
1363 if (r < 0)
1364 return r;
1365
1366 r = sd_bus_creds_get_pid(creds, &pid);
1367 if (r < 0)
1368 return r;
1369
1370 r = manager_get_machine_by_pid(m, pid, &machine);
1371 if (r <= 0)
1372 return 0;
1373 } else {
1374 _cleanup_free_ char *e = NULL;
1375 const char *p;
1376
1377 p = startswith(path, "/org/freedesktop/machine1/machine/");
1378 if (!p)
1379 return 0;
1380
1381 e = bus_label_unescape(p);
1382 if (!e)
1383 return -ENOMEM;
1384
1385 machine = hashmap_get(m->machines, e);
1386 if (!machine)
1387 return 0;
1388 }
1389
1390 *found = machine;
1391 return 1;
1392 }
1393
1394 char *machine_bus_path(Machine *m) {
1395 _cleanup_free_ char *e = NULL;
1396
1397 assert(m);
1398
1399 e = bus_label_escape(m->name);
1400 if (!e)
1401 return NULL;
1402
1403 return strappend("/org/freedesktop/machine1/machine/", e);
1404 }
1405
1406 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
1407 _cleanup_strv_free_ char **l = NULL;
1408 Machine *machine = NULL;
1409 Manager *m = userdata;
1410 Iterator i;
1411 int r;
1412
1413 assert(bus);
1414 assert(path);
1415 assert(nodes);
1416
1417 HASHMAP_FOREACH(machine, m->machines, i) {
1418 char *p;
1419
1420 p = machine_bus_path(machine);
1421 if (!p)
1422 return -ENOMEM;
1423
1424 r = strv_consume(&l, p);
1425 if (r < 0)
1426 return r;
1427 }
1428
1429 *nodes = TAKE_PTR(l);
1430
1431 return 1;
1432 }
1433
1434 int machine_send_signal(Machine *m, bool new_machine) {
1435 _cleanup_free_ char *p = NULL;
1436
1437 assert(m);
1438
1439 p = machine_bus_path(m);
1440 if (!p)
1441 return -ENOMEM;
1442
1443 return sd_bus_emit_signal(
1444 m->manager->bus,
1445 "/org/freedesktop/machine1",
1446 "org.freedesktop.machine1.Manager",
1447 new_machine ? "MachineNew" : "MachineRemoved",
1448 "so", m->name, p);
1449 }
1450
1451 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
1452 _cleanup_(sd_bus_message_unrefp) sd_bus_message *c = NULL;
1453 _cleanup_free_ char *p = NULL;
1454
1455 assert(m);
1456
1457 if (!m->create_message)
1458 return 0;
1459
1460 c = TAKE_PTR(m->create_message);
1461
1462 if (error)
1463 return sd_bus_reply_method_error(c, error);
1464
1465 /* Update the machine state file before we notify the client
1466 * about the result. */
1467 machine_save(m);
1468
1469 p = machine_bus_path(m);
1470 if (!p)
1471 return -ENOMEM;
1472
1473 return sd_bus_reply_method_return(c, "o", p);
1474 }