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