1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
9 #include "btrfs-util.h"
10 #include "bus-common-errors.h"
11 #include "bus-get-properties.h"
12 #include "bus-locator.h"
13 #include "bus-polkit.h"
14 #include "cgroup-util.h"
15 #include "errno-util.h"
18 #include "format-util.h"
19 #include "hostname-util.h"
20 #include "image-dbus.h"
22 #include "machine-dbus.h"
23 #include "machine-image.h"
24 #include "machine-pool.h"
26 #include "missing_capability.h"
27 #include "path-util.h"
28 #include "process-util.h"
29 #include "stdio-util.h"
31 #include "tmpfile-util.h"
32 #include "unit-name.h"
33 #include "user-util.h"
35 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path
, "s", "/var/lib/machines");
37 static int property_get_pool_usage(
40 const char *interface
,
42 sd_bus_message
*reply
,
44 sd_bus_error
*error
) {
46 _cleanup_close_
int fd
= -1;
47 uint64_t usage
= (uint64_t) -1;
52 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
56 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
60 return sd_bus_message_append(reply
, "t", usage
);
63 static int property_get_pool_limit(
66 const char *interface
,
68 sd_bus_message
*reply
,
70 sd_bus_error
*error
) {
72 _cleanup_close_
int fd
= -1;
73 uint64_t size
= (uint64_t) -1;
78 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
82 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
83 size
= q
.referenced_max
;
86 return sd_bus_message_append(reply
, "t", size
);
89 static int method_get_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
90 _cleanup_free_
char *p
= NULL
;
91 Manager
*m
= userdata
;
99 r
= sd_bus_message_read(message
, "s", &name
);
103 machine
= hashmap_get(m
->machines
, name
);
105 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
107 p
= machine_bus_path(machine
);
111 return sd_bus_reply_method_return(message
, "o", p
);
114 static int method_get_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
115 _cleanup_free_
char *p
= NULL
;
116 _unused_ Manager
*m
= userdata
;
123 r
= sd_bus_message_read(message
, "s", &name
);
127 r
= image_find(IMAGE_MACHINE
, name
, NULL
);
129 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
133 p
= image_bus_path(name
);
137 return sd_bus_reply_method_return(message
, "o", p
);
140 static int method_get_machine_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
141 _cleanup_free_
char *p
= NULL
;
142 Manager
*m
= userdata
;
143 Machine
*machine
= NULL
;
150 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
152 r
= sd_bus_message_read(message
, "u", &pid
);
160 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
162 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
166 r
= sd_bus_creds_get_pid(creds
, &pid
);
171 r
= manager_get_machine_by_pid(m
, pid
, &machine
);
175 return sd_bus_error_setf(error
, BUS_ERROR_NO_MACHINE_FOR_PID
, "PID "PID_FMT
" does not belong to any known machine", pid
);
177 p
= machine_bus_path(machine
);
181 return sd_bus_reply_method_return(message
, "o", p
);
184 static int method_list_machines(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
185 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
186 Manager
*m
= userdata
;
194 r
= sd_bus_message_new_method_return(message
, &reply
);
196 return sd_bus_error_set_errno(error
, r
);
198 r
= sd_bus_message_open_container(reply
, 'a', "(ssso)");
200 return sd_bus_error_set_errno(error
, r
);
202 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
203 _cleanup_free_
char *p
= NULL
;
205 p
= machine_bus_path(machine
);
209 r
= sd_bus_message_append(reply
, "(ssso)",
211 strempty(machine_class_to_string(machine
->class)),
215 return sd_bus_error_set_errno(error
, r
);
218 r
= sd_bus_message_close_container(reply
);
220 return sd_bus_error_set_errno(error
, r
);
222 return sd_bus_send(NULL
, reply
, NULL
);
225 static int method_create_or_register_machine(Manager
*manager
, sd_bus_message
*message
, bool read_network
, Machine
**_m
, sd_bus_error
*error
) {
226 const char *name
, *service
, *class, *root_directory
;
227 const int32_t *netif
= NULL
;
233 size_t n
, n_netif
= 0;
240 r
= sd_bus_message_read(message
, "s", &name
);
243 if (!machine_name_is_valid(name
))
244 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
246 r
= sd_bus_message_read_array(message
, 'y', &v
, &n
);
254 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
256 r
= sd_bus_message_read(message
, "ssus", &service
, &class, &leader
, &root_directory
);
263 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
267 n_netif
/= sizeof(int32_t);
269 for (i
= 0; i
< n_netif
; i
++) {
271 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
276 c
= _MACHINE_CLASS_INVALID
;
278 c
= machine_class_from_string(class);
280 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
284 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
286 if (!isempty(root_directory
) && !path_is_absolute(root_directory
))
287 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root directory must be empty or an absolute path");
290 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
292 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
296 assert_cc(sizeof(uint32_t) == sizeof(pid_t
));
298 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
303 if (hashmap_get(manager
->machines
, name
))
304 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
306 r
= manager_add_machine(manager
, name
, &m
);
314 if (!isempty(service
)) {
315 m
->service
= strdup(service
);
322 if (!isempty(root_directory
)) {
323 m
->root_directory
= strdup(root_directory
);
324 if (!m
->root_directory
) {
331 assert_cc(sizeof(int32_t) == sizeof(int));
332 m
->netif
= memdup(netif
, sizeof(int32_t) * n_netif
);
338 m
->n_netif
= n_netif
;
346 machine_add_to_gc_queue(m
);
350 static int method_create_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
351 Manager
*manager
= userdata
;
358 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
362 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
366 r
= machine_start(m
, message
, error
);
370 m
->create_message
= sd_bus_message_ref(message
);
374 machine_add_to_gc_queue(m
);
378 static int method_create_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
379 return method_create_machine_internal(message
, true, userdata
, error
);
382 static int method_create_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
383 return method_create_machine_internal(message
, false, userdata
, error
);
386 static int method_register_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
387 Manager
*manager
= userdata
;
388 _cleanup_free_
char *p
= NULL
;
395 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
399 r
= cg_pid_get_unit(m
->leader
, &m
->unit
);
401 r
= sd_bus_error_set_errnof(error
, r
,
402 "Failed to determine unit of process "PID_FMT
" : %m",
407 r
= machine_start(m
, NULL
, error
);
411 p
= machine_bus_path(m
);
417 return sd_bus_reply_method_return(message
, "o", p
);
420 machine_add_to_gc_queue(m
);
424 static int method_register_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
425 return method_register_machine_internal(message
, true, userdata
, error
);
428 static int method_register_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
429 return method_register_machine_internal(message
, false, userdata
, error
);
432 static int redirect_method_to_machine(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
441 r
= sd_bus_message_read(message
, "s", &name
);
443 return sd_bus_error_set_errno(error
, r
);
445 machine
= hashmap_get(m
->machines
, name
);
447 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
449 return method(message
, machine
, error
);
452 static int method_unregister_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
453 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_unregister
);
456 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
457 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_terminate
);
460 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
461 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_kill
);
464 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
465 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_addresses
);
468 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
469 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_os_release
);
472 static int method_list_images(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
473 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
474 _cleanup_hashmap_free_ Hashmap
*images
= NULL
;
475 _unused_ Manager
*m
= userdata
;
483 images
= hashmap_new(&image_hash_ops
);
487 r
= image_discover(IMAGE_MACHINE
, images
);
491 r
= sd_bus_message_new_method_return(message
, &reply
);
495 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
499 HASHMAP_FOREACH(image
, images
, i
) {
500 _cleanup_free_
char *p
= NULL
;
502 p
= image_bus_path(image
->name
);
506 r
= sd_bus_message_append(reply
, "(ssbttto)",
508 image_type_to_string(image
->type
),
518 r
= sd_bus_message_close_container(reply
);
522 return sd_bus_send(NULL
, reply
, NULL
);
525 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
526 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_pty
);
529 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
530 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_login
);
533 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
534 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_shell
);
537 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
538 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_bind_mount
);
541 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
542 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_copy
);
545 static int method_open_machine_root_directory(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
546 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_root_directory
);
549 static int method_get_machine_uid_shift(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
550 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_uid_shift
);
553 static int redirect_method_to_image(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
554 _cleanup_(image_unrefp
) Image
* i
= NULL
;
562 r
= sd_bus_message_read(message
, "s", &name
);
566 if (!image_name_is_valid(name
))
567 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
569 r
= image_find(IMAGE_MACHINE
, name
, &i
);
571 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
576 return method(message
, i
, error
);
579 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
580 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_remove
);
583 static int method_rename_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
584 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_rename
);
587 static int method_clone_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
588 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_clone
);
591 static int method_mark_image_read_only(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
592 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_mark_read_only
);
595 static int method_get_image_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
596 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_hostname
);
599 static int method_get_image_machine_id(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
600 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_id
);
603 static int method_get_image_machine_info(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
604 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_info
);
607 static int method_get_image_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
608 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_os_release
);
611 static int clean_pool_done(Operation
*operation
, int ret
, sd_bus_error
*error
) {
612 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
613 _cleanup_fclose_
FILE *f
= NULL
;
619 assert(operation
->extra_fd
>= 0);
621 if (lseek(operation
->extra_fd
, 0, SEEK_SET
) == (off_t
) -1)
624 f
= take_fdopen(&operation
->extra_fd
, "r");
628 /* The resulting temporary file starts with a boolean value that indicates success or not. */
630 n
= fread(&success
, 1, sizeof(success
), f
);
631 if (n
!= sizeof(success
))
632 return ret
< 0 ? ret
: errno_or_else(EIO
);
635 _cleanup_free_
char *name
= NULL
;
637 /* The clean-up operation failed. In this case the resulting temporary file should contain a boolean
638 * set to false followed by the name of the failed image. Let's try to read this and use it for the
639 * error message. If we can't read it, don't mind, and return the naked error. */
641 if (success
) /* The resulting temporary file could not be updated, ignore it. */
644 r
= read_nul_string(f
, LONG_LINE_MAX
, &name
);
645 if (r
<= 0) /* Same here... */
648 return sd_bus_error_set_errnof(error
, ret
, "Failed to remove image %s: %m", name
);
653 r
= sd_bus_message_new_method_return(operation
->message
, &reply
);
657 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
661 /* On success the resulting temporary file will contain a list of image names that were removed followed by
662 * their size on disk. Let's read that and turn it into a bus message. */
664 _cleanup_free_
char *name
= NULL
;
667 r
= read_nul_string(f
, LONG_LINE_MAX
, &name
);
670 if (r
== 0) /* reached the end */
674 n
= fread(&size
, 1, sizeof(size
), f
);
675 if (n
!= sizeof(size
))
676 return errno_or_else(EIO
);
678 r
= sd_bus_message_append(reply
, "(st)", name
, size
);
683 r
= sd_bus_message_close_container(reply
);
687 return sd_bus_send(NULL
, reply
, NULL
);
690 static int method_clean_pool(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
696 _cleanup_close_pair_
int errno_pipe_fd
[2] = { -1, -1 };
697 _cleanup_close_
int result_fd
= -1;
698 Manager
*m
= userdata
;
699 Operation
*operation
;
706 if (m
->n_operations
>= OPERATIONS_MAX
)
707 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Too many ongoing operations.");
709 r
= sd_bus_message_read(message
, "s", &mm
);
713 if (streq(mm
, "all"))
715 else if (streq(mm
, "hidden"))
716 mode
= REMOVE_HIDDEN
;
718 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mode '%s'.", mm
);
720 r
= bus_verify_polkit_async(
723 "org.freedesktop.machine1.manage-machines",
732 return 1; /* Will call us back */
734 if (pipe2(errno_pipe_fd
, O_CLOEXEC
|O_NONBLOCK
) < 0)
735 return sd_bus_error_set_errnof(error
, errno
, "Failed to create pipe: %m");
737 /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this
738 * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this
740 result_fd
= open_tmpfile_unlinkable(NULL
, O_RDWR
|O_CLOEXEC
);
744 /* This might be a slow operation, run it asynchronously in a background process */
745 r
= safe_fork("(sd-clean)", FORK_RESET_SIGNALS
, &child
);
747 return sd_bus_error_set_errnof(error
, r
, "Failed to fork(): %m");
749 _cleanup_hashmap_free_ Hashmap
*images
= NULL
;
755 errno_pipe_fd
[0] = safe_close(errno_pipe_fd
[0]);
757 images
= hashmap_new(&image_hash_ops
);
763 r
= image_discover(IMAGE_MACHINE
, images
);
767 l
= write(result_fd
, &success
, sizeof(success
));
773 HASHMAP_FOREACH(image
, images
, i
) {
775 /* We can't remove vendor images (i.e. those in /usr) */
776 if (IMAGE_IS_VENDOR(image
))
779 if (IMAGE_IS_HOST(image
))
782 if (mode
== REMOVE_HIDDEN
&& !IMAGE_IS_HIDDEN(image
))
785 r
= image_remove(image
);
786 if (r
== -EBUSY
) /* keep images that are currently being used. */
789 /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */
791 (void) ftruncate(result_fd
, 0);
792 (void) lseek(result_fd
, 0, SEEK_SET
);
793 (void) write(result_fd
, &success
, sizeof(success
));
794 (void) write(result_fd
, image
->name
, strlen(image
->name
)+1);
798 l
= write(result_fd
, image
->name
, strlen(image
->name
)+1);
804 l
= write(result_fd
, &image
->usage_exclusive
, sizeof(image
->usage_exclusive
));
811 result_fd
= safe_close(result_fd
);
815 (void) write(errno_pipe_fd
[1], &r
, sizeof(r
));
819 errno_pipe_fd
[1] = safe_close(errno_pipe_fd
[1]);
821 /* The clean-up might take a while, hence install a watch on the child and return */
823 r
= operation_new(m
, NULL
, child
, message
, errno_pipe_fd
[0], &operation
);
825 (void) sigkill_wait(child
);
829 operation
->extra_fd
= result_fd
;
830 operation
->done
= clean_pool_done
;
833 errno_pipe_fd
[0] = -1;
838 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
839 Manager
*m
= userdata
;
845 r
= sd_bus_message_read(message
, "t", &limit
);
848 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
849 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
851 r
= bus_verify_polkit_async(
854 "org.freedesktop.machine1.manage-machines",
863 return 1; /* Will call us back */
865 /* Set up the machine directory if necessary */
866 r
= setup_machine_directory(error
);
870 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
872 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
874 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
876 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
878 return sd_bus_reply_method_return(message
, NULL
);
881 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
882 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_set_limit
);
885 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
886 Manager
*m
= userdata
;
893 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
897 if (!uid_is_valid(uid
))
898 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
900 machine
= hashmap_get(m
->machines
, name
);
902 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
904 if (machine
->class != MACHINE_CONTAINER
)
905 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
907 r
= machine_translate_uid(machine
, uid
, &converted
);
909 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
913 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
916 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
917 _cleanup_free_
char *o
= NULL
;
918 Manager
*m
= userdata
;
920 uid_t uid
, converted
;
923 r
= sd_bus_message_read(message
, "u", &uid
);
926 if (!uid_is_valid(uid
))
927 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
929 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
931 r
= manager_find_machine_for_uid(m
, uid
, &machine
, &converted
);
935 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
937 o
= machine_bus_path(machine
);
941 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
944 static int method_map_from_machine_group(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
945 Manager
*m
= userdata
;
952 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
956 if (!gid_is_valid(gid
))
957 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
959 machine
= hashmap_get(m
->machines
, name
);
961 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
963 if (machine
->class != MACHINE_CONTAINER
)
964 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
966 r
= machine_translate_gid(machine
, gid
, &converted
);
968 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
972 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
975 static int method_map_to_machine_group(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
976 _cleanup_free_
char *o
= NULL
;
977 Manager
*m
= userdata
;
979 gid_t gid
, converted
;
982 r
= sd_bus_message_read(message
, "u", &gid
);
985 if (!gid_is_valid(gid
))
986 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
988 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
990 r
= manager_find_machine_for_gid(m
, gid
, &machine
, &converted
);
994 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
996 o
= machine_bus_path(machine
);
1000 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1003 const sd_bus_vtable manager_vtable
[] = {
1004 SD_BUS_VTABLE_START(0),
1006 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1007 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1008 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1010 SD_BUS_METHOD_WITH_NAMES("GetMachine",
1014 SD_BUS_PARAM(machine
),
1016 SD_BUS_VTABLE_UNPRIVILEGED
),
1017 SD_BUS_METHOD_WITH_NAMES("GetImage",
1021 SD_BUS_PARAM(image
),
1023 SD_BUS_VTABLE_UNPRIVILEGED
),
1024 SD_BUS_METHOD_WITH_NAMES("GetMachineByPID",
1028 SD_BUS_PARAM(machine
),
1029 method_get_machine_by_pid
,
1030 SD_BUS_VTABLE_UNPRIVILEGED
),
1031 SD_BUS_METHOD_WITH_NAMES("ListMachines",
1034 SD_BUS_PARAM(machines
),
1035 method_list_machines
,
1036 SD_BUS_VTABLE_UNPRIVILEGED
),
1037 SD_BUS_METHOD_WITH_NAMES("ListImages",
1040 SD_BUS_PARAM(images
),
1042 SD_BUS_VTABLE_UNPRIVILEGED
),
1043 SD_BUS_METHOD_WITH_NAMES("CreateMachine",
1047 SD_BUS_PARAM(service
)
1049 SD_BUS_PARAM(leader
)
1050 SD_BUS_PARAM(root_directory
)
1051 SD_BUS_PARAM(scope_properties
),
1054 method_create_machine
, 0),
1055 SD_BUS_METHOD_WITH_NAMES("CreateMachineWithNetwork",
1059 SD_BUS_PARAM(service
)
1061 SD_BUS_PARAM(leader
)
1062 SD_BUS_PARAM(root_directory
)
1063 SD_BUS_PARAM(ifindices
)
1064 SD_BUS_PARAM(scope_properties
),
1067 method_create_machine_with_network
, 0),
1068 SD_BUS_METHOD_WITH_NAMES("RegisterMachine",
1072 SD_BUS_PARAM(service
)
1074 SD_BUS_PARAM(leader
)
1075 SD_BUS_PARAM(root_directory
),
1078 method_register_machine
, 0),
1079 SD_BUS_METHOD_WITH_NAMES("RegisterMachineWithNetwork",
1083 SD_BUS_PARAM(service
)
1085 SD_BUS_PARAM(leader
)
1086 SD_BUS_PARAM(root_directory
)
1087 SD_BUS_PARAM(ifindices
),
1090 method_register_machine_with_network
, 0),
1091 SD_BUS_METHOD_WITH_NAMES("UnregisterMachine",
1095 method_unregister_machine
,
1096 SD_BUS_VTABLE_UNPRIVILEGED
),
1097 SD_BUS_METHOD_WITH_NAMES("TerminateMachine",
1101 method_terminate_machine
,
1102 SD_BUS_VTABLE_UNPRIVILEGED
),
1103 SD_BUS_METHOD_WITH_NAMES("KillMachine",
1107 SD_BUS_PARAM(signal
),
1109 method_kill_machine
,
1110 SD_BUS_VTABLE_UNPRIVILEGED
),
1111 SD_BUS_METHOD_WITH_NAMES("GetMachineAddresses",
1115 SD_BUS_PARAM(addresses
),
1116 method_get_machine_addresses
,
1117 SD_BUS_VTABLE_UNPRIVILEGED
),
1118 SD_BUS_METHOD_WITH_NAMES("GetMachineOSRelease",
1122 SD_BUS_PARAM(fields
),
1123 method_get_machine_os_release
,
1124 SD_BUS_VTABLE_UNPRIVILEGED
),
1125 SD_BUS_METHOD_WITH_NAMES("OpenMachinePTY",
1130 SD_BUS_PARAM(pty_path
),
1131 method_open_machine_pty
,
1133 SD_BUS_METHOD_WITH_NAMES("OpenMachineLogin",
1138 SD_BUS_PARAM(pty_path
),
1139 method_open_machine_login
,
1140 SD_BUS_VTABLE_UNPRIVILEGED
),
1141 SD_BUS_METHOD_WITH_NAMES("OpenMachineShell",
1147 SD_BUS_PARAM(environment
),
1150 SD_BUS_PARAM(pty_path
),
1151 method_open_machine_shell
,
1152 SD_BUS_VTABLE_UNPRIVILEGED
),
1153 SD_BUS_METHOD_WITH_NAMES("BindMountMachine",
1156 SD_BUS_PARAM(source
)
1157 SD_BUS_PARAM(destination
)
1158 SD_BUS_PARAM(read_only
)
1159 SD_BUS_PARAM(mkdir
),
1161 method_bind_mount_machine
,
1162 SD_BUS_VTABLE_UNPRIVILEGED
),
1163 SD_BUS_METHOD_WITH_NAMES("CopyFromMachine",
1166 SD_BUS_PARAM(source
)
1167 SD_BUS_PARAM(destination
),
1169 method_copy_machine
,
1170 SD_BUS_VTABLE_UNPRIVILEGED
),
1171 SD_BUS_METHOD_WITH_NAMES("CopyToMachine",
1174 SD_BUS_PARAM(source
)
1175 SD_BUS_PARAM(destination
),
1177 method_copy_machine
,
1178 SD_BUS_VTABLE_UNPRIVILEGED
),
1179 SD_BUS_METHOD_WITH_NAMES("OpenMachineRootDirectory",
1184 method_open_machine_root_directory
,
1185 SD_BUS_VTABLE_UNPRIVILEGED
),
1186 SD_BUS_METHOD_WITH_NAMES("GetMachineUIDShift",
1190 SD_BUS_PARAM(shift
),
1191 method_get_machine_uid_shift
,
1192 SD_BUS_VTABLE_UNPRIVILEGED
),
1193 SD_BUS_METHOD_WITH_NAMES("RemoveImage",
1197 method_remove_image
,
1198 SD_BUS_VTABLE_UNPRIVILEGED
),
1199 SD_BUS_METHOD_WITH_NAMES("RenameImage",
1202 SD_BUS_PARAM(new_name
),
1204 method_rename_image
,
1205 SD_BUS_VTABLE_UNPRIVILEGED
),
1206 SD_BUS_METHOD_WITH_NAMES("CloneImage",
1209 SD_BUS_PARAM(new_name
)
1210 SD_BUS_PARAM(read_only
),
1213 SD_BUS_VTABLE_UNPRIVILEGED
),
1214 SD_BUS_METHOD_WITH_NAMES("MarkImageReadOnly",
1217 SD_BUS_PARAM(read_only
),
1219 method_mark_image_read_only
,
1220 SD_BUS_VTABLE_UNPRIVILEGED
),
1221 SD_BUS_METHOD_WITH_NAMES("GetImageHostname",
1225 SD_BUS_PARAM(hostname
),
1226 method_get_image_hostname
,
1227 SD_BUS_VTABLE_UNPRIVILEGED
),
1228 SD_BUS_METHOD_WITH_NAMES("GetImageMachineID",
1233 method_get_image_machine_id
,
1234 SD_BUS_VTABLE_UNPRIVILEGED
),
1235 SD_BUS_METHOD_WITH_NAMES("GetImageMachineInfo",
1239 SD_BUS_PARAM(machine_info
),
1240 method_get_image_machine_info
,
1241 SD_BUS_VTABLE_UNPRIVILEGED
),
1242 SD_BUS_METHOD_WITH_NAMES("GetImageOSRelease",
1246 SD_BUS_PARAM(os_release
),
1247 method_get_image_os_release
,
1248 SD_BUS_VTABLE_UNPRIVILEGED
),
1249 SD_BUS_METHOD_WITH_NAMES("SetPoolLimit",
1253 method_set_pool_limit
,
1254 SD_BUS_VTABLE_UNPRIVILEGED
),
1255 SD_BUS_METHOD_WITH_NAMES("SetImageLimit",
1260 method_set_image_limit
,
1261 SD_BUS_VTABLE_UNPRIVILEGED
),
1262 SD_BUS_METHOD_WITH_NAMES("CleanPool",
1266 SD_BUS_PARAM(images
),
1268 SD_BUS_VTABLE_UNPRIVILEGED
),
1269 SD_BUS_METHOD_WITH_NAMES("MapFromMachineUser",
1272 SD_BUS_PARAM(uid_inner
),
1274 SD_BUS_PARAM(uid_outer
),
1275 method_map_from_machine_user
,
1276 SD_BUS_VTABLE_UNPRIVILEGED
),
1277 SD_BUS_METHOD_WITH_NAMES("MapToMachineUser",
1279 SD_BUS_PARAM(uid_outer
),
1281 SD_BUS_PARAM(machine_name
)
1282 SD_BUS_PARAM(machine_path
)
1283 SD_BUS_PARAM(uid_inner
),
1284 method_map_to_machine_user
,
1285 SD_BUS_VTABLE_UNPRIVILEGED
),
1286 SD_BUS_METHOD_WITH_NAMES("MapFromMachineGroup",
1289 SD_BUS_PARAM(gid_inner
),
1291 SD_BUS_PARAM(gid_outer
),
1292 method_map_from_machine_group
,
1293 SD_BUS_VTABLE_UNPRIVILEGED
),
1294 SD_BUS_METHOD_WITH_NAMES("MapToMachineGroup",
1296 SD_BUS_PARAM(gid_outer
),
1298 SD_BUS_PARAM(machine_name
)
1299 SD_BUS_PARAM(machine_path
)
1300 SD_BUS_PARAM(gid_inner
),
1301 method_map_to_machine_group
,
1302 SD_BUS_VTABLE_UNPRIVILEGED
),
1304 SD_BUS_SIGNAL_WITH_NAMES("MachineNew",
1306 SD_BUS_PARAM(machine
)
1309 SD_BUS_SIGNAL_WITH_NAMES("MachineRemoved",
1311 SD_BUS_PARAM(machine
)
1318 const BusObjectImplementation manager_object
= {
1319 "/org/freedesktop/machine1",
1320 "org.freedesktop.machine1.Manager",
1321 .vtables
= BUS_VTABLES(manager_vtable
),
1322 .children
= BUS_IMPLEMENTATIONS( &machine_object
,
1326 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1327 const char *path
, *result
, *unit
;
1328 Manager
*m
= userdata
;
1336 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1338 bus_log_parse_error(r
);
1342 machine
= hashmap_get(m
->machine_units
, unit
);
1346 if (streq_ptr(path
, machine
->scope_job
)) {
1347 machine
->scope_job
= mfree(machine
->scope_job
);
1349 if (machine
->started
) {
1350 if (streq(result
, "done"))
1351 machine_send_create_reply(machine
, NULL
);
1353 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
1355 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1357 machine_send_create_reply(machine
, &e
);
1361 machine_save(machine
);
1364 machine_add_to_gc_queue(machine
);
1368 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1369 _cleanup_free_
char *unit
= NULL
;
1371 Manager
*m
= userdata
;
1378 path
= sd_bus_message_get_path(message
);
1382 r
= unit_name_from_dbus_path(path
, &unit
);
1383 if (r
== -EINVAL
) /* not for a unit */
1390 machine
= hashmap_get(m
->machine_units
, unit
);
1394 machine_add_to_gc_queue(machine
);
1398 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1399 const char *path
, *unit
;
1400 Manager
*m
= userdata
;
1407 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1409 bus_log_parse_error(r
);
1413 machine
= hashmap_get(m
->machine_units
, unit
);
1417 machine_add_to_gc_queue(machine
);
1421 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1422 Manager
*m
= userdata
;
1430 r
= sd_bus_message_read(message
, "b", &b
);
1432 bus_log_parse_error(r
);
1438 /* systemd finished reloading, let's recheck all our machines */
1439 log_debug("System manager has been reloaded, rechecking machines...");
1441 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1442 machine_add_to_gc_queue(machine
);
1447 int manager_unref_unit(
1450 sd_bus_error
*error
) {
1455 return bus_call_method(m
->bus
, bus_systemd_mgr
, "UnrefUnit", error
, NULL
, "s", unit
);
1458 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1459 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1465 r
= bus_call_method(manager
->bus
, bus_systemd_mgr
, "StopUnit", error
, &reply
, "ss", unit
, "fail");
1467 if (sd_bus_error_has_names(error
, BUS_ERROR_NO_SUCH_UNIT
,
1468 BUS_ERROR_LOAD_FAILED
)) {
1473 sd_bus_error_free(error
);
1484 r
= sd_bus_message_read(reply
, "o", &j
);
1498 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1502 return bus_call_method(manager
->bus
, bus_systemd_mgr
, "KillUnit", error
, NULL
, "ssi", unit
, "all", signo
);
1505 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1506 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1507 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1508 _cleanup_free_
char *path
= NULL
;
1515 path
= unit_dbus_path_from_name(unit
);
1519 r
= sd_bus_get_property(
1521 "org.freedesktop.systemd1",
1523 "org.freedesktop.systemd1.Unit",
1529 if (sd_bus_error_has_names(&error
, SD_BUS_ERROR_NO_REPLY
,
1530 SD_BUS_ERROR_DISCONNECTED
))
1533 if (sd_bus_error_has_names(&error
, BUS_ERROR_NO_SUCH_UNIT
,
1534 BUS_ERROR_LOAD_FAILED
))
1540 r
= sd_bus_message_read(reply
, "s", &state
);
1544 return !STR_IN_SET(state
, "inactive", "failed");
1547 int manager_job_is_active(Manager
*manager
, const char *path
) {
1548 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1549 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1555 r
= sd_bus_get_property(
1557 "org.freedesktop.systemd1",
1559 "org.freedesktop.systemd1.Job",
1565 if (sd_bus_error_has_names(&error
, SD_BUS_ERROR_NO_REPLY
,
1566 SD_BUS_ERROR_DISCONNECTED
))
1569 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1575 /* We don't actually care about the state really. The fact
1576 * that we could read the job state is enough for us */
1581 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1589 mm
= hashmap_get(m
->machine_leaders
, PID_TO_PTR(pid
));
1591 _cleanup_free_
char *unit
= NULL
;
1593 r
= cg_pid_get_unit(pid
, &unit
);
1595 mm
= hashmap_get(m
->machine_units
, unit
);
1604 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1610 machine
= hashmap_get(m
->machines
, name
);
1612 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1618 *_machine
= machine
;