chiark / gitweb /
machinectl: issue all bus commands while allowing interactive auth
[elogind.git] / src / machine / machine-dbus.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2011 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <string.h>
24 #include <arpa/inet.h>
25 #include <sys/mount.h>
26
27 /* When we include libgen.h because we need dirname() we immediately
28  * undefine basename() since libgen.h defines it as a macro to the XDG
29  * version which is really broken. */
30 #include <libgen.h>
31 #undef basename
32
33 #include "bus-util.h"
34 #include "bus-label.h"
35 #include "strv.h"
36 #include "bus-common-errors.h"
37 #include "copy.h"
38 #include "fileio.h"
39 #include "in-addr-util.h"
40 #include "local-addresses.h"
41 #include "path-util.h"
42 #include "mkdir.h"
43 #include "bus-internal.h"
44 #include "machine.h"
45 #include "machine-dbus.h"
46
47 static int property_get_id(
48                 sd_bus *bus,
49                 const char *path,
50                 const char *interface,
51                 const char *property,
52                 sd_bus_message *reply,
53                 void *userdata,
54                 sd_bus_error *error) {
55
56         Machine *m = userdata;
57         int r;
58
59         assert(bus);
60         assert(reply);
61         assert(m);
62
63         r = sd_bus_message_append_array(reply, 'y', &m->id, 16);
64         if (r < 0)
65                 return r;
66
67         return 1;
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         int r;
107
108         assert(bus);
109         assert(reply);
110         assert(m);
111
112         assert_cc(sizeof(int) == sizeof(int32_t));
113
114         r = sd_bus_message_append_array(reply, 'i', m->netif, m->n_netif * sizeof(int));
115         if (r < 0)
116                 return r;
117
118         return 1;
119 }
120
121 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_class, machine_class, MachineClass);
122
123 int bus_machine_method_terminate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
124         Machine *m = userdata;
125         int r;
126
127         assert(bus);
128         assert(message);
129         assert(m);
130
131         r = bus_verify_polkit_async(
132                         message,
133                         CAP_KILL,
134                         "org.freedesktop.machine1.manage-machines",
135                         false,
136                         &m->manager->polkit_registry,
137                         error);
138         if (r < 0)
139                 return r;
140         if (r == 0)
141                 return 1; /* Will call us back */
142
143         r = machine_stop(m);
144         if (r < 0)
145                 return r;
146
147         return sd_bus_reply_method_return(message, NULL);
148 }
149
150 int bus_machine_method_kill(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
151         Machine *m = userdata;
152         const char *swho;
153         int32_t signo;
154         KillWho who;
155         int r;
156
157         assert(bus);
158         assert(message);
159         assert(m);
160
161         r = sd_bus_message_read(message, "si", &swho, &signo);
162         if (r < 0)
163                 return r;
164
165         if (isempty(swho))
166                 who = KILL_ALL;
167         else {
168                 who = kill_who_from_string(swho);
169                 if (who < 0)
170                         return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid kill parameter '%s'", swho);
171         }
172
173         if (signo <= 0 || signo >= _NSIG)
174                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid signal %i", signo);
175
176         r = bus_verify_polkit_async(
177                         message,
178                         CAP_KILL,
179                         "org.freedesktop.machine1.manage-machines",
180                         false,
181                         &m->manager->polkit_registry,
182                         error);
183         if (r < 0)
184                 return r;
185         if (r == 0)
186                 return 1; /* Will call us back */
187
188         r = machine_kill(m, who, signo);
189         if (r < 0)
190                 return r;
191
192         return sd_bus_reply_method_return(message, NULL);
193 }
194
195 int bus_machine_method_get_addresses(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
196         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
197         _cleanup_close_pair_ int pair[2] = { -1, -1 };
198         _cleanup_free_ char *us = NULL, *them = NULL;
199         _cleanup_close_ int netns_fd = -1;
200         Machine *m = userdata;
201         const char *p;
202         siginfo_t si;
203         pid_t child;
204         int r;
205
206         assert(bus);
207         assert(message);
208         assert(m);
209
210         if (m->class != MACHINE_CONTAINER)
211                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting IP address data is only supported on container machines.");
212
213         r = readlink_malloc("/proc/self/ns/net", &us);
214         if (r < 0)
215                 return r;
216
217         p = procfs_file_alloca(m->leader, "ns/net");
218         r = readlink_malloc(p, &them);
219         if (r < 0)
220                 return r;
221
222         if (streq(us, them))
223                 return sd_bus_error_setf(error, BUS_ERROR_NO_PRIVATE_NETWORKING, "Machine %s does not use private networking", m->name);
224
225         r = namespace_open(m->leader, NULL, NULL, &netns_fd, NULL);
226         if (r < 0)
227                 return r;
228
229         if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
230                 return -errno;
231
232         child = fork();
233         if (child < 0)
234                 return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
235
236         if (child == 0) {
237                 _cleanup_free_ struct local_address *addresses = NULL;
238                 struct local_address *a;
239                 int i, n;
240
241                 pair[0] = safe_close(pair[0]);
242
243                 r = namespace_enter(-1, -1, netns_fd, -1);
244                 if (r < 0)
245                         _exit(EXIT_FAILURE);
246
247                 n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
248                 if (n < 0)
249                         _exit(EXIT_FAILURE);
250
251                 for (a = addresses, i = 0; i < n; a++, i++) {
252                         struct iovec iov[2] = {
253                                 { .iov_base = &a->family, .iov_len = sizeof(a->family) },
254                                 { .iov_base = &a->address, .iov_len = FAMILY_ADDRESS_SIZE(a->family) },
255                         };
256
257                         r = writev(pair[1], iov, 2);
258                         if (r < 0)
259                                 _exit(EXIT_FAILURE);
260                 }
261
262                 pair[1] = safe_close(pair[1]);
263
264                 _exit(EXIT_SUCCESS);
265         }
266
267         pair[1] = safe_close(pair[1]);
268
269         r = sd_bus_message_new_method_return(message, &reply);
270         if (r < 0)
271                 return r;
272
273         r = sd_bus_message_open_container(reply, 'a', "(iay)");
274         if (r < 0)
275                 return r;
276
277         for (;;) {
278                 int family;
279                 ssize_t n;
280                 union in_addr_union in_addr;
281                 struct iovec iov[2];
282                 struct msghdr mh = {
283                         .msg_iov = iov,
284                         .msg_iovlen = 2,
285                 };
286
287                 iov[0] = (struct iovec) { .iov_base = &family, .iov_len = sizeof(family) };
288                 iov[1] = (struct iovec) { .iov_base = &in_addr, .iov_len = sizeof(in_addr) };
289
290                 n = recvmsg(pair[0], &mh, 0);
291                 if (n < 0)
292                         return -errno;
293                 if ((size_t) n < sizeof(family))
294                         break;
295
296                 r = sd_bus_message_open_container(reply, 'r', "iay");
297                 if (r < 0)
298                         return r;
299
300                 r = sd_bus_message_append(reply, "i", family);
301                 if (r < 0)
302                         return r;
303
304                 switch (family) {
305
306                 case AF_INET:
307                         if (n != sizeof(struct in_addr) + sizeof(family))
308                                 return -EIO;
309
310                         r = sd_bus_message_append_array(reply, 'y', &in_addr.in, sizeof(in_addr.in));
311                         break;
312
313                 case AF_INET6:
314                         if (n != sizeof(struct in6_addr) + sizeof(family))
315                                 return -EIO;
316
317                         r = sd_bus_message_append_array(reply, 'y', &in_addr.in6, sizeof(in_addr.in6));
318                         break;
319                 }
320                 if (r < 0)
321                         return r;
322
323                 r = sd_bus_message_close_container(reply);
324                 if (r < 0)
325                         return r;
326         }
327
328         r = wait_for_terminate(child, &si);
329         if (r < 0)
330                 return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
331         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
332                 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
333
334         r = sd_bus_message_close_container(reply);
335         if (r < 0)
336                 return r;
337
338         return sd_bus_send(bus, reply, NULL);
339 }
340
341 int bus_machine_method_get_os_release(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
342         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
343         _cleanup_close_ int mntns_fd = -1, root_fd = -1;
344         _cleanup_close_pair_ int pair[2] = { -1, -1 };
345         _cleanup_strv_free_ char **l = NULL;
346         _cleanup_fclose_ FILE *f = NULL;
347         Machine *m = userdata;
348         char **k, **v;
349         siginfo_t si;
350         pid_t child;
351         int r;
352
353         assert(bus);
354         assert(message);
355         assert(m);
356
357         if (m->class != MACHINE_CONTAINER)
358                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
359
360         r = namespace_open(m->leader, NULL, &mntns_fd, NULL, &root_fd);
361         if (r < 0)
362                 return r;
363
364         if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
365                 return -errno;
366
367         child = fork();
368         if (child < 0)
369                 return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
370
371         if (child == 0) {
372                 _cleanup_close_ int fd = -1;
373
374                 pair[0] = safe_close(pair[0]);
375
376                 r = namespace_enter(-1, mntns_fd, -1, root_fd);
377                 if (r < 0)
378                         _exit(EXIT_FAILURE);
379
380                 fd = open("/etc/os-release", O_RDONLY|O_CLOEXEC);
381                 if (fd < 0) {
382                         fd = open("/usr/lib/os-release", O_RDONLY|O_CLOEXEC);
383                         if (fd < 0)
384                                 _exit(EXIT_FAILURE);
385                 }
386
387                 r = copy_bytes(fd, pair[1], (off_t) -1, false);
388                 if (r < 0)
389                         _exit(EXIT_FAILURE);
390
391                 _exit(EXIT_SUCCESS);
392         }
393
394         pair[1] = safe_close(pair[1]);
395
396         f = fdopen(pair[0], "re");
397         if (!f)
398                 return -errno;
399
400         pair[0] = -1;
401
402         r = load_env_file_pairs(f, "/etc/os-release", NULL, &l);
403         if (r < 0)
404                 return r;
405
406         r = wait_for_terminate(child, &si);
407         if (r < 0)
408                 return sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
409         if (si.si_code != CLD_EXITED || si.si_status != EXIT_SUCCESS)
410                 return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
411
412         r = sd_bus_message_new_method_return(message, &reply);
413         if (r < 0)
414                 return r;
415
416         r = sd_bus_message_open_container(reply, 'a', "{ss}");
417         if (r < 0)
418                 return r;
419
420         STRV_FOREACH_PAIR(k, v, l) {
421                 r = sd_bus_message_append(reply, "{ss}", *k, *v);
422                 if (r < 0)
423                         return r;
424         }
425
426         r = sd_bus_message_close_container(reply);
427         if (r < 0)
428                 return r;
429
430         return sd_bus_send(bus, reply, NULL);
431 }
432
433 int bus_machine_method_open_pty(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
434         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
435         _cleanup_free_ char *pty_name = NULL;
436         _cleanup_close_ int master = -1;
437         Machine *m = userdata;
438         int r;
439
440         assert(bus);
441         assert(message);
442         assert(m);
443
444         if (m->class != MACHINE_CONTAINER)
445                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening pseudo TTYs is only supported on container machines.");
446
447         master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
448         if (master < 0)
449                 return master;
450
451         r = ptsname_malloc(master, &pty_name);
452         if (r < 0)
453                 return r;
454
455         r = sd_bus_message_new_method_return(message, &reply);
456         if (r < 0)
457                 return r;
458
459         r = sd_bus_message_append(reply, "hs", master, pty_name);
460         if (r < 0)
461                 return r;
462
463         return sd_bus_send(bus, reply, NULL);
464 }
465
466 int bus_machine_method_open_login(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
467         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
468         _cleanup_free_ char *pty_name = NULL, *getty = NULL;
469         _cleanup_bus_unref_ sd_bus *container_bus = NULL;
470         _cleanup_close_ int master = -1;
471         Machine *m = userdata;
472         const char *p;
473         int r;
474
475         if (m->class != MACHINE_CONTAINER)
476                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening logins is only supported on container machines.");
477
478         r = bus_verify_polkit_async(
479                         message,
480                         CAP_SYS_ADMIN,
481                         "org.freedesktop.machine1.login",
482                         false,
483                         &m->manager->polkit_registry,
484                         error);
485         if (r < 0)
486                 return r;
487         if (r == 0)
488                 return 1; /* Will call us back */
489
490         master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
491         if (master < 0)
492                 return master;
493
494         r = ptsname_malloc(master, &pty_name);
495         if (r < 0)
496                 return r;
497
498         p = path_startswith(pty_name, "/dev/pts/");
499         if (!p)
500                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
501
502         if (unlockpt(master) < 0)
503                 return -errno;
504
505         r = sd_bus_new(&container_bus);
506         if (r < 0)
507                 return r;
508
509 #ifdef ENABLE_KDBUS
510         asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT ";x-machine-unix:pid=" PID_FMT, m->leader, m->leader);
511 #else
512         asprintf(&container_bus->address, "x-machine-kernel:pid=" PID_FMT, m->leader);
513 #endif
514         if (!container_bus->address)
515                 return log_oom();
516
517         container_bus->bus_client = true;
518         container_bus->trusted = false;
519         container_bus->is_system = true;
520
521         r = sd_bus_start(container_bus);
522         if (r < 0)
523                 return r;
524
525         getty = strjoin("container-getty@", p, ".service", NULL);
526         if (!getty)
527                 return log_oom();
528
529         r = sd_bus_call_method(
530                         container_bus,
531                         "org.freedesktop.systemd1",
532                         "/org/freedesktop/systemd1",
533                         "org.freedesktop.systemd1.Manager",
534                         "StartUnit",
535                         error, NULL,
536                         "ss", getty, "replace");
537         if (r < 0)
538                 return r;
539
540         container_bus = sd_bus_unref(container_bus);
541
542         r = sd_bus_message_new_method_return(message, &reply);
543         if (r < 0)
544                 return r;
545
546         r = sd_bus_message_append(reply, "hs", master, pty_name);
547         if (r < 0)
548                 return r;
549
550         return sd_bus_send(bus, reply, NULL);
551 }
552
553 int bus_machine_method_bind_mount(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
554         _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
555         char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
556         bool mount_slave_created = false, mount_slave_mounted = false,
557                 mount_tmp_created = false, mount_tmp_mounted = false,
558                 mount_outside_created = false, mount_outside_mounted = false;
559         const char *dest, *src;
560         Machine *m = userdata;
561         int read_only, make_directory;
562         pid_t child;
563         siginfo_t si;
564         int r;
565
566         if (m->class != MACHINE_CONTAINER)
567                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
568
569         r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory);
570         if (r < 0)
571                 return r;
572
573         if (!path_is_absolute(src) || !path_is_safe(src))
574                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
575
576         if (isempty(dest))
577                 dest = src;
578         else if (!path_is_absolute(dest) || !path_is_safe(dest))
579                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
580
581         r = bus_verify_polkit_async(
582                         message,
583                         CAP_SYS_ADMIN,
584                         "org.freedesktop.machine1.manage-machines",
585                         false,
586                         &m->manager->polkit_registry,
587                         error);
588         if (r < 0)
589                 return r;
590         if (r == 0)
591                 return 1; /* Will call us back */
592
593         /* One day, when bind mounting /proc/self/fd/n works across
594          * namespace boundaries we should rework this logic to make
595          * use of it... */
596
597         p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
598         if (laccess(p, F_OK) < 0)
599                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
600
601         /* Our goal is to install a new bind mount into the container,
602            possibly read-only. This is irritatingly complex
603            unfortunately, currently.
604
605            First, we start by creating a private playground in /tmp,
606            that we can mount MS_SLAVE. (Which is necessary, since
607            MS_MOUNT cannot be applied to mounts with MS_SHARED parent
608            mounts.) */
609
610         if (!mkdtemp(mount_slave))
611                 return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
612
613         mount_slave_created = true;
614
615         if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
616                 r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
617                 goto finish;
618         }
619
620         mount_slave_mounted = true;
621
622         if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
623                 r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
624                 goto finish;
625         }
626
627         /* Second, we mount the source directory to a directory inside
628            of our MS_SLAVE playground. */
629         mount_tmp = strjoina(mount_slave, "/mount");
630         if (mkdir(mount_tmp, 0700) < 0) {
631                 r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
632                 goto finish;
633         }
634
635         mount_tmp_created = true;
636
637         if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
638                 r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp);
639                 goto finish;
640         }
641
642         mount_tmp_mounted = true;
643
644         /* Third, we remount the new bind mount read-only if requested. */
645         if (read_only)
646                 if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
647                         r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
648                         goto finish;
649                 }
650
651         /* Fourth, we move the new bind mount into the propagation
652          * directory. This way it will appear there read-only
653          * right-away. */
654
655         mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
656         if (!mkdtemp(mount_outside)) {
657                 r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
658                 goto finish;
659         }
660
661         mount_outside_created = true;
662
663         if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
664                 r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
665                 goto finish;
666         }
667
668         mount_outside_mounted = true;
669         mount_tmp_mounted = false;
670
671         (void) rmdir(mount_tmp);
672         mount_tmp_created = false;
673
674         (void) umount(mount_slave);
675         mount_slave_mounted = false;
676
677         (void) rmdir(mount_slave);
678         mount_slave_created = false;
679
680         if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
681                 r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
682                 goto finish;
683         }
684
685         child = fork();
686         if (child < 0) {
687                 r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
688                 goto finish;
689         }
690
691         if (child == 0) {
692                 const char *mount_inside;
693                 int mntfd;
694                 const char *q;
695
696                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
697
698                 q = procfs_file_alloca(m->leader, "ns/mnt");
699                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
700                 if (mntfd < 0) {
701                         r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
702                         goto child_fail;
703                 }
704
705                 if (setns(mntfd, CLONE_NEWNS) < 0) {
706                         r = log_error_errno(errno, "Failed to join namespace of leader: %m");
707                         goto child_fail;
708                 }
709
710                 if (make_directory)
711                         (void) mkdir_p(dest, 0755);
712
713                 /* Fifth, move the mount to the right place inside */
714                 mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
715                 if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
716                         r = log_error_errno(errno, "Failed to mount: %m");
717                         goto child_fail;
718                 }
719
720                 _exit(EXIT_SUCCESS);
721
722         child_fail:
723                 (void) write(errno_pipe_fd[1], &r, sizeof(r));
724                 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
725
726                 _exit(EXIT_FAILURE);
727         }
728
729         errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
730
731         r = wait_for_terminate(child, &si);
732         if (r < 0) {
733                 r = sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
734                 goto finish;
735         }
736         if (si.si_code != CLD_EXITED) {
737                 r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
738                 goto finish;
739         }
740         if (si.si_status != EXIT_SUCCESS) {
741
742                 if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
743                         r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
744                 else
745                         r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client failed.");
746                 goto finish;
747         }
748
749         r = sd_bus_reply_method_return(message, NULL);
750
751 finish:
752         if (mount_outside_mounted)
753                 umount(mount_outside);
754         if (mount_outside_created)
755                 rmdir(mount_outside);
756
757         if (mount_tmp_mounted)
758                 umount(mount_tmp);
759         if (mount_tmp_created)
760                 rmdir(mount_tmp);
761
762         if (mount_slave_mounted)
763                 umount(mount_slave);
764         if (mount_slave_created)
765                 rmdir(mount_slave);
766
767         return r;
768 }
769
770 static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
771         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
772         MachineOperation *o = userdata;
773         int r;
774
775         assert(o);
776         assert(si);
777
778         o->pid = 0;
779
780         if (si->si_code != CLD_EXITED) {
781                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
782                 goto fail;
783         }
784
785         if (si->si_status != EXIT_SUCCESS) {
786                 if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r))
787                         r = sd_bus_error_set_errnof(&error, r, "%m");
788                 else
789                         r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client failed.");
790
791                 goto fail;
792         }
793
794         r = sd_bus_reply_method_return(o->message, NULL);
795         if (r < 0)
796                 log_error_errno(r, "Failed to reply to message: %m");
797
798         machine_operation_unref(o);
799         return 0;
800
801 fail:
802         r = sd_bus_reply_method_error(o->message, &error);
803         if (r < 0)
804                 log_error_errno(r, "Failed to reply to message: %m");
805
806         machine_operation_unref(o);
807         return 0;
808 }
809
810 int bus_machine_method_copy(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
811         const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
812         _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
813         _cleanup_close_ int hostfd = -1;
814         Machine *m = userdata;
815         MachineOperation *o;
816         bool copy_from;
817         pid_t child;
818         char *t;
819         int r;
820
821         if (m->n_operations >= MACHINE_OPERATIONS_MAX)
822                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
823
824         if (m->class != MACHINE_CONTAINER)
825                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
826
827         r = sd_bus_message_read(message, "ss", &src, &dest);
828         if (r < 0)
829                 return r;
830
831         if (!path_is_absolute(src) || !path_is_safe(src))
832                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
833
834         if (isempty(dest))
835                 dest = src;
836         else if (!path_is_absolute(dest) || !path_is_safe(dest))
837                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
838
839         r = bus_verify_polkit_async(
840                         message,
841                         CAP_SYS_ADMIN,
842                         "org.freedesktop.machine1.manage-machines",
843                         false,
844                         &m->manager->polkit_registry,
845                         error);
846         if (r < 0)
847                 return r;
848         if (r == 0)
849                 return 1; /* Will call us back */
850
851         copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
852
853         if (copy_from) {
854                 container_path = src;
855                 host_path = dest;
856         } else {
857                 host_path = src;
858                 container_path = dest;
859         }
860
861         host_basename = basename(host_path);
862         t = strdupa(host_path);
863         host_dirname = dirname(t);
864
865         container_basename = basename(container_path);
866         t = strdupa(container_path);
867         container_dirname = dirname(t);
868
869         hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
870         if (r < 0)
871                 return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname);
872
873         if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
874                 return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
875
876         child = fork();
877         if (child < 0)
878                 return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
879
880         if (child == 0) {
881                 int containerfd;
882                 const char *q;
883                 int mntfd;
884
885                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
886
887                 q = procfs_file_alloca(m->leader, "ns/mnt");
888                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
889                 if (mntfd < 0) {
890                         r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
891                         goto child_fail;
892                 }
893
894                 if (setns(mntfd, CLONE_NEWNS) < 0) {
895                         r = log_error_errno(errno, "Failed to join namespace of leader: %m");
896                         goto child_fail;
897                 }
898
899                 containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
900                 if (containerfd < 0) {
901                         r = log_error_errno(errno, "Failed top open destination directory: %m");
902                         goto child_fail;
903                 }
904
905                 if (copy_from)
906                         r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
907                 else
908                         r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
909
910                 hostfd = safe_close(hostfd);
911                 containerfd = safe_close(containerfd);
912
913                 if (r < 0) {
914                         r = log_error_errno(r, "Failed to copy tree: %m");
915                         goto child_fail;
916                 }
917
918                 _exit(EXIT_SUCCESS);
919
920         child_fail:
921                 (void) write(errno_pipe_fd[1], &r, sizeof(r));
922                 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
923
924                 _exit(EXIT_FAILURE);
925         }
926
927         errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
928
929         /* Copying might take a while, hence install a watch the
930          * child, and return */
931
932         o = new0(MachineOperation, 1);
933         if (!o)
934                 return log_oom();
935
936         o->pid = child;
937         o->message = sd_bus_message_ref(message);
938         o->errno_fd = errno_pipe_fd[0];
939         errno_pipe_fd[0] = -1;
940
941         r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
942         if (r < 0) {
943                 machine_operation_unref(o);
944                 return log_oom();
945         }
946
947         LIST_PREPEND(operations, m->operations, o);
948         m->n_operations++;
949         o->machine = m;
950
951         return 1;
952 }
953
954 const sd_bus_vtable machine_vtable[] = {
955         SD_BUS_VTABLE_START(0),
956         SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
957         SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
958         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
959         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
960         SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
961         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
962         SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
963         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
964         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
965         SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
966         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
967         SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
968         SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
969         SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
970         SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
971         SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, 0),
972         SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED),
973         SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
974         SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
975         SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
976         SD_BUS_VTABLE_END
977 };
978
979 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
980         Manager *m = userdata;
981         Machine *machine;
982         int r;
983
984         assert(bus);
985         assert(path);
986         assert(interface);
987         assert(found);
988         assert(m);
989
990         if (streq(path, "/org/freedesktop/machine1/machine/self")) {
991                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
992                 sd_bus_message *message;
993                 pid_t pid;
994
995                 message = sd_bus_get_current_message(bus);
996                 if (!message)
997                         return 0;
998
999                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
1000                 if (r < 0)
1001                         return r;
1002
1003                 r = sd_bus_creds_get_pid(creds, &pid);
1004                 if (r < 0)
1005                         return r;
1006
1007                 r = manager_get_machine_by_pid(m, pid, &machine);
1008                 if (r <= 0)
1009                         return 0;
1010         } else {
1011                 _cleanup_free_ char *e = NULL;
1012                 const char *p;
1013
1014                 p = startswith(path, "/org/freedesktop/machine1/machine/");
1015                 if (!p)
1016                         return 0;
1017
1018                 e = bus_label_unescape(p);
1019                 if (!e)
1020                         return -ENOMEM;
1021
1022                 machine = hashmap_get(m->machines, e);
1023                 if (!machine)
1024                         return 0;
1025         }
1026
1027         *found = machine;
1028         return 1;
1029 }
1030
1031 char *machine_bus_path(Machine *m) {
1032         _cleanup_free_ char *e = NULL;
1033
1034         assert(m);
1035
1036         e = bus_label_escape(m->name);
1037         if (!e)
1038                 return NULL;
1039
1040         return strappend("/org/freedesktop/machine1/machine/", e);
1041 }
1042
1043 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
1044         _cleanup_strv_free_ char **l = NULL;
1045         Machine *machine = NULL;
1046         Manager *m = userdata;
1047         Iterator i;
1048         int r;
1049
1050         assert(bus);
1051         assert(path);
1052         assert(nodes);
1053
1054         HASHMAP_FOREACH(machine, m->machines, i) {
1055                 char *p;
1056
1057                 p = machine_bus_path(machine);
1058                 if (!p)
1059                         return -ENOMEM;
1060
1061                 r = strv_consume(&l, p);
1062                 if (r < 0)
1063                         return r;
1064         }
1065
1066         *nodes = l;
1067         l = NULL;
1068
1069         return 1;
1070 }
1071
1072 int machine_send_signal(Machine *m, bool new_machine) {
1073         _cleanup_free_ char *p = NULL;
1074
1075         assert(m);
1076
1077         p = machine_bus_path(m);
1078         if (!p)
1079                 return -ENOMEM;
1080
1081         return sd_bus_emit_signal(
1082                         m->manager->bus,
1083                         "/org/freedesktop/machine1",
1084                         "org.freedesktop.machine1.Manager",
1085                         new_machine ? "MachineNew" : "MachineRemoved",
1086                         "so", m->name, p);
1087 }
1088
1089 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
1090         _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
1091         _cleanup_free_ char *p = NULL;
1092
1093         assert(m);
1094
1095         if (!m->create_message)
1096                 return 0;
1097
1098         c = m->create_message;
1099         m->create_message = NULL;
1100
1101         if (error)
1102                 return sd_bus_reply_method_error(c, error);
1103
1104         /* Update the machine state file before we notify the client
1105          * about the result. */
1106         machine_save(m);
1107
1108         p = machine_bus_path(m);
1109         if (!p)
1110                 return -ENOMEM;
1111
1112         return sd_bus_reply_method_return(c, "o", p);
1113 }