Merge pull request #10747 from poettering/machinectl-list-fix
properly acquire os-release file from containers
This commit is contained in:
commit
b5be61d1ed
|
@ -1409,6 +1409,60 @@ int safe_fork_full(
|
|||
return 0;
|
||||
}
|
||||
|
||||
int namespace_fork(
|
||||
const char *outer_name,
|
||||
const char *inner_name,
|
||||
const int except_fds[],
|
||||
size_t n_except_fds,
|
||||
ForkFlags flags,
|
||||
int pidns_fd,
|
||||
int mntns_fd,
|
||||
int netns_fd,
|
||||
int userns_fd,
|
||||
int root_fd,
|
||||
pid_t *ret_pid) {
|
||||
|
||||
int r;
|
||||
|
||||
/* This is much like safe_fork(), but forks twice, and joins the specified namespaces in the middle
|
||||
* process. This ensures that we are fully a member of the destination namespace, with pidns an all, so that
|
||||
* /proc/self/fd works correctly. */
|
||||
|
||||
r = safe_fork_full(outer_name, except_fds, n_except_fds, (flags|FORK_DEATHSIG) & ~(FORK_REOPEN_LOG|FORK_NEW_MOUNTNS|FORK_MOUNTNS_SLAVE), ret_pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
pid_t pid;
|
||||
|
||||
/* Child */
|
||||
|
||||
r = namespace_enter(pidns_fd, mntns_fd, netns_fd, userns_fd, root_fd);
|
||||
if (r < 0) {
|
||||
log_full_errno(FLAGS_SET(flags, FORK_LOG) ? LOG_ERR : LOG_DEBUG, r, "Failed to join namespace: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* We mask a few flags here that either make no sense for the grandchild, or that we don't have to do again */
|
||||
r = safe_fork_full(inner_name, except_fds, n_except_fds, flags & ~(FORK_WAIT|FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_NULL_STDIO), &pid);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
if (r == 0) {
|
||||
/* Child */
|
||||
if (ret_pid)
|
||||
*ret_pid = pid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = wait_for_terminate_and_check(inner_name, pid, FLAGS_SET(flags, FORK_LOG) ? WAIT_LOG : 0);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(r);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret_pid, const char *path, ...) {
|
||||
bool stdout_is_tty, stderr_is_tty;
|
||||
size_t n, i;
|
||||
|
|
|
@ -159,6 +159,8 @@ static inline int safe_fork(const char *name, ForkFlags flags, pid_t *ret_pid) {
|
|||
return safe_fork_full(name, NULL, 0, flags, ret_pid);
|
||||
}
|
||||
|
||||
int namespace_fork(const char *outer_name, const char *inner_name, const int except_fds[], size_t n_except_fds, ForkFlags flags, int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd, pid_t *ret_pid);
|
||||
|
||||
int fork_agent(const char *name, const int except[], size_t n_except, pid_t *pid, const char *path, ...) _sentinel_;
|
||||
|
||||
int set_oom_score_adjust(int value);
|
||||
|
|
|
@ -1095,7 +1095,8 @@ int openpt_in_namespace(pid_t pid, int flags) {
|
|||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-openpt)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-openptns)", "(sd-openpt)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
@ -1103,10 +1104,6 @@ int openpt_in_namespace(pid_t pid, int flags) {
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
master = posix_openpt(flags|O_NOCTTY|O_CLOEXEC);
|
||||
if (master < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -1122,7 +1119,7 @@ int openpt_in_namespace(pid_t pid, int flags) {
|
|||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-openpt)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-openptns)", child, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
@ -1144,7 +1141,8 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
|
|||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-terminal)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-terminalns)", "(sd-terminal)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
@ -1152,10 +1150,6 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
master = open_terminal(name, mode|O_NOCTTY|O_CLOEXEC);
|
||||
if (master < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -1168,7 +1162,7 @@ int open_terminal_in_namespace(pid_t pid, const char *name, int mode) {
|
|||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-terminal)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-terminalns)", child, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
|
|
@ -45,51 +45,27 @@ int bus_container_connect_socket(sd_bus *b) {
|
|||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-buscntr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-buscntrns)", "(sd-buscntr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
pidnsfd, mntnsfd, -1, usernsfd, rootfd, &child);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
pid_t grandchild;
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
|
||||
if (r < 0)
|
||||
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
|
||||
if (r < 0) {
|
||||
/* Try to send error up */
|
||||
error_buf = errno;
|
||||
(void) write(pair[1], &error_buf, sizeof(error_buf));
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
/* We just changed PID namespace, however it will only
|
||||
* take effect on the children we now fork. Hence,
|
||||
* let's fork another time, and connect from this
|
||||
* grandchild, so that SO_PEERCRED of our connection
|
||||
* comes from a process from within the container, and
|
||||
* not outside of it */
|
||||
|
||||
r = safe_fork("(sd-buscntr2)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &grandchild);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
if (r == 0) {
|
||||
|
||||
r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
|
||||
if (r < 0) {
|
||||
/* Try to send error up */
|
||||
error_buf = errno;
|
||||
(void) write(pair[1], &error_buf, sizeof(error_buf));
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-buscntr2)", grandchild, 0);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
_exit(r);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-buscntr)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-buscntrns)", child, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
|
|
@ -207,7 +207,8 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
|
|||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-addr)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-addrns)", "(sd-addr)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
-1, -1, netns_fd, -1, -1, &child);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to fork(): %m");
|
||||
if (r == 0) {
|
||||
|
@ -217,10 +218,6 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(-1, -1, netns_fd, -1, -1);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
n = local_addresses(NULL, 0, AF_UNSPEC, &addresses);
|
||||
if (n < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -294,7 +291,7 @@ int bus_machine_method_get_addresses(sd_bus_message *message, void *userdata, sd
|
|||
return r;
|
||||
}
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-addr)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-addrns)", child, 0);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
@ -333,19 +330,21 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
|
|||
break;
|
||||
|
||||
case MACHINE_CONTAINER: {
|
||||
_cleanup_close_ int mntns_fd = -1, root_fd = -1;
|
||||
_cleanup_close_ int mntns_fd = -1, root_fd = -1, pidns_fd = -1;
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
pid_t child;
|
||||
|
||||
r = namespace_open(m->leader, NULL, &mntns_fd, NULL, NULL, &root_fd);
|
||||
r = namespace_open(m->leader, &pidns_fd, &mntns_fd, NULL, NULL, &root_fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-osrel)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-osrelns)", "(sd-osrel)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
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) {
|
||||
|
@ -353,10 +352,6 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
r = open_os_release(NULL, NULL, &fd);
|
||||
if (r == -ENOENT)
|
||||
_exit(EXIT_NOT_FOUND);
|
||||
|
@ -382,7 +377,7 @@ int bus_machine_method_get_os_release(sd_bus_message *message, void *userdata, s
|
|||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-osrel)", child, 0);
|
||||
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)
|
||||
|
@ -1239,7 +1234,8 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
|||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-openroot)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-openrootns)", "(sd-openroot)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
-1, 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) {
|
||||
|
@ -1247,10 +1243,6 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(-1, mntns_fd, -1, -1, root_fd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
dfd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY);
|
||||
if (dfd < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -1265,7 +1257,7 @@ int bus_machine_method_open_root_directory(sd_bus_message *message, void *userda
|
|||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-openroot)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-openrootns)", child, 0);
|
||||
if (r < 0)
|
||||
return sd_bus_error_set_errnof(error, r, "Failed to wait for child: %m");
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
|
|
@ -1342,7 +1342,8 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
|||
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
|
||||
return -errno;
|
||||
|
||||
r = safe_fork("(sd-bootid)", FORK_RESET_SIGNALS|FORK_DEATHSIG, &child);
|
||||
r = namespace_fork("(sd-bootidns)", "(sd-bootid)", NULL, 0, FORK_RESET_SIGNALS|FORK_DEATHSIG,
|
||||
pidnsfd, mntnsfd, -1, -1, rootfd, &child);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
|
@ -1350,10 +1351,6 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
|||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
r = namespace_enter(pidnsfd, mntnsfd, -1, -1, rootfd);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
fd = open("/proc/sys/kernel/random/boot_id", O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
@ -1372,7 +1369,7 @@ static int get_boot_id_for_machine(const char *machine, sd_id128_t *boot_id) {
|
|||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
|
||||
r = wait_for_terminate_and_check("(sd-bootid)", child, 0);
|
||||
r = wait_for_terminate_and_check("(sd-bootidns)", child, 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r != EXIT_SUCCESS)
|
||||
|
|
Loading…
Reference in New Issue