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-polkit.h"
13 #include "cgroup-util.h"
14 #include "errno-util.h"
17 #include "format-util.h"
18 #include "hostname-util.h"
19 #include "image-dbus.h"
21 #include "machine-dbus.h"
22 #include "machine-image.h"
23 #include "machine-pool.h"
25 #include "missing_capability.h"
26 #include "path-util.h"
27 #include "process-util.h"
28 #include "stdio-util.h"
30 #include "tmpfile-util.h"
31 #include "unit-name.h"
32 #include "user-util.h"
34 static BUS_DEFINE_PROPERTY_GET_GLOBAL(property_get_pool_path
, "s", "/var/lib/machines");
36 static int property_get_pool_usage(
39 const char *interface
,
41 sd_bus_message
*reply
,
43 sd_bus_error
*error
) {
45 _cleanup_close_
int fd
= -1;
46 uint64_t usage
= (uint64_t) -1;
51 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
55 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
59 return sd_bus_message_append(reply
, "t", usage
);
62 static int property_get_pool_limit(
65 const char *interface
,
67 sd_bus_message
*reply
,
69 sd_bus_error
*error
) {
71 _cleanup_close_
int fd
= -1;
72 uint64_t size
= (uint64_t) -1;
77 fd
= open("/var/lib/machines", O_RDONLY
|O_CLOEXEC
|O_DIRECTORY
);
81 if (btrfs_subvol_get_subtree_quota_fd(fd
, 0, &q
) >= 0)
82 size
= q
.referenced_max
;
85 return sd_bus_message_append(reply
, "t", size
);
88 static int method_get_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
89 _cleanup_free_
char *p
= NULL
;
90 Manager
*m
= userdata
;
98 r
= sd_bus_message_read(message
, "s", &name
);
102 machine
= hashmap_get(m
->machines
, name
);
104 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
106 p
= machine_bus_path(machine
);
110 return sd_bus_reply_method_return(message
, "o", p
);
113 static int method_get_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
114 _cleanup_free_
char *p
= NULL
;
115 _unused_ Manager
*m
= userdata
;
122 r
= sd_bus_message_read(message
, "s", &name
);
126 r
= image_find(IMAGE_MACHINE
, name
, NULL
);
128 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
132 p
= image_bus_path(name
);
136 return sd_bus_reply_method_return(message
, "o", p
);
139 static int method_get_machine_by_pid(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
140 _cleanup_free_
char *p
= NULL
;
141 Manager
*m
= userdata
;
142 Machine
*machine
= NULL
;
149 assert_cc(sizeof(pid_t
) == sizeof(uint32_t));
151 r
= sd_bus_message_read(message
, "u", &pid
);
159 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
161 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
165 r
= sd_bus_creds_get_pid(creds
, &pid
);
170 r
= manager_get_machine_by_pid(m
, pid
, &machine
);
174 return sd_bus_error_setf(error
, BUS_ERROR_NO_MACHINE_FOR_PID
, "PID "PID_FMT
" does not belong to any known machine", pid
);
176 p
= machine_bus_path(machine
);
180 return sd_bus_reply_method_return(message
, "o", p
);
183 static int method_list_machines(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
184 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
185 Manager
*m
= userdata
;
193 r
= sd_bus_message_new_method_return(message
, &reply
);
195 return sd_bus_error_set_errno(error
, r
);
197 r
= sd_bus_message_open_container(reply
, 'a', "(ssso)");
199 return sd_bus_error_set_errno(error
, r
);
201 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
202 _cleanup_free_
char *p
= NULL
;
204 p
= machine_bus_path(machine
);
208 r
= sd_bus_message_append(reply
, "(ssso)",
210 strempty(machine_class_to_string(machine
->class)),
214 return sd_bus_error_set_errno(error
, r
);
217 r
= sd_bus_message_close_container(reply
);
219 return sd_bus_error_set_errno(error
, r
);
221 return sd_bus_send(NULL
, reply
, NULL
);
224 static int method_create_or_register_machine(Manager
*manager
, sd_bus_message
*message
, bool read_network
, Machine
**_m
, sd_bus_error
*error
) {
225 const char *name
, *service
, *class, *root_directory
;
226 const int32_t *netif
= NULL
;
232 size_t n
, n_netif
= 0;
239 r
= sd_bus_message_read(message
, "s", &name
);
242 if (!machine_name_is_valid(name
))
243 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine name");
245 r
= sd_bus_message_read_array(message
, 'y', &v
, &n
);
253 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine ID parameter");
255 r
= sd_bus_message_read(message
, "ssus", &service
, &class, &leader
, &root_directory
);
262 r
= sd_bus_message_read_array(message
, 'i', (const void**) &netif
, &n_netif
);
266 n_netif
/= sizeof(int32_t);
268 for (i
= 0; i
< n_netif
; i
++) {
270 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid network interface index %i", netif
[i
]);
275 c
= _MACHINE_CLASS_INVALID
;
277 c
= machine_class_from_string(class);
279 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid machine class parameter");
283 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid leader PID");
285 if (!isempty(root_directory
) && !path_is_absolute(root_directory
))
286 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Root directory must be empty or an absolute path");
289 _cleanup_(sd_bus_creds_unrefp
) sd_bus_creds
*creds
= NULL
;
291 r
= sd_bus_query_sender_creds(message
, SD_BUS_CREDS_PID
, &creds
);
295 assert_cc(sizeof(uint32_t) == sizeof(pid_t
));
297 r
= sd_bus_creds_get_pid(creds
, (pid_t
*) &leader
);
302 if (hashmap_get(manager
->machines
, name
))
303 return sd_bus_error_setf(error
, BUS_ERROR_MACHINE_EXISTS
, "Machine '%s' already exists", name
);
305 r
= manager_add_machine(manager
, name
, &m
);
313 if (!isempty(service
)) {
314 m
->service
= strdup(service
);
321 if (!isempty(root_directory
)) {
322 m
->root_directory
= strdup(root_directory
);
323 if (!m
->root_directory
) {
330 assert_cc(sizeof(int32_t) == sizeof(int));
331 m
->netif
= memdup(netif
, sizeof(int32_t) * n_netif
);
337 m
->n_netif
= n_netif
;
345 machine_add_to_gc_queue(m
);
349 static int method_create_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
350 Manager
*manager
= userdata
;
357 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
361 r
= sd_bus_message_enter_container(message
, 'a', "(sv)");
365 r
= machine_start(m
, message
, error
);
369 m
->create_message
= sd_bus_message_ref(message
);
373 machine_add_to_gc_queue(m
);
377 static int method_create_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
378 return method_create_machine_internal(message
, true, userdata
, error
);
381 static int method_create_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
382 return method_create_machine_internal(message
, false, userdata
, error
);
385 static int method_register_machine_internal(sd_bus_message
*message
, bool read_network
, void *userdata
, sd_bus_error
*error
) {
386 Manager
*manager
= userdata
;
387 _cleanup_free_
char *p
= NULL
;
394 r
= method_create_or_register_machine(manager
, message
, read_network
, &m
, error
);
398 r
= cg_pid_get_unit(m
->leader
, &m
->unit
);
400 r
= sd_bus_error_set_errnof(error
, r
,
401 "Failed to determine unit of process "PID_FMT
" : %m",
406 r
= machine_start(m
, NULL
, error
);
410 p
= machine_bus_path(m
);
416 return sd_bus_reply_method_return(message
, "o", p
);
419 machine_add_to_gc_queue(m
);
423 static int method_register_machine_with_network(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
424 return method_register_machine_internal(message
, true, userdata
, error
);
427 static int method_register_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
428 return method_register_machine_internal(message
, false, userdata
, error
);
431 static int redirect_method_to_machine(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
440 r
= sd_bus_message_read(message
, "s", &name
);
442 return sd_bus_error_set_errno(error
, r
);
444 machine
= hashmap_get(m
->machines
, name
);
446 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
448 return method(message
, machine
, error
);
451 static int method_unregister_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
452 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_unregister
);
455 static int method_terminate_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
456 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_terminate
);
459 static int method_kill_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
460 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_kill
);
463 static int method_get_machine_addresses(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
464 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_addresses
);
467 static int method_get_machine_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
468 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_os_release
);
471 static int method_list_images(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
472 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
473 _cleanup_hashmap_free_ Hashmap
*images
= NULL
;
474 _unused_ Manager
*m
= userdata
;
482 images
= hashmap_new(&image_hash_ops
);
486 r
= image_discover(IMAGE_MACHINE
, images
);
490 r
= sd_bus_message_new_method_return(message
, &reply
);
494 r
= sd_bus_message_open_container(reply
, 'a', "(ssbttto)");
498 HASHMAP_FOREACH(image
, images
, i
) {
499 _cleanup_free_
char *p
= NULL
;
501 p
= image_bus_path(image
->name
);
505 r
= sd_bus_message_append(reply
, "(ssbttto)",
507 image_type_to_string(image
->type
),
517 r
= sd_bus_message_close_container(reply
);
521 return sd_bus_send(NULL
, reply
, NULL
);
524 static int method_open_machine_pty(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
525 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_pty
);
528 static int method_open_machine_login(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
529 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_login
);
532 static int method_open_machine_shell(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
533 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_shell
);
536 static int method_bind_mount_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
537 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_bind_mount
);
540 static int method_copy_machine(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
541 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_copy
);
544 static int method_open_machine_root_directory(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
545 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_open_root_directory
);
548 static int method_get_machine_uid_shift(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
549 return redirect_method_to_machine(message
, userdata
, error
, bus_machine_method_get_uid_shift
);
552 static int redirect_method_to_image(sd_bus_message
*message
, Manager
*m
, sd_bus_error
*error
, sd_bus_message_handler_t method
) {
553 _cleanup_(image_unrefp
) Image
* i
= NULL
;
561 r
= sd_bus_message_read(message
, "s", &name
);
565 if (!image_name_is_valid(name
))
566 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Image name '%s' is invalid.", name
);
568 r
= image_find(IMAGE_MACHINE
, name
, &i
);
570 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_IMAGE
, "No image '%s' known", name
);
575 return method(message
, i
, error
);
578 static int method_remove_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
579 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_remove
);
582 static int method_rename_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
583 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_rename
);
586 static int method_clone_image(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
587 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_clone
);
590 static int method_mark_image_read_only(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
591 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_mark_read_only
);
594 static int method_get_image_hostname(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
595 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_hostname
);
598 static int method_get_image_machine_id(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
599 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_id
);
602 static int method_get_image_machine_info(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
603 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_machine_info
);
606 static int method_get_image_os_release(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
607 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_get_os_release
);
610 static int clean_pool_done(Operation
*operation
, int ret
, sd_bus_error
*error
) {
611 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
612 _cleanup_fclose_
FILE *f
= NULL
;
618 assert(operation
->extra_fd
>= 0);
620 if (lseek(operation
->extra_fd
, 0, SEEK_SET
) == (off_t
) -1)
623 f
= take_fdopen(&operation
->extra_fd
, "r");
627 /* The resulting temporary file starts with a boolean value that indicates success or not. */
629 n
= fread(&success
, 1, sizeof(success
), f
);
630 if (n
!= sizeof(success
))
631 return ret
< 0 ? ret
: errno_or_else(EIO
);
634 _cleanup_free_
char *name
= NULL
;
636 /* The clean-up operation failed. In this case the resulting temporary file should contain a boolean
637 * set to false followed by the name of the failed image. Let's try to read this and use it for the
638 * error message. If we can't read it, don't mind, and return the naked error. */
640 if (success
) /* The resulting temporary file could not be updated, ignore it. */
643 r
= read_nul_string(f
, LONG_LINE_MAX
, &name
);
644 if (r
<= 0) /* Same here... */
647 return sd_bus_error_set_errnof(error
, ret
, "Failed to remove image %s: %m", name
);
652 r
= sd_bus_message_new_method_return(operation
->message
, &reply
);
656 r
= sd_bus_message_open_container(reply
, 'a', "(st)");
660 /* On success the resulting temporary file will contain a list of image names that were removed followed by
661 * their size on disk. Let's read that and turn it into a bus message. */
663 _cleanup_free_
char *name
= NULL
;
666 r
= read_nul_string(f
, LONG_LINE_MAX
, &name
);
669 if (r
== 0) /* reached the end */
673 n
= fread(&size
, 1, sizeof(size
), f
);
674 if (n
!= sizeof(size
))
675 return errno_or_else(EIO
);
677 r
= sd_bus_message_append(reply
, "(st)", name
, size
);
682 r
= sd_bus_message_close_container(reply
);
686 return sd_bus_send(NULL
, reply
, NULL
);
689 static int method_clean_pool(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
695 _cleanup_close_pair_
int errno_pipe_fd
[2] = { -1, -1 };
696 _cleanup_close_
int result_fd
= -1;
697 Manager
*m
= userdata
;
698 Operation
*operation
;
705 if (m
->n_operations
>= OPERATIONS_MAX
)
706 return sd_bus_error_setf(error
, SD_BUS_ERROR_LIMITS_EXCEEDED
, "Too many ongoing operations.");
708 r
= sd_bus_message_read(message
, "s", &mm
);
712 if (streq(mm
, "all"))
714 else if (streq(mm
, "hidden"))
715 mode
= REMOVE_HIDDEN
;
717 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Unknown mode '%s'.", mm
);
719 r
= bus_verify_polkit_async(
722 "org.freedesktop.machine1.manage-machines",
731 return 1; /* Will call us back */
733 if (pipe2(errno_pipe_fd
, O_CLOEXEC
|O_NONBLOCK
) < 0)
734 return sd_bus_error_set_errnof(error
, errno
, "Failed to create pipe: %m");
736 /* Create a temporary file we can dump information about deleted images into. We use a temporary file for this
737 * instead of a pipe or so, since this might grow quit large in theory and we don't want to process this
739 result_fd
= open_tmpfile_unlinkable(NULL
, O_RDWR
|O_CLOEXEC
);
743 /* This might be a slow operation, run it asynchronously in a background process */
744 r
= safe_fork("(sd-clean)", FORK_RESET_SIGNALS
, &child
);
746 return sd_bus_error_set_errnof(error
, r
, "Failed to fork(): %m");
748 _cleanup_hashmap_free_ Hashmap
*images
= NULL
;
754 errno_pipe_fd
[0] = safe_close(errno_pipe_fd
[0]);
756 images
= hashmap_new(&image_hash_ops
);
762 r
= image_discover(IMAGE_MACHINE
, images
);
766 l
= write(result_fd
, &success
, sizeof(success
));
772 HASHMAP_FOREACH(image
, images
, i
) {
774 /* We can't remove vendor images (i.e. those in /usr) */
775 if (IMAGE_IS_VENDOR(image
))
778 if (IMAGE_IS_HOST(image
))
781 if (mode
== REMOVE_HIDDEN
&& !IMAGE_IS_HIDDEN(image
))
784 r
= image_remove(image
);
785 if (r
== -EBUSY
) /* keep images that are currently being used. */
788 /* If the operation failed, let's override everything we wrote, and instead write there at which image we failed. */
790 (void) ftruncate(result_fd
, 0);
791 (void) lseek(result_fd
, 0, SEEK_SET
);
792 (void) write(result_fd
, &success
, sizeof(success
));
793 (void) write(result_fd
, image
->name
, strlen(image
->name
)+1);
797 l
= write(result_fd
, image
->name
, strlen(image
->name
)+1);
803 l
= write(result_fd
, &image
->usage_exclusive
, sizeof(image
->usage_exclusive
));
810 result_fd
= safe_close(result_fd
);
814 (void) write(errno_pipe_fd
[1], &r
, sizeof(r
));
818 errno_pipe_fd
[1] = safe_close(errno_pipe_fd
[1]);
820 /* The clean-up might take a while, hence install a watch on the child and return */
822 r
= operation_new(m
, NULL
, child
, message
, errno_pipe_fd
[0], &operation
);
824 (void) sigkill_wait(child
);
828 operation
->extra_fd
= result_fd
;
829 operation
->done
= clean_pool_done
;
832 errno_pipe_fd
[0] = -1;
837 static int method_set_pool_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
838 Manager
*m
= userdata
;
844 r
= sd_bus_message_read(message
, "t", &limit
);
847 if (!FILE_SIZE_VALID_OR_INFINITY(limit
))
848 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "New limit out of range");
850 r
= bus_verify_polkit_async(
853 "org.freedesktop.machine1.manage-machines",
862 return 1; /* Will call us back */
864 /* Set up the machine directory if necessary */
865 r
= setup_machine_directory(error
);
869 (void) btrfs_qgroup_set_limit("/var/lib/machines", 0, limit
);
871 r
= btrfs_subvol_set_subtree_quota_limit("/var/lib/machines", 0, limit
);
873 return sd_bus_error_setf(error
, SD_BUS_ERROR_NOT_SUPPORTED
, "Quota is only supported on btrfs.");
875 return sd_bus_error_set_errnof(error
, r
, "Failed to adjust quota limit: %m");
877 return sd_bus_reply_method_return(message
, NULL
);
880 static int method_set_image_limit(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
881 return redirect_method_to_image(message
, userdata
, error
, bus_image_method_set_limit
);
884 static int method_map_from_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
885 _cleanup_fclose_
FILE *f
= NULL
;
886 Manager
*m
= userdata
;
887 const char *name
, *p
;
892 r
= sd_bus_message_read(message
, "su", &name
, &uid
);
896 if (!uid_is_valid(uid
))
897 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
899 machine
= hashmap_get(m
->machines
, name
);
901 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
903 if (machine
->class != MACHINE_CONTAINER
)
904 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
906 p
= procfs_file_alloca(machine
->leader
, "uid_map");
912 uid_t uid_base
, uid_shift
, uid_range
, converted
;
916 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
917 if (k
< 0 && feof(f
))
921 return errno_or_else(EIO
);
926 if (uid
< uid_base
|| uid
>= uid_base
+ uid_range
)
929 converted
= uid
- uid_base
+ uid_shift
;
930 if (!uid_is_valid(converted
))
931 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
933 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
936 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "Machine '%s' has no matching user mappings.", name
);
939 static int method_map_to_machine_user(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
940 Manager
*m
= userdata
;
946 r
= sd_bus_message_read(message
, "u", &uid
);
949 if (!uid_is_valid(uid
))
950 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
952 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "User " UID_FMT
" belongs to host UID range", uid
);
954 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
955 _cleanup_fclose_
FILE *f
= NULL
;
956 char p
[STRLEN("/proc//uid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
958 if (machine
->class != MACHINE_CONTAINER
)
961 xsprintf(p
, "/proc/" UID_FMT
"/uid_map", machine
->leader
);
964 log_warning_errno(errno
, "Failed to open %s, ignoring,", p
);
969 _cleanup_free_
char *o
= NULL
;
970 uid_t uid_base
, uid_shift
, uid_range
, converted
;
974 k
= fscanf(f
, UID_FMT
" " UID_FMT
" " UID_FMT
, &uid_base
, &uid_shift
, &uid_range
);
975 if (k
< 0 && feof(f
))
979 return errno_or_else(EIO
);
984 /* The private user namespace is disabled, ignoring. */
988 if (uid
< uid_shift
|| uid
>= uid_shift
+ uid_range
)
991 converted
= (uid
- uid_shift
+ uid_base
);
992 if (!uid_is_valid(converted
))
993 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid user ID " UID_FMT
, uid
);
995 o
= machine_bus_path(machine
);
999 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1003 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_USER_MAPPING
, "No matching user mapping for " UID_FMT
".", uid
);
1006 static int method_map_from_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1007 _cleanup_fclose_
FILE *f
= NULL
;
1008 Manager
*m
= groupdata
;
1009 const char *name
, *p
;
1014 r
= sd_bus_message_read(message
, "su", &name
, &gid
);
1018 if (!gid_is_valid(gid
))
1019 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1021 machine
= hashmap_get(m
->machines
, name
);
1023 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_MACHINE
, "No machine '%s' known", name
);
1025 if (machine
->class != MACHINE_CONTAINER
)
1026 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Not supported for non-container machines.");
1028 p
= procfs_file_alloca(machine
->leader
, "gid_map");
1034 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1038 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1039 if (k
< 0 && feof(f
))
1043 return errno_or_else(EIO
);
1048 if (gid
< gid_base
|| gid
>= gid_base
+ gid_range
)
1051 converted
= gid
- gid_base
+ gid_shift
;
1052 if (!gid_is_valid(converted
))
1053 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1055 return sd_bus_reply_method_return(message
, "u", (uint32_t) converted
);
1058 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Machine '%s' has no matching group mappings.", name
);
1061 static int method_map_to_machine_group(sd_bus_message
*message
, void *groupdata
, sd_bus_error
*error
) {
1062 Manager
*m
= groupdata
;
1068 r
= sd_bus_message_read(message
, "u", &gid
);
1071 if (!gid_is_valid(gid
))
1072 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1074 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "Group " GID_FMT
" belongs to host GID range", gid
);
1076 HASHMAP_FOREACH(machine
, m
->machines
, i
) {
1077 _cleanup_fclose_
FILE *f
= NULL
;
1078 char p
[STRLEN("/proc//gid_map") + DECIMAL_STR_MAX(pid_t
) + 1];
1080 if (machine
->class != MACHINE_CONTAINER
)
1083 xsprintf(p
, "/proc/" GID_FMT
"/gid_map", machine
->leader
);
1086 log_warning_errno(errno
, "Failed to open %s, ignoring,", p
);
1091 _cleanup_free_
char *o
= NULL
;
1092 gid_t gid_base
, gid_shift
, gid_range
, converted
;
1096 k
= fscanf(f
, GID_FMT
" " GID_FMT
" " GID_FMT
, &gid_base
, &gid_shift
, &gid_range
);
1097 if (k
< 0 && feof(f
))
1101 return errno_or_else(EIO
);
1106 /* The private user namespace is disabled, ignoring. */
1110 if (gid
< gid_shift
|| gid
>= gid_shift
+ gid_range
)
1113 converted
= (gid
- gid_shift
+ gid_base
);
1114 if (!gid_is_valid(converted
))
1115 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid group ID " GID_FMT
, gid
);
1117 o
= machine_bus_path(machine
);
1121 return sd_bus_reply_method_return(message
, "sou", machine
->name
, o
, (uint32_t) converted
);
1125 return sd_bus_error_setf(error
, BUS_ERROR_NO_SUCH_GROUP_MAPPING
, "No matching group mapping for " GID_FMT
".", gid
);
1128 const sd_bus_vtable manager_vtable
[] = {
1129 SD_BUS_VTABLE_START(0),
1131 SD_BUS_PROPERTY("PoolPath", "s", property_get_pool_path
, 0, 0),
1132 SD_BUS_PROPERTY("PoolUsage", "t", property_get_pool_usage
, 0, 0),
1133 SD_BUS_PROPERTY("PoolLimit", "t", property_get_pool_limit
, 0, 0),
1135 SD_BUS_METHOD_WITH_NAMES("GetMachine",
1139 SD_BUS_PARAM(machine
),
1141 SD_BUS_VTABLE_UNPRIVILEGED
),
1142 SD_BUS_METHOD_WITH_NAMES("GetImage",
1146 SD_BUS_PARAM(image
),
1148 SD_BUS_VTABLE_UNPRIVILEGED
),
1149 SD_BUS_METHOD_WITH_NAMES("GetMachineByPID",
1153 SD_BUS_PARAM(machine
),
1154 method_get_machine_by_pid
,
1155 SD_BUS_VTABLE_UNPRIVILEGED
),
1156 SD_BUS_METHOD_WITH_NAMES("ListMachines",
1159 SD_BUS_PARAM(machines
),
1160 method_list_machines
,
1161 SD_BUS_VTABLE_UNPRIVILEGED
),
1162 SD_BUS_METHOD_WITH_NAMES("ListImages",
1165 SD_BUS_PARAM(images
),
1167 SD_BUS_VTABLE_UNPRIVILEGED
),
1168 SD_BUS_METHOD_WITH_NAMES("CreateMachine",
1172 SD_BUS_PARAM(service
)
1174 SD_BUS_PARAM(leader
)
1175 SD_BUS_PARAM(root_directory
)
1176 SD_BUS_PARAM(scope_properties
),
1179 method_create_machine
, 0),
1180 SD_BUS_METHOD_WITH_NAMES("CreateMachineWithNetwork",
1184 SD_BUS_PARAM(service
)
1186 SD_BUS_PARAM(leader
)
1187 SD_BUS_PARAM(root_directory
)
1188 SD_BUS_PARAM(ifindices
)
1189 SD_BUS_PARAM(scope_properties
),
1192 method_create_machine_with_network
, 0),
1193 SD_BUS_METHOD_WITH_NAMES("RegisterMachine",
1197 SD_BUS_PARAM(service
)
1199 SD_BUS_PARAM(leader
)
1200 SD_BUS_PARAM(root_directory
),
1203 method_register_machine
, 0),
1204 SD_BUS_METHOD_WITH_NAMES("RegisterMachineWithNetwork",
1208 SD_BUS_PARAM(service
)
1210 SD_BUS_PARAM(leader
)
1211 SD_BUS_PARAM(root_directory
)
1212 SD_BUS_PARAM(ifindices
),
1215 method_register_machine_with_network
, 0),
1216 SD_BUS_METHOD_WITH_NAMES("UnregisterMachine",
1220 method_unregister_machine
,
1221 SD_BUS_VTABLE_UNPRIVILEGED
),
1222 SD_BUS_METHOD_WITH_NAMES("TerminateMachine",
1226 method_terminate_machine
,
1227 SD_BUS_VTABLE_UNPRIVILEGED
),
1228 SD_BUS_METHOD_WITH_NAMES("KillMachine",
1232 SD_BUS_PARAM(signal
),
1234 method_kill_machine
,
1235 SD_BUS_VTABLE_UNPRIVILEGED
),
1236 SD_BUS_METHOD_WITH_NAMES("GetMachineAddresses",
1240 SD_BUS_PARAM(addresses
),
1241 method_get_machine_addresses
,
1242 SD_BUS_VTABLE_UNPRIVILEGED
),
1243 SD_BUS_METHOD_WITH_NAMES("GetMachineOSRelease",
1247 SD_BUS_PARAM(fields
),
1248 method_get_machine_os_release
,
1249 SD_BUS_VTABLE_UNPRIVILEGED
),
1250 SD_BUS_METHOD_WITH_NAMES("OpenMachinePTY",
1255 SD_BUS_PARAM(pty_path
),
1256 method_open_machine_pty
,
1258 SD_BUS_METHOD_WITH_NAMES("OpenMachineLogin",
1263 SD_BUS_PARAM(pty_path
),
1264 method_open_machine_login
,
1265 SD_BUS_VTABLE_UNPRIVILEGED
),
1266 SD_BUS_METHOD_WITH_NAMES("OpenMachineShell",
1272 SD_BUS_PARAM(environment
),
1275 SD_BUS_PARAM(pty_path
),
1276 method_open_machine_shell
,
1277 SD_BUS_VTABLE_UNPRIVILEGED
),
1278 SD_BUS_METHOD_WITH_NAMES("BindMountMachine",
1281 SD_BUS_PARAM(source
)
1282 SD_BUS_PARAM(destination
)
1283 SD_BUS_PARAM(read_only
)
1284 SD_BUS_PARAM(mkdir
),
1286 method_bind_mount_machine
,
1287 SD_BUS_VTABLE_UNPRIVILEGED
),
1288 SD_BUS_METHOD_WITH_NAMES("CopyFromMachine",
1291 SD_BUS_PARAM(source
)
1292 SD_BUS_PARAM(destination
),
1294 method_copy_machine
,
1295 SD_BUS_VTABLE_UNPRIVILEGED
),
1296 SD_BUS_METHOD_WITH_NAMES("CopyToMachine",
1299 SD_BUS_PARAM(source
)
1300 SD_BUS_PARAM(destination
),
1302 method_copy_machine
,
1303 SD_BUS_VTABLE_UNPRIVILEGED
),
1304 SD_BUS_METHOD_WITH_NAMES("OpenMachineRootDirectory",
1309 method_open_machine_root_directory
,
1310 SD_BUS_VTABLE_UNPRIVILEGED
),
1311 SD_BUS_METHOD_WITH_NAMES("GetMachineUIDShift",
1315 SD_BUS_PARAM(shift
),
1316 method_get_machine_uid_shift
,
1317 SD_BUS_VTABLE_UNPRIVILEGED
),
1318 SD_BUS_METHOD_WITH_NAMES("RemoveImage",
1322 method_remove_image
,
1323 SD_BUS_VTABLE_UNPRIVILEGED
),
1324 SD_BUS_METHOD_WITH_NAMES("RenameImage",
1327 SD_BUS_PARAM(new_name
),
1329 method_rename_image
,
1330 SD_BUS_VTABLE_UNPRIVILEGED
),
1331 SD_BUS_METHOD_WITH_NAMES("CloneImage",
1334 SD_BUS_PARAM(new_name
)
1335 SD_BUS_PARAM(read_only
),
1338 SD_BUS_VTABLE_UNPRIVILEGED
),
1339 SD_BUS_METHOD_WITH_NAMES("MarkImageReadOnly",
1342 SD_BUS_PARAM(read_only
),
1344 method_mark_image_read_only
,
1345 SD_BUS_VTABLE_UNPRIVILEGED
),
1346 SD_BUS_METHOD_WITH_NAMES("GetImageHostname",
1350 SD_BUS_PARAM(hostname
),
1351 method_get_image_hostname
,
1352 SD_BUS_VTABLE_UNPRIVILEGED
),
1353 SD_BUS_METHOD_WITH_NAMES("GetImageMachineID",
1358 method_get_image_machine_id
,
1359 SD_BUS_VTABLE_UNPRIVILEGED
),
1360 SD_BUS_METHOD_WITH_NAMES("GetImageMachineInfo",
1364 SD_BUS_PARAM(machine_info
),
1365 method_get_image_machine_info
,
1366 SD_BUS_VTABLE_UNPRIVILEGED
),
1367 SD_BUS_METHOD_WITH_NAMES("GetImageOSRelease",
1371 SD_BUS_PARAM(os_release
),
1372 method_get_image_os_release
,
1373 SD_BUS_VTABLE_UNPRIVILEGED
),
1374 SD_BUS_METHOD_WITH_NAMES("SetPoolLimit",
1378 method_set_pool_limit
,
1379 SD_BUS_VTABLE_UNPRIVILEGED
),
1380 SD_BUS_METHOD_WITH_NAMES("SetImageLimit",
1385 method_set_image_limit
,
1386 SD_BUS_VTABLE_UNPRIVILEGED
),
1387 SD_BUS_METHOD_WITH_NAMES("CleanPool",
1391 SD_BUS_PARAM(images
),
1393 SD_BUS_VTABLE_UNPRIVILEGED
),
1394 SD_BUS_METHOD_WITH_NAMES("MapFromMachineUser",
1397 SD_BUS_PARAM(uid_inner
),
1399 SD_BUS_PARAM(uid_outer
),
1400 method_map_from_machine_user
,
1401 SD_BUS_VTABLE_UNPRIVILEGED
),
1402 SD_BUS_METHOD_WITH_NAMES("MapToMachineUser",
1404 SD_BUS_PARAM(uid_outer
),
1406 SD_BUS_PARAM(machine_name
)
1407 SD_BUS_PARAM(machine_path
)
1408 SD_BUS_PARAM(uid_inner
),
1409 method_map_to_machine_user
,
1410 SD_BUS_VTABLE_UNPRIVILEGED
),
1411 SD_BUS_METHOD_WITH_NAMES("MapFromMachineGroup",
1414 SD_BUS_PARAM(gid_inner
),
1416 SD_BUS_PARAM(gid_outer
),
1417 method_map_from_machine_group
,
1418 SD_BUS_VTABLE_UNPRIVILEGED
),
1419 SD_BUS_METHOD_WITH_NAMES("MapToMachineGroup",
1421 SD_BUS_PARAM(gid_outer
),
1423 SD_BUS_PARAM(machine_name
)
1424 SD_BUS_PARAM(machine_path
)
1425 SD_BUS_PARAM(gid_inner
),
1426 method_map_to_machine_group
,
1427 SD_BUS_VTABLE_UNPRIVILEGED
),
1429 SD_BUS_SIGNAL_WITH_NAMES("MachineNew",
1431 SD_BUS_PARAM(machine
)
1434 SD_BUS_SIGNAL_WITH_NAMES("MachineRemoved",
1436 SD_BUS_PARAM(machine
)
1443 const BusObjectImplementation manager_object
= {
1444 "/org/freedesktop/machine1",
1445 "org.freedesktop.machine1.Manager",
1446 .vtables
= BUS_VTABLES(manager_vtable
),
1447 .children
= BUS_IMPLEMENTATIONS( &machine_object
,
1451 int match_job_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1452 const char *path
, *result
, *unit
;
1453 Manager
*m
= userdata
;
1461 r
= sd_bus_message_read(message
, "uoss", &id
, &path
, &unit
, &result
);
1463 bus_log_parse_error(r
);
1467 machine
= hashmap_get(m
->machine_units
, unit
);
1471 if (streq_ptr(path
, machine
->scope_job
)) {
1472 machine
->scope_job
= mfree(machine
->scope_job
);
1474 if (machine
->started
) {
1475 if (streq(result
, "done"))
1476 machine_send_create_reply(machine
, NULL
);
1478 _cleanup_(sd_bus_error_free
) sd_bus_error e
= SD_BUS_ERROR_NULL
;
1480 sd_bus_error_setf(&e
, BUS_ERROR_JOB_FAILED
, "Start job for unit %s failed with '%s'", unit
, result
);
1482 machine_send_create_reply(machine
, &e
);
1486 machine_save(machine
);
1489 machine_add_to_gc_queue(machine
);
1493 int match_properties_changed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1494 _cleanup_free_
char *unit
= NULL
;
1496 Manager
*m
= userdata
;
1503 path
= sd_bus_message_get_path(message
);
1507 r
= unit_name_from_dbus_path(path
, &unit
);
1508 if (r
== -EINVAL
) /* not for a unit */
1515 machine
= hashmap_get(m
->machine_units
, unit
);
1519 machine_add_to_gc_queue(machine
);
1523 int match_unit_removed(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1524 const char *path
, *unit
;
1525 Manager
*m
= userdata
;
1532 r
= sd_bus_message_read(message
, "so", &unit
, &path
);
1534 bus_log_parse_error(r
);
1538 machine
= hashmap_get(m
->machine_units
, unit
);
1542 machine_add_to_gc_queue(machine
);
1546 int match_reloading(sd_bus_message
*message
, void *userdata
, sd_bus_error
*error
) {
1547 Manager
*m
= userdata
;
1555 r
= sd_bus_message_read(message
, "b", &b
);
1557 bus_log_parse_error(r
);
1563 /* systemd finished reloading, let's recheck all our machines */
1564 log_debug("System manager has been reloaded, rechecking machines...");
1566 HASHMAP_FOREACH(machine
, m
->machines
, i
)
1567 machine_add_to_gc_queue(machine
);
1572 int manager_unref_unit(
1575 sd_bus_error
*error
) {
1580 return sd_bus_call_method(
1582 "org.freedesktop.systemd1",
1583 "/org/freedesktop/systemd1",
1584 "org.freedesktop.systemd1.Manager",
1592 int manager_stop_unit(Manager
*manager
, const char *unit
, sd_bus_error
*error
, char **job
) {
1593 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1599 r
= sd_bus_call_method(
1601 "org.freedesktop.systemd1",
1602 "/org/freedesktop/systemd1",
1603 "org.freedesktop.systemd1.Manager",
1607 "ss", unit
, "fail");
1609 if (sd_bus_error_has_name(error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1610 sd_bus_error_has_name(error
, BUS_ERROR_LOAD_FAILED
)) {
1615 sd_bus_error_free(error
);
1626 r
= sd_bus_message_read(reply
, "o", &j
);
1640 int manager_kill_unit(Manager
*manager
, const char *unit
, int signo
, sd_bus_error
*error
) {
1644 return sd_bus_call_method(
1646 "org.freedesktop.systemd1",
1647 "/org/freedesktop/systemd1",
1648 "org.freedesktop.systemd1.Manager",
1652 "ssi", unit
, "all", signo
);
1655 int manager_unit_is_active(Manager
*manager
, const char *unit
) {
1656 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1657 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1658 _cleanup_free_
char *path
= NULL
;
1665 path
= unit_dbus_path_from_name(unit
);
1669 r
= sd_bus_get_property(
1671 "org.freedesktop.systemd1",
1673 "org.freedesktop.systemd1.Unit",
1679 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1680 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1683 if (sd_bus_error_has_name(&error
, BUS_ERROR_NO_SUCH_UNIT
) ||
1684 sd_bus_error_has_name(&error
, BUS_ERROR_LOAD_FAILED
))
1690 r
= sd_bus_message_read(reply
, "s", &state
);
1694 return !STR_IN_SET(state
, "inactive", "failed");
1697 int manager_job_is_active(Manager
*manager
, const char *path
) {
1698 _cleanup_(sd_bus_error_free
) sd_bus_error error
= SD_BUS_ERROR_NULL
;
1699 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
1705 r
= sd_bus_get_property(
1707 "org.freedesktop.systemd1",
1709 "org.freedesktop.systemd1.Job",
1715 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_NO_REPLY
) ||
1716 sd_bus_error_has_name(&error
, SD_BUS_ERROR_DISCONNECTED
))
1719 if (sd_bus_error_has_name(&error
, SD_BUS_ERROR_UNKNOWN_OBJECT
))
1725 /* We don't actually care about the state really. The fact
1726 * that we could read the job state is enough for us */
1731 int manager_get_machine_by_pid(Manager
*m
, pid_t pid
, Machine
**machine
) {
1739 mm
= hashmap_get(m
->machine_leaders
, PID_TO_PTR(pid
));
1741 _cleanup_free_
char *unit
= NULL
;
1743 r
= cg_pid_get_unit(pid
, &unit
);
1745 mm
= hashmap_get(m
->machine_units
, unit
);
1754 int manager_add_machine(Manager
*m
, const char *name
, Machine
**_machine
) {
1760 machine
= hashmap_get(m
->machines
, name
);
1762 machine
= machine_new(m
, _MACHINE_CLASS_INVALID
, name
);
1768 *_machine
= machine
;