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