chiark / gitweb /
d6b8c90090fedeec14bcc0b2523f4d1265aa08b6
[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         char *address;
475         int r;
476
477         if (m->class != MACHINE_CONTAINER)
478                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Opening logins is only supported on container machines.");
479
480         r = bus_verify_polkit_async(
481                         message,
482                         CAP_SYS_ADMIN,
483                         "org.freedesktop.machine1.login",
484                         false,
485                         UID_INVALID,
486                         &m->manager->polkit_registry,
487                         error);
488         if (r < 0)
489                 return r;
490         if (r == 0)
491                 return 1; /* Will call us back */
492
493         master = openpt_in_namespace(m->leader, O_RDWR|O_NOCTTY|O_CLOEXEC);
494         if (master < 0)
495                 return master;
496
497         r = ptsname_malloc(master, &pty_name);
498         if (r < 0)
499                 return r;
500
501         p = path_startswith(pty_name, "/dev/pts/");
502         if (!p)
503                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "PTS name %s is invalid", pty_name);
504
505         if (unlockpt(master) < 0)
506                 return -errno;
507
508         r = sd_bus_new(&container_bus);
509         if (r < 0)
510                 return r;
511
512 #ifdef ENABLE_KDBUS
513 #  define ADDRESS_FMT "x-machine-kernel:pid=%1$" PID_PRI ";x-machine-unix:pid=%1$" PID_PRI
514 #else
515 #  define ADDRESS_FMT "x-machine-unix:pid=%1$" PID_PRI
516 #endif
517         if (asprintf(&address, ADDRESS_FMT, m->leader) < 0)
518                 return log_oom();
519
520         container_bus->address = address;
521         container_bus->bus_client = true;
522         container_bus->trusted = false;
523         container_bus->is_system = true;
524
525         r = sd_bus_start(container_bus);
526         if (r < 0)
527                 return r;
528
529         getty = strjoin("container-getty@", p, ".service", NULL);
530         if (!getty)
531                 return log_oom();
532
533         r = sd_bus_call_method(
534                         container_bus,
535                         "org.freedesktop.systemd1",
536                         "/org/freedesktop/systemd1",
537                         "org.freedesktop.systemd1.Manager",
538                         "StartUnit",
539                         error, NULL,
540                         "ss", getty, "replace");
541         if (r < 0)
542                 return r;
543
544         container_bus = sd_bus_unref(container_bus);
545
546         r = sd_bus_message_new_method_return(message, &reply);
547         if (r < 0)
548                 return r;
549
550         r = sd_bus_message_append(reply, "hs", master, pty_name);
551         if (r < 0)
552                 return r;
553
554         return sd_bus_send(bus, reply, NULL);
555 }
556
557 int bus_machine_method_bind_mount(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
558         _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
559         char mount_slave[] = "/tmp/propagate.XXXXXX", *mount_tmp, *mount_outside, *p;
560         bool mount_slave_created = false, mount_slave_mounted = false,
561                 mount_tmp_created = false, mount_tmp_mounted = false,
562                 mount_outside_created = false, mount_outside_mounted = false;
563         const char *dest, *src;
564         Machine *m = userdata;
565         int read_only, make_directory;
566         pid_t child;
567         siginfo_t si;
568         int r;
569
570         if (m->class != MACHINE_CONTAINER)
571                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Bind mounting is only supported on container machines.");
572
573         r = sd_bus_message_read(message, "ssbb", &src, &dest, &read_only, &make_directory);
574         if (r < 0)
575                 return r;
576
577         if (!path_is_absolute(src) || !path_is_safe(src))
578                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
579
580         if (isempty(dest))
581                 dest = src;
582         else if (!path_is_absolute(dest) || !path_is_safe(dest))
583                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
584
585         r = bus_verify_polkit_async(
586                         message,
587                         CAP_SYS_ADMIN,
588                         "org.freedesktop.machine1.manage-machines",
589                         false,
590                         UID_INVALID,
591                         &m->manager->polkit_registry,
592                         error);
593         if (r < 0)
594                 return r;
595         if (r == 0)
596                 return 1; /* Will call us back */
597
598         /* One day, when bind mounting /proc/self/fd/n works across
599          * namespace boundaries we should rework this logic to make
600          * use of it... */
601
602         p = strjoina("/run/systemd/nspawn/propagate/", m->name, "/");
603         if (laccess(p, F_OK) < 0)
604                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Container does not allow propagation of mount points.");
605
606         /* Our goal is to install a new bind mount into the container,
607            possibly read-only. This is irritatingly complex
608            unfortunately, currently.
609
610            First, we start by creating a private playground in /tmp,
611            that we can mount MS_SLAVE. (Which is necessary, since
612            MS_MOUNT cannot be applied to mounts with MS_SHARED parent
613            mounts.) */
614
615         if (!mkdtemp(mount_slave))
616                 return sd_bus_error_set_errnof(error, errno, "Failed to create playground %s: %m", mount_slave);
617
618         mount_slave_created = true;
619
620         if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) {
621                 r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave);
622                 goto finish;
623         }
624
625         mount_slave_mounted = true;
626
627         if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) {
628                 r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave);
629                 goto finish;
630         }
631
632         /* Second, we mount the source directory to a directory inside
633            of our MS_SLAVE playground. */
634         mount_tmp = strjoina(mount_slave, "/mount");
635         if (mkdir(mount_tmp, 0700) < 0) {
636                 r = sd_bus_error_set_errnof(error, errno, "Failed to create temporary mount point %s: %m", mount_tmp);
637                 goto finish;
638         }
639
640         mount_tmp_created = true;
641
642         if (mount(src, mount_tmp, NULL, MS_BIND, NULL) < 0) {
643                 r = sd_bus_error_set_errnof(error, errno, "Failed to overmount %s: %m", mount_tmp);
644                 goto finish;
645         }
646
647         mount_tmp_mounted = true;
648
649         /* Third, we remount the new bind mount read-only if requested. */
650         if (read_only)
651                 if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) {
652                         r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp);
653                         goto finish;
654                 }
655
656         /* Fourth, we move the new bind mount into the propagation
657          * directory. This way it will appear there read-only
658          * right-away. */
659
660         mount_outside = strjoina("/run/systemd/nspawn/propagate/", m->name, "/XXXXXX");
661         if (!mkdtemp(mount_outside)) {
662                 r = sd_bus_error_set_errnof(error, errno, "Cannot create propagation directory %s: %m", mount_outside);
663                 goto finish;
664         }
665
666         mount_outside_created = true;
667
668         if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) {
669                 r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside);
670                 goto finish;
671         }
672
673         mount_outside_mounted = true;
674         mount_tmp_mounted = false;
675
676         (void) rmdir(mount_tmp);
677         mount_tmp_created = false;
678
679         (void) umount(mount_slave);
680         mount_slave_mounted = false;
681
682         (void) rmdir(mount_slave);
683         mount_slave_created = false;
684
685         if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0) {
686                 r = sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
687                 goto finish;
688         }
689
690         child = fork();
691         if (child < 0) {
692                 r = sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
693                 goto finish;
694         }
695
696         if (child == 0) {
697                 const char *mount_inside;
698                 int mntfd;
699                 const char *q;
700
701                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
702
703                 q = procfs_file_alloca(m->leader, "ns/mnt");
704                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
705                 if (mntfd < 0) {
706                         r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
707                         goto child_fail;
708                 }
709
710                 if (setns(mntfd, CLONE_NEWNS) < 0) {
711                         r = log_error_errno(errno, "Failed to join namespace of leader: %m");
712                         goto child_fail;
713                 }
714
715                 if (make_directory)
716                         (void) mkdir_p(dest, 0755);
717
718                 /* Fifth, move the mount to the right place inside */
719                 mount_inside = strjoina("/run/systemd/nspawn/incoming/", basename(mount_outside));
720                 if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) {
721                         r = log_error_errno(errno, "Failed to mount: %m");
722                         goto child_fail;
723                 }
724
725                 _exit(EXIT_SUCCESS);
726
727         child_fail:
728                 (void) write(errno_pipe_fd[1], &r, sizeof(r));
729                 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
730
731                 _exit(EXIT_FAILURE);
732         }
733
734         errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
735
736         r = wait_for_terminate(child, &si);
737         if (r < 0) {
738                 r = sd_bus_error_set_errnof(error, r, "Failed to wait for client: %m");
739                 goto finish;
740         }
741         if (si.si_code != CLD_EXITED) {
742                 r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
743                 goto finish;
744         }
745         if (si.si_status != EXIT_SUCCESS) {
746
747                 if (read(errno_pipe_fd[0], &r, sizeof(r)) == sizeof(r))
748                         r = sd_bus_error_set_errnof(error, r, "Failed to mount: %m");
749                 else
750                         r = sd_bus_error_setf(error, SD_BUS_ERROR_FAILED, "Client failed.");
751                 goto finish;
752         }
753
754         r = sd_bus_reply_method_return(message, NULL);
755
756 finish:
757         if (mount_outside_mounted)
758                 umount(mount_outside);
759         if (mount_outside_created)
760                 rmdir(mount_outside);
761
762         if (mount_tmp_mounted)
763                 umount(mount_tmp);
764         if (mount_tmp_created)
765                 rmdir(mount_tmp);
766
767         if (mount_slave_mounted)
768                 umount(mount_slave);
769         if (mount_slave_created)
770                 rmdir(mount_slave);
771
772         return r;
773 }
774
775 static int machine_operation_done(sd_event_source *s, const siginfo_t *si, void *userdata) {
776         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
777         MachineOperation *o = userdata;
778         int r;
779
780         assert(o);
781         assert(si);
782
783         o->pid = 0;
784
785         if (si->si_code != CLD_EXITED) {
786                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client died abnormally.");
787                 goto fail;
788         }
789
790         if (si->si_status != EXIT_SUCCESS) {
791                 if (read(o->errno_fd, &r, sizeof(r)) == sizeof(r))
792                         r = sd_bus_error_set_errnof(&error, r, "%m");
793                 else
794                         r = sd_bus_error_setf(&error, SD_BUS_ERROR_FAILED, "Client failed.");
795
796                 goto fail;
797         }
798
799         r = sd_bus_reply_method_return(o->message, NULL);
800         if (r < 0)
801                 log_error_errno(r, "Failed to reply to message: %m");
802
803         machine_operation_unref(o);
804         return 0;
805
806 fail:
807         r = sd_bus_reply_method_error(o->message, &error);
808         if (r < 0)
809                 log_error_errno(r, "Failed to reply to message: %m");
810
811         machine_operation_unref(o);
812         return 0;
813 }
814
815 int bus_machine_method_copy(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
816         const char *src, *dest, *host_path, *container_path, *host_basename, *host_dirname, *container_basename, *container_dirname;
817         _cleanup_close_pair_ int errno_pipe_fd[2] = { -1, -1 };
818         _cleanup_close_ int hostfd = -1;
819         Machine *m = userdata;
820         MachineOperation *o;
821         bool copy_from;
822         pid_t child;
823         char *t;
824         int r;
825
826         if (m->n_operations >= MACHINE_OPERATIONS_MAX)
827                 return sd_bus_error_setf(error, SD_BUS_ERROR_LIMITS_EXCEEDED, "Too many ongoing copies.");
828
829         if (m->class != MACHINE_CONTAINER)
830                 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Copying files is only supported on container machines.");
831
832         r = sd_bus_message_read(message, "ss", &src, &dest);
833         if (r < 0)
834                 return r;
835
836         if (!path_is_absolute(src) || !path_is_safe(src))
837                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Source path must be absolute and not contain ../.");
838
839         if (isempty(dest))
840                 dest = src;
841         else if (!path_is_absolute(dest) || !path_is_safe(dest))
842                 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Destination path must be absolute and not contain ../.");
843
844         r = bus_verify_polkit_async(
845                         message,
846                         CAP_SYS_ADMIN,
847                         "org.freedesktop.machine1.manage-machines",
848                         false,
849                         UID_INVALID,
850                         &m->manager->polkit_registry,
851                         error);
852         if (r < 0)
853                 return r;
854         if (r == 0)
855                 return 1; /* Will call us back */
856
857         copy_from = strstr(sd_bus_message_get_member(message), "CopyFrom");
858
859         if (copy_from) {
860                 container_path = src;
861                 host_path = dest;
862         } else {
863                 host_path = src;
864                 container_path = dest;
865         }
866
867         host_basename = basename(host_path);
868         t = strdupa(host_path);
869         host_dirname = dirname(t);
870
871         container_basename = basename(container_path);
872         t = strdupa(container_path);
873         container_dirname = dirname(t);
874
875         hostfd = open(host_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
876         if (hostfd < 0)
877                 return sd_bus_error_set_errnof(error, errno, "Failed to open host directory %s: %m", host_dirname);
878
879         if (pipe2(errno_pipe_fd, O_CLOEXEC|O_NONBLOCK) < 0)
880                 return sd_bus_error_set_errnof(error, errno, "Failed to create pipe: %m");
881
882         child = fork();
883         if (child < 0)
884                 return sd_bus_error_set_errnof(error, errno, "Failed to fork(): %m");
885
886         if (child == 0) {
887                 int containerfd;
888                 const char *q;
889                 int mntfd;
890
891                 errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
892
893                 q = procfs_file_alloca(m->leader, "ns/mnt");
894                 mntfd = open(q, O_RDONLY|O_NOCTTY|O_CLOEXEC);
895                 if (mntfd < 0) {
896                         r = log_error_errno(errno, "Failed to open mount namespace of leader: %m");
897                         goto child_fail;
898                 }
899
900                 if (setns(mntfd, CLONE_NEWNS) < 0) {
901                         r = log_error_errno(errno, "Failed to join namespace of leader: %m");
902                         goto child_fail;
903                 }
904
905                 containerfd = open(container_dirname, O_CLOEXEC|O_RDONLY|O_NOCTTY|O_DIRECTORY);
906                 if (containerfd < 0) {
907                         r = log_error_errno(errno, "Failed top open destination directory: %m");
908                         goto child_fail;
909                 }
910
911                 if (copy_from)
912                         r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, true);
913                 else
914                         r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, true);
915
916                 hostfd = safe_close(hostfd);
917                 containerfd = safe_close(containerfd);
918
919                 if (r < 0) {
920                         r = log_error_errno(r, "Failed to copy tree: %m");
921                         goto child_fail;
922                 }
923
924                 _exit(EXIT_SUCCESS);
925
926         child_fail:
927                 (void) write(errno_pipe_fd[1], &r, sizeof(r));
928                 errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
929
930                 _exit(EXIT_FAILURE);
931         }
932
933         errno_pipe_fd[1] = safe_close(errno_pipe_fd[1]);
934
935         /* Copying might take a while, hence install a watch the
936          * child, and return */
937
938         o = new0(MachineOperation, 1);
939         if (!o)
940                 return log_oom();
941
942         o->pid = child;
943         o->message = sd_bus_message_ref(message);
944         o->errno_fd = errno_pipe_fd[0];
945         errno_pipe_fd[0] = -1;
946
947         r = sd_event_add_child(m->manager->event, &o->event_source, child, WEXITED, machine_operation_done, o);
948         if (r < 0) {
949                 machine_operation_unref(o);
950                 return log_oom();
951         }
952
953         LIST_PREPEND(operations, m->operations, o);
954         m->n_operations++;
955         o->machine = m;
956
957         return 1;
958 }
959
960 const sd_bus_vtable machine_vtable[] = {
961         SD_BUS_VTABLE_START(0),
962         SD_BUS_PROPERTY("Name", "s", NULL, offsetof(Machine, name), SD_BUS_VTABLE_PROPERTY_CONST),
963         SD_BUS_PROPERTY("Id", "ay", property_get_id, 0, SD_BUS_VTABLE_PROPERTY_CONST),
964         BUS_PROPERTY_DUAL_TIMESTAMP("Timestamp", offsetof(Machine, timestamp), SD_BUS_VTABLE_PROPERTY_CONST),
965         SD_BUS_PROPERTY("Service", "s", NULL, offsetof(Machine, service), SD_BUS_VTABLE_PROPERTY_CONST),
966         SD_BUS_PROPERTY("Unit", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST),
967         SD_BUS_PROPERTY("Scope", "s", NULL, offsetof(Machine, unit), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
968         SD_BUS_PROPERTY("Leader", "u", NULL, offsetof(Machine, leader), SD_BUS_VTABLE_PROPERTY_CONST),
969         SD_BUS_PROPERTY("Class", "s", property_get_class, offsetof(Machine, class), SD_BUS_VTABLE_PROPERTY_CONST),
970         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(Machine, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
971         SD_BUS_PROPERTY("NetworkInterfaces", "ai", property_get_netif, 0, SD_BUS_VTABLE_PROPERTY_CONST),
972         SD_BUS_PROPERTY("State", "s", property_get_state, 0, 0),
973         SD_BUS_METHOD("Terminate", NULL, NULL, bus_machine_method_terminate, SD_BUS_VTABLE_UNPRIVILEGED),
974         SD_BUS_METHOD("Kill", "si", NULL, bus_machine_method_kill, SD_BUS_VTABLE_UNPRIVILEGED),
975         SD_BUS_METHOD("GetAddresses", NULL, "a(iay)", bus_machine_method_get_addresses, SD_BUS_VTABLE_UNPRIVILEGED),
976         SD_BUS_METHOD("GetOSRelease", NULL, "a{ss}", bus_machine_method_get_os_release, SD_BUS_VTABLE_UNPRIVILEGED),
977         SD_BUS_METHOD("OpenPTY", NULL, "hs", bus_machine_method_open_pty, 0),
978         SD_BUS_METHOD("OpenLogin", NULL, "hs", bus_machine_method_open_login, SD_BUS_VTABLE_UNPRIVILEGED),
979         SD_BUS_METHOD("BindMount", "ssbb", NULL, bus_machine_method_bind_mount, SD_BUS_VTABLE_UNPRIVILEGED),
980         SD_BUS_METHOD("CopyFrom", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
981         SD_BUS_METHOD("CopyTo", "ss", NULL, bus_machine_method_copy, SD_BUS_VTABLE_UNPRIVILEGED),
982         SD_BUS_VTABLE_END
983 };
984
985 int machine_object_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
986         Manager *m = userdata;
987         Machine *machine;
988         int r;
989
990         assert(bus);
991         assert(path);
992         assert(interface);
993         assert(found);
994         assert(m);
995
996         if (streq(path, "/org/freedesktop/machine1/machine/self")) {
997                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
998                 sd_bus_message *message;
999                 pid_t pid;
1000
1001                 message = sd_bus_get_current_message(bus);
1002                 if (!message)
1003                         return 0;
1004
1005                 r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
1006                 if (r < 0)
1007                         return r;
1008
1009                 r = sd_bus_creds_get_pid(creds, &pid);
1010                 if (r < 0)
1011                         return r;
1012
1013                 r = manager_get_machine_by_pid(m, pid, &machine);
1014                 if (r <= 0)
1015                         return 0;
1016         } else {
1017                 _cleanup_free_ char *e = NULL;
1018                 const char *p;
1019
1020                 p = startswith(path, "/org/freedesktop/machine1/machine/");
1021                 if (!p)
1022                         return 0;
1023
1024                 e = bus_label_unescape(p);
1025                 if (!e)
1026                         return -ENOMEM;
1027
1028                 machine = hashmap_get(m->machines, e);
1029                 if (!machine)
1030                         return 0;
1031         }
1032
1033         *found = machine;
1034         return 1;
1035 }
1036
1037 char *machine_bus_path(Machine *m) {
1038         _cleanup_free_ char *e = NULL;
1039
1040         assert(m);
1041
1042         e = bus_label_escape(m->name);
1043         if (!e)
1044                 return NULL;
1045
1046         return strappend("/org/freedesktop/machine1/machine/", e);
1047 }
1048
1049 int machine_node_enumerator(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
1050         _cleanup_strv_free_ char **l = NULL;
1051         Machine *machine = NULL;
1052         Manager *m = userdata;
1053         Iterator i;
1054         int r;
1055
1056         assert(bus);
1057         assert(path);
1058         assert(nodes);
1059
1060         HASHMAP_FOREACH(machine, m->machines, i) {
1061                 char *p;
1062
1063                 p = machine_bus_path(machine);
1064                 if (!p)
1065                         return -ENOMEM;
1066
1067                 r = strv_consume(&l, p);
1068                 if (r < 0)
1069                         return r;
1070         }
1071
1072         *nodes = l;
1073         l = NULL;
1074
1075         return 1;
1076 }
1077
1078 int machine_send_signal(Machine *m, bool new_machine) {
1079         _cleanup_free_ char *p = NULL;
1080
1081         assert(m);
1082
1083         p = machine_bus_path(m);
1084         if (!p)
1085                 return -ENOMEM;
1086
1087         return sd_bus_emit_signal(
1088                         m->manager->bus,
1089                         "/org/freedesktop/machine1",
1090                         "org.freedesktop.machine1.Manager",
1091                         new_machine ? "MachineNew" : "MachineRemoved",
1092                         "so", m->name, p);
1093 }
1094
1095 int machine_send_create_reply(Machine *m, sd_bus_error *error) {
1096         _cleanup_bus_message_unref_ sd_bus_message *c = NULL;
1097         _cleanup_free_ char *p = NULL;
1098
1099         assert(m);
1100
1101         if (!m->create_message)
1102                 return 0;
1103
1104         c = m->create_message;
1105         m->create_message = NULL;
1106
1107         if (error)
1108                 return sd_bus_reply_method_error(c, error);
1109
1110         /* Update the machine state file before we notify the client
1111          * about the result. */
1112         machine_save(m);
1113
1114         p = machine_bus_path(m);
1115         if (!p)
1116                 return -ENOMEM;
1117
1118         return sd_bus_reply_method_return(c, "o", p);
1119 }