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