summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorIvan Kruglov <mail@ikruglov.com>2024-09-25 14:17:38 +0200
committerIvan Kruglov <mail@ikruglov.com>2024-10-01 19:00:25 +0200
commit31f9f589a83508b576412eb32dfeacfe224ab573 (patch)
treef2b31fc33eea9995bdc81e9bbc27fe3e1fcab39e /src
parentmachine: generalise logic GetMachineAddresses to later use it in varlink inte... (diff)
downloadsystemd-31f9f589a83508b576412eb32dfeacfe224ab573.tar.xz
systemd-31f9f589a83508b576412eb32dfeacfe224ab573.zip
machine: generalise logic GetOSRelease to later use it in varlink interface
Diffstat (limited to 'src')
-rw-r--r--src/machine/machine-dbus.c81
-rw-r--r--src/machine/machined-core.c104
-rw-r--r--src/machine/machined.h1
3 files changed, 111 insertions, 75 deletions
diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c
index a8c376dee9..85cb00a8a6 100644
--- a/src/machine/machine-dbus.c
+++ b/src/machine/machine-dbus.c
@@ -236,8 +236,6 @@ int bus_machine_method_get_ssh_info(sd_bus_message *message, void *userdata, sd_
return sd_bus_send(NULL, reply, NULL);
}
-#define EXIT_NOT_FOUND 2
-
int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_strv_free_ char **l = NULL;
Machine *m = ASSERT_PTR(userdata);
@@ -245,80 +243,13 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
assert(message);
- switch (m->class) {
-
- case MACHINE_HOST:
- r = load_os_release_pairs(NULL, &l);
- if (r < 0)
- return r;
-
- break;
-
- case MACHINE_CONTAINER: {
- _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
- _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
- _cleanup_fclose_ FILE *f = NULL;
- pid_t child;
-
- r = pidref_namespace_open(&m->leader,
- &pidns_fd,
- &mntns_fd,
- /* ret_netns_fd = */ NULL,
- /* ret_userns_fd = */ NULL,
- &root_fd);
- if (r < 0)
- return r;
-
- if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
- return -errno;
-
- r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
- pidns_fd, mntns_fd, -1, -1, root_fd,
- &child);
- if (r < 0)
- return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
- if (r == 0) {
- int fd = -EBADF;
-
- pair[0] = safe_close(pair[0]);
-
- r = open_os_release(NULL, NULL, &fd);
- if (r == -ENOENT)
- _exit(EXIT_NOT_FOUND);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- r = copy_bytes(fd, pair[1], UINT64_MAX, 0);
- if (r < 0)
- _exit(EXIT_FAILURE);
-
- _exit(EXIT_SUCCESS);
- }
-
- pair[1] = safe_close(pair[1]);
-
- f = take_fdopen(&pair[0], "r");
- if (!f)
- return -errno;
-
- r = load_env_file_pairs(f, "/etc/os-release", &l);
- if (r < 0)
- return r;
-
- r = wait_for_terminate_and_check("(sd-osrelns)", child, 0);
- if (r < 0)
- return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
- if (r == EXIT_NOT_FOUND)
- return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information");
- if (r != EXIT_SUCCESS)
- return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Child died abnormally.");
-
- break;
- }
-
- default:
+ r = machine_get_os_release(m, &l);
+ if (r == -ENONET)
+ return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, "Machine does not contain OS release information.");
+ if (ERRNO_IS_NEG_NOT_SUPPORTED(r))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Requesting OS release data is only supported on container machines.");
- }
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to get OS release: %m");
return bus_reply_pair_array(message, l);
}
diff --git a/src/machine/machined-core.c b/src/machine/machined-core.c
index df6e437835..0045f75b0c 100644
--- a/src/machine/machined-core.c
+++ b/src/machine/machined-core.c
@@ -1,7 +1,10 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "cgroup-util.h"
+#include "copy.h"
+#include "env-file.h"
#include "fd-util.h"
+#include "fileio.h"
#include "iovec-util.h"
#include "machined.h"
#include "process-util.h"
@@ -299,3 +302,104 @@ int machine_get_addresses(Machine* machine, struct local_address **ret_addresses
return -EOPNOTSUPP;
}
}
+
+#define EXIT_NOT_FOUND 2
+
+int machine_get_os_release(Machine *machine, char ***ret_os_release) {
+ _cleanup_strv_free_ char **l = NULL;
+ int r;
+
+ assert(machine);
+ assert(ret_os_release);
+
+ switch (machine->class) {
+
+ case MACHINE_HOST:
+ r = load_os_release_pairs(/* root = */ NULL, &l);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to load OS release information: %m");
+
+ break;
+
+ case MACHINE_CONTAINER: {
+ _cleanup_close_ int mntns_fd = -EBADF, root_fd = -EBADF, pidns_fd = -EBADF;
+ _cleanup_close_pair_ int pair[2] = EBADF_PAIR;
+ _cleanup_fclose_ FILE *f = NULL;
+ pid_t child;
+
+ r = pidref_namespace_open(&machine->leader,
+ &pidns_fd,
+ &mntns_fd,
+ /* ret_netns_fd = */ NULL,
+ /* ret_userns_fd = */ NULL,
+ &root_fd);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to open namespace: %m");
+
+ if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
+ return log_debug_errno(errno, "Failed to call socketpair(): %m");
+
+ r = namespace_fork("(sd-osrelns)",
+ "(sd-osrel)",
+ /* except_fds = */ NULL,
+ /* n_except_fds = */ 0,
+ FORK_RESET_SIGNALS|FORK_DEATHSIG_SIGKILL,
+ pidns_fd,
+ mntns_fd,
+ /* netns_fd = */ -1,
+ /* userns_fd = */ -1,
+ root_fd,
+ &child);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to fork(): %m");
+ if (r == 0) {
+ _cleanup_close_ int fd = -EBADF;
+
+ pair[0] = safe_close(pair[0]);
+
+ r = open_os_release(/* root = */ NULL, /* ret_path = */ NULL, &fd);
+ if (r == -ENOENT)
+ _exit(EXIT_NOT_FOUND);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to read OS release: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ r = copy_bytes(fd, pair[1], UINT64_MAX, /* copy_flags = */ 0);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to write to fd: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ pair[1] = safe_close(pair[1]);
+
+ f = take_fdopen(&pair[0], "r");
+ if (!f)
+ return log_debug_errno(errno, "Failed to fdopen(): %m");
+
+ r = load_env_file_pairs(f, "/etc/os-release", &l);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to load OS release information: %m");
+
+ r = wait_for_terminate_and_check("(sd-osrelns)", child, /* flags = */ 0);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to wait for child: %m");
+ if (r == EXIT_NOT_FOUND)
+ return -ENOENT;
+ if (r != EXIT_SUCCESS)
+ return log_debug_errno(SYNTHETIC_ERRNO(ESHUTDOWN), "Child died abnormally");
+
+ break;
+ }
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+
+ *ret_os_release = TAKE_PTR(l);
+ return 0;
+}
diff --git a/src/machine/machined.h b/src/machine/machined.h
index f1d0d157c8..4a718f9462 100644
--- a/src/machine/machined.h
+++ b/src/machine/machined.h
@@ -66,3 +66,4 @@ void manager_gc(Manager *m, bool drop_not_started);
void manager_enqueue_gc(Manager *m);
int machine_get_addresses(Machine* machine, struct local_address **ret_addresses);
+int machine_get_os_release(Machine *machine, char ***ret_os_release);