1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
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.
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.
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/>.
28 #include "btrfs-util.h"
29 #include "bus-common-errors.h"
31 #include "cgroup-util.h"
33 #include "formats-util.h"
34 #include "hostname-util.h"
35 #include "image-dbus.h"
36 #include "machine-dbus.h"
37 #include "machine-image.h"
38 #include "machine-pool.h"
40 #include "path-util.h"
41 #include "process-util.h"
43 #include "unit-name.h"
45 static int property_get_pool_path(
48 const char *interface
,
50 sd_bus_message
*reply
,
52 sd_bus_error
*error
) {
57 return sd_bus_message_append(reply
, "s", "/var/lib/machines");
60 static int property_get_pool_usage(
63 const char *interface
,
65 sd_bus_message
*reply
,
67 sd_bus_error
*error
) {
69 _cleanup_close_
int fd
= -1;
70 uint64_t usage
= (uint64_t) -1;
76 /* We try to read the quota info from /var/lib/machines, as
77 * well as the usage of the loopback file
78 * /var/lib/machines.raw, and pick the larger value. */
80 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
84 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
88 if (stat("/var/lib/machines.raw", &st
) >= 0) {
89 if (usage
== (uint64_t) -1 || st
.st_blocks
* 512ULL > usage
)
90 usage
= st
.st_blocks
* 512ULL;
93 return sd_bus_message_append(reply
, "t", usage
);
96 static int property_get_pool_limit(
99 const char *interface
,
100 const char *property
,
101 sd_bus_message
*reply
,
103 sd_bus_error
*error
) {
105 _cleanup_close_
int fd
= -1;
106 uint64_t size
= (uint64_t) -1;
112 /* We try to read the quota limit from /var/lib/machines, as
113 * well as the size of the loopback file
114 * /var/lib/machines.raw, and pick the smaller value. */
116 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
120 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
121 size
= q
.referenced_max
;
124 if (stat("/var/lib/machines.raw", &st
) >= 0) {
125 if (size
== (uint64_t) -1 || (uint64_t) st
.st_size
< size
)
129 return sd_bus_message_append(reply
, "t", size
);
132 static int method_get_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
133 _cleanup_free_
char *p
= NULL
;
134 Manager
*m
= userdata
;
142 r
= sd_bus_message_read(message
, "s", &name
);
146 machine
= hashmap_get(m
->machines
, name
);
148 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
150 p
= machine_bus_path(machine
);
154 return sd_bus_reply_method_return(message
, "o", p
);
157 static int method_get_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
158 _cleanup_free_
char *p
= NULL
;
159 Manager
*m
= userdata
;
166 r
= sd_bus_message_read(message
, "s", &name
);
170 r
= image_find(name
, NULL
);
172 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
176 p
= image_bus_path(name
);
180 return sd_bus_reply_method_return(message
, "o", p
);
183 static int method_get_machine_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
184 _cleanup_free_
char *p
= NULL
;
185 Manager
*m
= userdata
;
186 Machine
*machine
= NULL
;
193 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
195 r
= sd_bus_message_read(message
, "u", &pid
);
200 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
202 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
206 r
= sd_bus_creds_get_pid(creds
, &pid
);
211 r
= manager_get_machine_by_pid(m
, pid
, &machine
);
215 return sd_bus_error_setf(error
, BUS_ERROR_NO_MACHINE_FOR_PID
, "PID "PID_FMT
" does not belong to any known machine", pid
);
217 p
= machine_bus_path(machine
);
221 return sd_bus_reply_method_return(message
, "o", p
);
224 static int method_list_machines(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
225 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
226 Manager
*m
= userdata
;
234 r
= sd_bus_message_new_method_return(message
, &reply
);
236 return sd_bus_error_set_errno(error
, r
);
238 r
= sd_bus_message_open_container(reply
, 'a', "(ssso)");
240 return sd_bus_error_set_errno(error
, r
);
242 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
243 _cleanup_free_
char *p
= NULL
;
245 p
= machine_bus_path(machine
);
249 r
= sd_bus_message_append(reply
, "(ssso)",
251 strempty(machine_class_to_string(machine
->class)),
255 return sd_bus_error_set_errno(error
, r
);
258 r
= sd_bus_message_close_container(reply
);
260 return sd_bus_error_set_errno(error
, r
);
262 return sd_bus_send(NULL
, reply
, NULL
);
265 static int method_create_or_register_machine(Manager
*manager
, sd_bus_message
*message
, bool read_network
, Machine
**_m
, sd_bus_error
*error
) {
266 const char *name
, *service
, *class, *root_directory
;
267 const int32_t *netif
= NULL
;
273 size_t n
, n_netif
= 0;
280 r
= sd_bus_message_read(message
, "s", &name
);
283 if (!machine_name_is_valid(name
))
284 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
286 r
= sd_bus_message_read_array(message
, 'y', &v
, &n
);
294 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
296 r
= sd_bus_message_read(message
, "ssus", &service
, &class, &leader
, &root_directory
);
303 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
307 n_netif
/= sizeof(int32_t);
309 for (i
= 0; i
< n_netif
; i
++) {
311 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
316 c
= _MACHINE_CLASS_INVALID
;
318 c
= machine_class_from_string(class);
320 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
324 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
326 if (!isempty(root_directory
) && !path_is_absolute(root_directory
))
327 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root directory must be empty or an absolute path");
330 _cleanup_bus_creds_unref_ sd_bus_creds
*creds
= NULL
;
332 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
336 assert_cc(sizeof(uint32_t) == sizeof(pid_t
));
338 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
343 if (hashmap_get(manager
->machines
, name
))
344 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
346 r
= manager_add_machine(manager
, name
, &m
);
354 if (!isempty(service
)) {
355 m
->service
= strdup(service
);
362 if (!isempty(root_directory
)) {
363 m
->root_directory
= strdup(root_directory
);
364 if (!m
->root_directory
) {
371 assert_cc(sizeof(int32_t) == sizeof(int));
372 m
->netif
= memdup(netif
, sizeof(int32_t) * n_netif
);
378 m
->n_netif
= n_netif
;
386 machine_add_to_gc_queue(m
);
390 static int method_create_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
391 Manager
*manager
= userdata
;
398 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
402 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
406 r
= machine_start(m
, message
, error
);
410 m
->create_message
= sd_bus_message_ref(message
);
414 machine_add_to_gc_queue(m
);
418 static int method_create_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
419 return method_create_machine_internal(message
, true, userdata
, error
);
422 static int method_create_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
423 return method_create_machine_internal(message
, false, userdata
, error
);
426 static int method_register_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
427 Manager
*manager
= userdata
;
428 _cleanup_free_
char *p
= NULL
;
435 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
439 r
= cg_pid_get_unit(m
->leader
, &m
->unit
);
441 r
= sd_bus_error_set_errnof(error
, r
, "Failed to determine unit of process "PID_FMT
" : %s", m
->leader
, strerror(-r
));
445 r
= machine_start(m
, NULL
, error
);
449 p
= machine_bus_path(m
);
455 return sd_bus_reply_method_return(message
, "o", p
);
458 machine_add_to_gc_queue(m
);
462 static int method_register_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
463 return method_register_machine_internal(message
, true, userdata
, error
);
466 static int method_register_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
467 return method_register_machine_internal(message
, false, userdata
, error
);
470 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
471 Manager
*m
= userdata
;
479 r
= sd_bus_message_read(message
, "s", &name
);
481 return sd_bus_error_set_errno(error
, r
);
483 machine
= hashmap_get(m
->machines
, name
);
485 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
487 return bus_machine_method_terminate(message
, machine
, error
);
490 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
491 Manager
*m
= userdata
;
499 r
= sd_bus_message_read(message
, "s", &name
);
501 return sd_bus_error_set_errno(error
, r
);
503 machine
= hashmap_get(m
->machines
, name
);
505 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
507 return bus_machine_method_kill(message
, machine
, error
);
510 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
511 Manager
*m
= userdata
;
519 r
= sd_bus_message_read(message
, "s", &name
);
521 return sd_bus_error_set_errno(error
, r
);
523 machine
= hashmap_get(m
->machines
, name
);
525 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
527 return bus_machine_method_get_addresses(message
, machine
, error
);
530 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
531 Manager
*m
= userdata
;
539 r
= sd_bus_message_read(message
, "s", &name
);
541 return sd_bus_error_set_errno(error
, r
);
543 machine
= hashmap_get(m
->machines
, name
);
545 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
547 return bus_machine_method_get_os_release(message
, machine
, error
);
550 static int method_list_images(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
551 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
552 _cleanup_(image_hashmap_freep
) Hashmap
*images
= NULL
;
553 Manager
*m
= userdata
;
561 images
= hashmap_new(&string_hash_ops
);
565 r
= image_discover(images
);
569 r
= sd_bus_message_new_method_return(message
, &reply
);
573 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
577 HASHMAP_FOREACH(image
, images
, i
) {
578 _cleanup_free_
char *p
= NULL
;
580 p
= image_bus_path(image
->name
);
584 r
= sd_bus_message_append(reply
, "(ssbttto)",
586 image_type_to_string(image
->type
),
596 r
= sd_bus_message_close_container(reply
);
600 return sd_bus_send(NULL
, reply
, NULL
);
603 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
604 Manager
*m
= userdata
;
612 r
= sd_bus_message_read(message
, "s", &name
);
614 return sd_bus_error_set_errno(error
, r
);
616 machine
= hashmap_get(m
->machines
, name
);
618 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
620 return bus_machine_method_open_pty(message
, machine
, error
);
623 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
624 Manager
*m
= userdata
;
632 r
= sd_bus_message_read(message
, "s", &name
);
636 machine
= hashmap_get(m
->machines
, name
);
638 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
640 return bus_machine_method_open_login(message
, machine
, error
);
643 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
644 Manager
*m
= userdata
;
653 r
= sd_bus_message_read(message
, "s", &name
);
657 machine
= hashmap_get(m
->machines
, name
);
659 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
661 return bus_machine_method_open_shell(message
, machine
, error
);
664 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
665 Manager
*m
= userdata
;
673 r
= sd_bus_message_read(message
, "s", &name
);
677 machine
= hashmap_get(m
->machines
, name
);
679 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
681 return bus_machine_method_bind_mount(message
, machine
, error
);
684 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
685 Manager
*m
= userdata
;
693 r
= sd_bus_message_read(message
, "s", &name
);
697 machine
= hashmap_get(m
->machines
, name
);
699 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
701 return bus_machine_method_copy(message
, machine
, error
);
704 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
705 _cleanup_(image_unrefp
) Image
* i
= NULL
;
711 r
= sd_bus_message_read(message
, "s", &name
);
715 if (!image_name_is_valid(name
))
716 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
718 r
= image_find(name
, &i
);
722 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
724 i
->userdata
= userdata
;
725 return bus_image_method_remove(message
, i
, error
);
728 static int method_rename_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
729 _cleanup_(image_unrefp
) Image
* i
= NULL
;
730 const char *old_name
;
735 r
= sd_bus_message_read(message
, "s", &old_name
);
739 if (!image_name_is_valid(old_name
))
740 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", old_name
);
742 r
= image_find(old_name
, &i
);
746 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
748 i
->userdata
= userdata
;
749 return bus_image_method_rename(message
, i
, error
);
752 static int method_clone_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
753 _cleanup_(image_unrefp
) Image
*i
= NULL
;
754 const char *old_name
;
759 r
= sd_bus_message_read(message
, "s", &old_name
);
763 if (!image_name_is_valid(old_name
))
764 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", old_name
);
766 r
= image_find(old_name
, &i
);
770 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", old_name
);
772 i
->userdata
= userdata
;
773 return bus_image_method_clone(message
, i
, error
);
776 static int method_mark_image_read_only(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
777 _cleanup_(image_unrefp
) Image
*i
= NULL
;
783 r
= sd_bus_message_read(message
, "s", &name
);
787 if (!image_name_is_valid(name
))
788 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
790 r
= image_find(name
, &i
);
794 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
796 i
->userdata
= userdata
;
797 return bus_image_method_mark_read_only(message
, i
, error
);
800 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
801 Manager
*m
= userdata
;
807 r
= sd_bus_message_read(message
, "t", &limit
);
811 r
= bus_verify_polkit_async(
814 "org.freedesktop.machine1.manage-machines",
823 return 1; /* Will call us back */
825 /* Set up the machine directory if necessary */
826 r
= setup_machine_directory(limit
, error
);
830 r
= btrfs_resize_loopback("/var/lib/machines", limit
, false);
832 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
833 if (r
< 0 && r
!= -ENODEV
) /* ignore ENODEV, as that's what is returned if the file system is not on loopback */
834 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust loopback limit: %m");
836 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
838 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
840 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
842 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
844 return sd_bus_reply_method_return(message
, NULL
);
847 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
848 _cleanup_(image_unrefp
) Image
*i
= NULL
;
854 r
= sd_bus_message_read(message
, "s", &name
);
858 if (!image_name_is_valid(name
))
859 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
861 r
= image_find(name
, &i
);
865 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
867 i
->userdata
= userdata
;
868 return bus_image_method_set_limit(message
, i
, error
);
871 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
872 _cleanup_fclose_
FILE *f
= NULL
;
873 Manager
*m
= userdata
;
874 const char *name
, *p
;
879 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
883 if (!uid_is_valid(uid
))
884 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
886 machine
= hashmap_get(m
->machines
, name
);
888 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
890 if (machine
->class != MACHINE_CONTAINER
)
891 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
893 p
= procfs_file_alloca(machine
->leader
, "uid_map");
899 uid_t uid_base
, uid_shift
, uid_range
, converted
;
903 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
904 if (k
< 0 && feof(f
))
907 if (ferror(f
) && errno
!= 0)
913 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
916 converted
= uid
- uid_base
+ uid_shift
;
917 if (!uid_is_valid(converted
))
918 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
920 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
923 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
926 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
927 Manager
*m
= userdata
;
933 r
= sd_bus_message_read(message
, "u", &uid
);
936 if (!uid_is_valid(uid
))
937 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
939 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
941 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
942 _cleanup_fclose_
FILE *f
= NULL
;
943 char p
[strlen("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
945 if (machine
->class != MACHINE_CONTAINER
)
948 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
951 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
956 _cleanup_free_
char *o
= NULL
;
957 uid_t uid_base
, uid_shift
, uid_range
, converted
;
961 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
962 if (k
< 0 && feof(f
))
965 if (ferror(f
) && errno
!= 0)
971 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
974 converted
= (uid
- uid_shift
+ uid_base
);
975 if (!uid_is_valid(converted
))
976 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
978 o
= machine_bus_path(machine
);
982 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
986 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
989 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
990 _cleanup_fclose_
FILE *f
= NULL
;
991 Manager
*m
= groupdata
;
992 const char *name
, *p
;
997 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
1001 if (!gid_is_valid(gid
))
1002 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1004 machine
= hashmap_get(m
->machines
, name
);
1006 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1008 if (machine
->class != MACHINE_CONTAINER
)
1009 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1011 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1017 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1021 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1022 if (k
< 0 && feof(f
))
1025 if (ferror(f
) && errno
!= 0)
1031 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1034 converted
= gid
- gid_base
+ gid_shift
;
1035 if (!gid_is_valid(converted
))
1036 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1038 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1041 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1044 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1045 Manager
*m
= groupdata
;
1051 r
= sd_bus_message_read(message
, "u", &gid
);
1054 if (!gid_is_valid(gid
))
1055 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1057 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1059 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1060 _cleanup_fclose_
FILE *f
= NULL
;
1061 char p
[strlen("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1063 if (machine
->class != MACHINE_CONTAINER
)
1066 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1069 log_warning_errno(errno
, "Failed top open %s, ignoring,", p
);
1074 _cleanup_free_
char *o
= NULL
;
1075 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1079 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1080 if (k
< 0 && feof(f
))
1083 if (ferror(f
) && errno
!= 0)
1089 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1092 converted
= (gid
- gid_shift
+ gid_base
);
1093 if (!gid_is_valid(converted
))
1094 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1096 o
= machine_bus_path(machine
);
1100 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1104 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1107 const sd_bus_vtable manager_vtable
[] = {
1108 SD_BUS_VTABLE_START(0),
1109 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1110 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1111 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1112 SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1113 SD_BUS_METHOD("GetImage", "s", "o", method_get_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1114 SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid
, SD_BUS_VTABLE_UNPRIVILEGED
),
1115 SD_BUS_METHOD("ListMachines", NULL
, "a(ssso)", method_list_machines
, SD_BUS_VTABLE_UNPRIVILEGED
),
1116 SD_BUS_METHOD("ListImages", NULL
, "a(ssbttto)", method_list_images
, SD_BUS_VTABLE_UNPRIVILEGED
),
1117 SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine
, 0),
1118 SD_BUS_METHOD("CreateMachineWithNetwork", "sayssusaia(sv)", "o", method_create_machine_with_network
, 0),
1119 SD_BUS_METHOD("RegisterMachine", "sayssus", "o", method_register_machine
, 0),
1120 SD_BUS_METHOD("RegisterMachineWithNetwork", "sayssusai", "o", method_register_machine_with_network
, 0),
1121 SD_BUS_METHOD("TerminateMachine", "s", NULL
, method_terminate_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1122 SD_BUS_METHOD("KillMachine", "ssi", NULL
, method_kill_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1123 SD_BUS_METHOD("GetMachineAddresses", "s", "a(iay)", method_get_machine_addresses
, SD_BUS_VTABLE_UNPRIVILEGED
),
1124 SD_BUS_METHOD("GetMachineOSRelease", "s", "a{ss}", method_get_machine_os_release
, SD_BUS_VTABLE_UNPRIVILEGED
),
1125 SD_BUS_METHOD("OpenMachinePTY", "s", "hs", method_open_machine_pty
, 0),
1126 SD_BUS_METHOD("OpenMachineLogin", "s", "hs", method_open_machine_login
, SD_BUS_VTABLE_UNPRIVILEGED
),
1127 SD_BUS_METHOD("OpenMachineShell", "sssasas", "hs", method_open_machine_shell
, SD_BUS_VTABLE_UNPRIVILEGED
),
1128 SD_BUS_METHOD("BindMountMachine", "sssbb", NULL
, method_bind_mount_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1129 SD_BUS_METHOD("CopyFromMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1130 SD_BUS_METHOD("CopyToMachine", "sss", NULL
, method_copy_machine
, SD_BUS_VTABLE_UNPRIVILEGED
),
1131 SD_BUS_METHOD("RemoveImage", "s", NULL
, method_remove_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1132 SD_BUS_METHOD("RenameImage", "ss", NULL
, method_rename_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1133 SD_BUS_METHOD("CloneImage", "ssb", NULL
, method_clone_image
, SD_BUS_VTABLE_UNPRIVILEGED
),
1134 SD_BUS_METHOD("MarkImageReadOnly", "sb", NULL
, method_mark_image_read_only
, SD_BUS_VTABLE_UNPRIVILEGED
),
1135 SD_BUS_METHOD("SetPoolLimit", "t", NULL
, method_set_pool_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1136 SD_BUS_METHOD("SetImageLimit", "st", NULL
, method_set_image_limit
, SD_BUS_VTABLE_UNPRIVILEGED
),
1137 SD_BUS_METHOD("MapFromMachineUser", "su", "u", method_map_from_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1138 SD_BUS_METHOD("MapToMachineUser", "u", "sou", method_map_to_machine_user
, SD_BUS_VTABLE_UNPRIVILEGED
),
1139 SD_BUS_METHOD("MapFromMachineGroup", "su", "u", method_map_from_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1140 SD_BUS_METHOD("MapToMachineGroup", "u", "sou", method_map_to_machine_group
, SD_BUS_VTABLE_UNPRIVILEGED
),
1141 SD_BUS_SIGNAL("MachineNew", "so", 0),
1142 SD_BUS_SIGNAL("MachineRemoved", "so", 0),
1146 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1147 const char *path
, *result
, *unit
;
1148 Manager
*m
= userdata
;
1156 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1158 bus_log_parse_error(r
);
1162 machine
= hashmap_get(m
->machine_units
, unit
);
1166 if (streq_ptr(path
, machine
->scope_job
)) {
1167 machine
->scope_job
= mfree(machine
->scope_job
);
1169 if (machine
->started
) {
1170 if (streq(result
, "done"))
1171 machine_send_create_reply(machine
, NULL
);
1173 _cleanup_bus_error_free_ sd_bus_error e
= SD_BUS_ERROR_NULL
;
1175 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1177 machine_send_create_reply(machine
, &e
);
1181 machine_save(machine
);
1184 machine_add_to_gc_queue(machine
);
1188 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1189 _cleanup_free_
char *unit
= NULL
;
1191 Manager
*m
= userdata
;
1198 path
= sd_bus_message_get_path(message
);
1202 r
= unit_name_from_dbus_path(path
, &unit
);
1203 if (r
== -EINVAL
) /* not for a unit */
1210 machine
= hashmap_get(m
->machine_units
, unit
);
1214 machine_add_to_gc_queue(machine
);
1218 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1219 const char *path
, *unit
;
1220 Manager
*m
= userdata
;
1227 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1229 bus_log_parse_error(r
);
1233 machine
= hashmap_get(m
->machine_units
, unit
);
1237 machine_add_to_gc_queue(machine
);
1241 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1242 Manager
*m
= userdata
;
1250 r
= sd_bus_message_read(message
, "b", &b
);
1252 bus_log_parse_error(r
);
1258 /* systemd finished reloading, let's recheck all our machines */
1259 log_debug("System manager has been reloaded, rechecking machines...");
1261 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1262 machine_add_to_gc_queue(machine
);
1267 int manager_start_scope(
1272 const char *description
,
1273 sd_bus_message
*more_properties
,
1274 sd_bus_error
*error
,
1277 _cleanup_bus_message_unref_ sd_bus_message
*m
= NULL
, *reply
= NULL
;
1284 r
= sd_bus_message_new_method_call(
1287 "org.freedesktop.systemd1",
1288 "/org/freedesktop/systemd1",
1289 "org.freedesktop.systemd1.Manager",
1290 "StartTransientUnit");
1294 r
= sd_bus_message_append(m
, "ss", strempty(scope
), "fail");
1298 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
1302 if (!isempty(slice
)) {
1303 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
1308 if (!isempty(description
)) {
1309 r
= sd_bus_message_append(m
, "(sv)", "Description", "s", description
);
1314 r
= sd_bus_message_append(m
, "(sv)", "PIDs", "au", 1, pid
);
1318 r
= sd_bus_message_append(m
, "(sv)", "Delegate", "b", 1);
1322 if (more_properties
) {
1323 r
= sd_bus_message_copy(m
, more_properties
, true);
1328 r
= sd_bus_message_close_container(m
);
1332 r
= sd_bus_message_append(m
, "a(sa(sv))", 0);
1336 r
= sd_bus_call(manager
->bus
, m
, 0, error
, &reply
);
1344 r
= sd_bus_message_read(reply
, "o", &j
);
1358 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1359 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1365 r
= sd_bus_call_method(
1367 "org.freedesktop.systemd1",
1368 "/org/freedesktop/systemd1",
1369 "org.freedesktop.systemd1.Manager",
1373 "ss", unit
, "fail");
1375 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1376 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1381 sd_bus_error_free(error
);
1392 r
= sd_bus_message_read(reply
, "o", &j
);
1406 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1410 return sd_bus_call_method(
1412 "org.freedesktop.systemd1",
1413 "/org/freedesktop/systemd1",
1414 "org.freedesktop.systemd1.Manager",
1418 "ssi", unit
, "all", signo
);
1421 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1422 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1423 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1424 _cleanup_free_
char *path
= NULL
;
1431 path
= unit_dbus_path_from_name(unit
);
1435 r
= sd_bus_get_property(
1437 "org.freedesktop.systemd1",
1439 "org.freedesktop.systemd1.Unit",
1445 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1446 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1449 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1450 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1456 r
= sd_bus_message_read(reply
, "s", &state
);
1460 return !STR_IN_SET(state
, "inactive", "failed");
1463 int manager_job_is_active(Manager
*manager
, const char *path
) {
1464 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
1465 _cleanup_bus_message_unref_ sd_bus_message
*reply
= NULL
;
1471 r
= sd_bus_get_property(
1473 "org.freedesktop.systemd1",
1475 "org.freedesktop.systemd1.Job",
1481 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1482 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1485 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1491 /* We don't actually care about the state really. The fact
1492 * that we could read the job state is enough for us */
1497 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1505 mm
= hashmap_get(m
->machine_leaders
, UINT_TO_PTR(pid
));
1507 _cleanup_free_
char *unit
= NULL
;
1509 r
= cg_pid_get_unit(pid
, &unit
);
1511 mm
= hashmap_get(m
->machine_units
, unit
);
1520 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1526 machine
= hashmap_get(m
->machines
, name
);
1528 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1534 *_machine
= machine
;