Skip to content

Commit

Permalink
linux: add function to send mounts from the host
Browse files Browse the repository at this point in the history
preparation patch to enable the creation of mounts before joining or
creating a user namespace.  This is needed for creating idmapped
mounts that are usable from the container user namespace.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
  • Loading branch information
giuseppe committed Nov 15, 2021
1 parent 57b813e commit dc2d666
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 4 deletions.
102 changes: 99 additions & 3 deletions src/libcrun/linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -3243,6 +3243,94 @@ root_mapped_in_container_p (runtime_spec_schema_defs_id_mapping **mappings, size
return false;
}

static struct libcrun_fd_map *
get_fd_map (libcrun_container_t *container)
{
struct libcrun_fd_map *mount_fds = get_private_data (container)->mount_fds;

if (mount_fds == NULL)
{
runtime_spec_schema_config_schema *def = container->container_def;
mount_fds = make_libcrun_fd_map (def->mounts_len);
get_private_data (container)->mount_fds = mount_fds;
}
return mount_fds;
}

static int
prepare_and_send_mounts (libcrun_container_t *container, struct init_status_s *init_status,
pid_t pid, int sync_socket_host, libcrun_error_t *err)
{
runtime_spec_schema_config_schema *def = container->container_def;
cleanup_close_map struct libcrun_fd_map *mount_fds = NULL;
size_t how_many = 0;
size_t i;
int ret;

if (def->mounts_len == 0)
return 0;

mount_fds = make_libcrun_fd_map (def->mounts_len);

for (i = 0; i < def->mounts_len; i++)
{
if (mount_fds->fds[i] >= 0)
how_many++;
}

ret = TEMP_FAILURE_RETRY (write (sync_socket_host, &how_many, sizeof (how_many)));
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "write to sync socket");

for (i = 0; i < def->mounts_len; i++)
{
if (mount_fds->fds[i] >= 0)
{
ret = send_fd_to_socket_with_payload (sync_socket_host, mount_fds->fds[i], (char *) &i, sizeof (i), err);
if (UNLIKELY (ret < 0))
return ret;
}
}

return 0;
}

static int
receive_mounts (libcrun_container_t *container, int sync_socket_container, libcrun_error_t *err)
{
runtime_spec_schema_config_schema *def = container->container_def;
size_t i, how_many = 0;
struct libcrun_fd_map *mount_fds = NULL;
int ret;

if (def->mounts_len == 0)
return 0;

mount_fds = get_fd_map (container);

ret = TEMP_FAILURE_RETRY (read (sync_socket_container, &how_many, sizeof (how_many)));
if (UNLIKELY (ret < 0))
return crun_make_error (err, errno, "read from sync socket");

for (i = 0; i < how_many; i++)
{
size_t index;

ret = receive_fd_from_socket_with_payload (sync_socket_container, (char *) &index, sizeof (index), err);
if (UNLIKELY (ret < 0))
return ret;
if (index >= def->mounts_len)
return crun_make_error (err, 0, "invalid mount data received");

if (mount_fds->fds[index] >= 0)
TEMP_FAILURE_RETRY (close (mount_fds->fds[index]));

mount_fds->fds[index] = ret;
}

return 0;
}

static int
set_id_init (libcrun_container_t *container, libcrun_error_t *err)
{
Expand Down Expand Up @@ -3290,7 +3378,7 @@ init_container (libcrun_container_t *container, int sync_socket_container, struc
libcrun_error_t *err)
{
runtime_spec_schema_config_schema *def = container->container_def;
cleanup_close_map struct libcrun_fd_map *mount_fds = NULL;
struct libcrun_fd_map *mount_fds = get_fd_map (container);
pid_t pid_container = 0;
size_t i;
int ret;
Expand Down Expand Up @@ -3353,8 +3441,6 @@ init_container (libcrun_container_t *container, int sync_socket_container, struc
return ret;
}

mount_fds = make_libcrun_fd_map (def->mounts_len);

/* If the container needs to join an existing PID namespace, take a reference to it
before creating a new user namespace, as we could lose the access to the existing
namespace.
Expand Down Expand Up @@ -3470,6 +3556,11 @@ init_container (libcrun_container_t *container, int sync_socket_container, struc
return ret;
}

/* Receive the mounts sent by `prepare_and_send_mounts`. */
ret = receive_mounts (container, sync_socket_container, err);
if (UNLIKELY (ret < 0))
return ret;

ret = libcrun_container_setgroups (container, container->container_def->process, err);
if (UNLIKELY (ret < 0))
return ret;
Expand Down Expand Up @@ -3679,6 +3770,11 @@ libcrun_run_linux_container (libcrun_container_t *container, container_entrypoin
pid_to_clean = pid = grandchild;
}

/* They are received by `receive_mounts`. */
ret = prepare_and_send_mounts (container, &init_status, pid, sync_socket_host, err);
if (UNLIKELY (ret < 0))
return ret;

ret = expect_success_from_sync_socket (sync_socket_host, err);
if (UNLIKELY (ret < 0))
return ret;
Expand Down
14 changes: 13 additions & 1 deletion src/libcrun/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ send_fd_to_socket_with_payload (int server, int fd, const char *payload, size_t
}

int
receive_fd_from_socket (int from, libcrun_error_t *err)
receive_fd_from_socket_with_payload (int from, char *payload, size_t payload_len, libcrun_error_t *err)
{
cleanup_close int fd = -1;
int ret;
Expand All @@ -1024,6 +1024,12 @@ receive_fd_from_socket (int from, libcrun_error_t *err)
iov[0].iov_base = data;
iov[0].iov_len = sizeof (data);

if (payload_len > 0)
{
iov[0].iov_base = (void *) payload;
iov[0].iov_len = payload_len;
}

msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
Expand All @@ -1047,6 +1053,12 @@ receive_fd_from_socket (int from, libcrun_error_t *err)
return ret;
}

int
receive_fd_from_socket (int from, libcrun_error_t *err)
{
return receive_fd_from_socket_with_payload (from, NULL, 0, err);
}

int
create_socket_pair (int *pair, libcrun_error_t *err)
{
Expand Down
2 changes: 2 additions & 0 deletions src/libcrun/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ int create_socket_pair (int *pair, libcrun_error_t *err);

int receive_fd_from_socket (int from, libcrun_error_t *err);

int receive_fd_from_socket_with_payload (int from, char *payload, size_t payload_len, libcrun_error_t *err);

int create_signalfd (sigset_t *mask, libcrun_error_t *err);

int epoll_helper (int *fds, int *levelfds, libcrun_error_t *err);
Expand Down

0 comments on commit dc2d666

Please sign in to comment.