conf: support idmapped lxc.mount.entry entries

parent 1e4bce2c
...@@ -164,6 +164,16 @@ int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, ...@@ -164,6 +164,16 @@ int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data,
return lxc_abstract_unix_send_fds(fd, sendfds, num_sendfds, data, size); return lxc_abstract_unix_send_fds(fd, sendfds, num_sendfds, data, size);
} }
int __lxc_abstract_unix_send_two_fds(int fd, int fd_first, int fd_second,
void *data, size_t size)
{
int fd_send[2] = {
fd_first,
fd_second,
};
return lxc_abstract_unix_send_fds(fd, fd_send, 2, data, size);
}
static ssize_t lxc_abstract_unix_recv_fds_iov(int fd, static ssize_t lxc_abstract_unix_recv_fds_iov(int fd,
struct unix_fds *ret_fds, struct unix_fds *ret_fds,
struct iovec *ret_iov, struct iovec *ret_iov,
...@@ -355,13 +365,14 @@ ssize_t lxc_abstract_unix_recv_one_fd(int fd, int *ret_fd, void *ret_data, ...@@ -355,13 +365,14 @@ ssize_t lxc_abstract_unix_recv_one_fd(int fd, int *ret_fd, void *ret_data,
return ret; return ret;
} }
ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *ret_fd) ssize_t __lxc_abstract_unix_recv_two_fds(int fd, int *fd_first, int *fd_second,
void *data, size_t size)
{ {
call_cleaner(put_unix_fds) struct unix_fds *fds = NULL; call_cleaner(put_unix_fds) struct unix_fds *fds = NULL;
char buf[1] = {}; char buf[1] = {};
struct iovec iov = { struct iovec iov = {
.iov_base = buf, .iov_base = data ?: buf,
.iov_len = sizeof(buf), .iov_len = size ?: sizeof(buf),
}; };
ssize_t ret; ssize_t ret;
...@@ -377,11 +388,11 @@ ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *ret_fd) ...@@ -377,11 +388,11 @@ ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *ret_fd)
return ret_errno(ENODATA); return ret_errno(ENODATA);
if (fds->fd_count_ret != fds->fd_count_max) { if (fds->fd_count_ret != fds->fd_count_max) {
ret_fd[0] = -EBADF; *fd_first = -EBADF;
ret_fd[1] = -EBADF; *fd_second = -EBADF;
} else { } else {
ret_fd[0] = move_fd(fds->fd[0]); *fd_first = move_fd(fds->fd[0]);
ret_fd[1] = move_fd(fds->fd[1]); *fd_second = move_fd(fds->fd[1]);
} }
return 0; return 0;
......
...@@ -125,7 +125,24 @@ __hidden extern ssize_t lxc_abstract_unix_recv_one_fd(int fd, int *ret_fd, ...@@ -125,7 +125,24 @@ __hidden extern ssize_t lxc_abstract_unix_recv_one_fd(int fd, int *ret_fd,
size_t size_ret_data) size_t size_ret_data)
__access_r(3, 4); __access_r(3, 4);
__hidden extern ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *ret_fd); __hidden extern int __lxc_abstract_unix_send_two_fds(int fd, int fd_first,
int fd_second, void *data,
size_t size);
static inline int lxc_abstract_unix_send_two_fds(int fd, int fd_first,
int fd_second)
{
return __lxc_abstract_unix_send_two_fds(fd, fd_first, fd_second, NULL, 0);
}
__hidden extern ssize_t __lxc_abstract_unix_recv_two_fds(int fd, int *fd_first,
int *fd_second,
void *data, size_t size);
static inline ssize_t lxc_abstract_unix_recv_two_fds(int fd, int *fd_first, int *fd_second)
{
return __lxc_abstract_unix_recv_two_fds(fd, fd_first, fd_second, NULL, 0);
}
__hidden extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, size_t size); __hidden extern int lxc_unix_send_fds(int fd, int *sendfds, int num_sendfds, void *data, size_t size);
......
...@@ -2211,16 +2211,13 @@ static int cgroup_attach_move_into_leaf(const struct lxc_conf *conf, ...@@ -2211,16 +2211,13 @@ static int cgroup_attach_move_into_leaf(const struct lxc_conf *conf,
int *sk_fd, pid_t pid) int *sk_fd, pid_t pid)
{ {
__do_close int sk = *sk_fd, target_fd0 = -EBADF, target_fd1 = -EBADF; __do_close int sk = *sk_fd, target_fd0 = -EBADF, target_fd1 = -EBADF;
int target_fds[2];
char pidstr[INTTYPE_TO_STRLEN(int64_t) + 1]; char pidstr[INTTYPE_TO_STRLEN(int64_t) + 1];
size_t pidstr_len; size_t pidstr_len;
ssize_t ret; ssize_t ret;
ret = lxc_abstract_unix_recv_two_fds(sk, target_fds); ret = lxc_abstract_unix_recv_two_fds(sk, &target_fd0, &target_fd1);
if (ret < 0) if (ret < 0)
return log_error_errno(-1, errno, "Failed to receive target cgroup fd"); return log_error_errno(-1, errno, "Failed to receive target cgroup fd");
target_fd0 = target_fds[0];
target_fd1 = target_fds[1];
pidstr_len = sprintf(pidstr, INT64_FMT, (int64_t)pid); pidstr_len = sprintf(pidstr, INT64_FMT, (int64_t)pid);
......
...@@ -201,12 +201,13 @@ struct lxc_mount_options { ...@@ -201,12 +201,13 @@ struct lxc_mount_options {
int create_file : 1; int create_file : 1;
int optional : 1; int optional : 1;
int relative : 1; int relative : 1;
int userns_self : 1; int recursive : 1;
int bind : 1;
char userns_path[PATH_MAX]; char userns_path[PATH_MAX];
int userns_fd;
unsigned long mnt_flags; unsigned long mnt_flags;
unsigned long prop_flags; unsigned long prop_flags;
char *data; char *data;
struct lxc_mount_attr attr;
}; };
/* Defines a structure to store the rootfs location, the /* Defines a structure to store the rootfs location, the
...@@ -512,9 +513,12 @@ __hidden extern int lxc_rootfs_prepare(struct lxc_conf *conf, bool userns); ...@@ -512,9 +513,12 @@ __hidden extern int lxc_rootfs_prepare(struct lxc_conf *conf, bool userns);
__hidden extern void lxc_storage_put(struct lxc_conf *conf); __hidden extern void lxc_storage_put(struct lxc_conf *conf);
__hidden extern int lxc_rootfs_init(struct lxc_conf *conf, bool userns); __hidden extern int lxc_rootfs_init(struct lxc_conf *conf, bool userns);
__hidden extern int lxc_rootfs_prepare_parent(struct lxc_handler *handler); __hidden extern int lxc_rootfs_prepare_parent(struct lxc_handler *handler);
__hidden extern int lxc_idmapped_mounts_parent(struct lxc_handler *handler);
__hidden extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid); __hidden extern int lxc_map_ids(struct lxc_list *idmap, pid_t pid);
__hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf); __hidden extern int lxc_create_tty(const char *name, struct lxc_conf *conf);
__hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys); __hidden extern void lxc_delete_tty(struct lxc_tty_info *ttys);
__hidden extern int lxc_send_ttys_to_parent(struct lxc_handler *handler);
__hidden extern int lxc_send_devpts_to_parent(struct lxc_handler *handler);
__hidden extern int lxc_clear_config_caps(struct lxc_conf *c); __hidden extern int lxc_clear_config_caps(struct lxc_conf *c);
__hidden extern int lxc_clear_config_keepcaps(struct lxc_conf *c); __hidden extern int lxc_clear_config_keepcaps(struct lxc_conf *c);
__hidden extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version); __hidden extern int lxc_clear_cgroups(struct lxc_conf *c, const char *key, int version);
...@@ -541,7 +545,7 @@ __hidden extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), v ...@@ -541,7 +545,7 @@ __hidden extern int userns_exec_full(struct lxc_conf *conf, int (*fn)(void *), v
const char *fn_name); const char *fn_name);
__hidden extern int parse_mntopts_legacy(const char *mntopts, unsigned long *mntflags, char **mntdata); __hidden extern int parse_mntopts_legacy(const char *mntopts, unsigned long *mntflags, char **mntdata);
__hidden extern int parse_propagationopts(const char *mntopts, unsigned long *pflags); __hidden extern int parse_propagationopts(const char *mntopts, unsigned long *pflags);
__hidden extern int parse_lxc_mntopts(struct lxc_mount_options *opts, char *mnt_opts); __hidden extern int parse_lxc_mount_attrs(struct lxc_mount_options *opts, char *mnt_opts);
__hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf); __hidden extern void tmp_proc_unmount(struct lxc_conf *lxc_conf);
__hidden extern void suggest_default_idmap(void); __hidden extern void suggest_default_idmap(void);
__hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers); __hidden extern FILE *make_anonymous_mount_file(struct lxc_list *mount, bool include_nesting_helpers);
...@@ -593,12 +597,10 @@ static inline void put_lxc_mount_options(struct lxc_mount_options *mnt_opts) ...@@ -593,12 +597,10 @@ static inline void put_lxc_mount_options(struct lxc_mount_options *mnt_opts)
mnt_opts->create_file = 0; mnt_opts->create_file = 0;
mnt_opts->optional = 0; mnt_opts->optional = 0;
mnt_opts->relative = 0; mnt_opts->relative = 0;
mnt_opts->userns_self = 0;
mnt_opts->userns_path[0] = '\0'; mnt_opts->userns_path[0] = '\0';
mnt_opts->mnt_flags = 0; mnt_opts->mnt_flags = 0;
mnt_opts->prop_flags = 0; mnt_opts->prop_flags = 0;
close_prot_errno_disarm(mnt_opts->userns_fd);
free_disarm(mnt_opts->data); free_disarm(mnt_opts->data);
} }
...@@ -608,7 +610,6 @@ static inline void put_lxc_rootfs(struct lxc_rootfs *rootfs, bool unpin) ...@@ -608,7 +610,6 @@ static inline void put_lxc_rootfs(struct lxc_rootfs *rootfs, bool unpin)
close_prot_errno_disarm(rootfs->dfd_host); close_prot_errno_disarm(rootfs->dfd_host);
close_prot_errno_disarm(rootfs->dfd_mnt); close_prot_errno_disarm(rootfs->dfd_mnt);
close_prot_errno_disarm(rootfs->dfd_dev); close_prot_errno_disarm(rootfs->dfd_dev);
close_prot_errno_disarm(rootfs->mnt_opts.userns_fd);
if (unpin) if (unpin)
close_prot_errno_disarm(rootfs->fd_path_pin); close_prot_errno_disarm(rootfs->fd_path_pin);
close_prot_errno_disarm(rootfs->dfd_idmapped); close_prot_errno_disarm(rootfs->dfd_idmapped);
......
...@@ -2799,7 +2799,7 @@ static int set_config_rootfs_options(const char *key, const char *value, ...@@ -2799,7 +2799,7 @@ static int set_config_rootfs_options(const char *key, const char *value,
if (!dup) if (!dup)
return -ENOMEM; return -ENOMEM;
ret = parse_lxc_mntopts(mnt_opts, dup); ret = parse_lxc_mount_attrs(mnt_opts, dup);
if (ret < 0) if (ret < 0)
return ret; return ret;
......
...@@ -1291,12 +1291,6 @@ static int do_start(void *data) ...@@ -1291,12 +1291,6 @@ static int do_start(void *data)
if (ret < 0) if (ret < 0)
goto out_warn_father; goto out_warn_father;
ret = lxc_seccomp_send_notifier_fd(&handler->conf->seccomp, data_sock0);
if (ret < 0) {
SYSERROR("Failed to send seccomp notify fd to parent");
goto out_warn_father;
}
ret = run_lxc_hooks(handler->name, "start", handler->conf, NULL); ret = run_lxc_hooks(handler->name, "start", handler->conf, NULL);
if (ret < 0) { if (ret < 0) {
ERROR("Failed to run lxc.hook.start for container \"%s\"", ERROR("Failed to run lxc.hook.start for container \"%s\"",
...@@ -1336,6 +1330,35 @@ static int do_start(void *data) ...@@ -1336,6 +1330,35 @@ static int do_start(void *data)
if (!lxc_sync_barrier_parent(handler, START_SYNC_CGROUP_LIMITS)) if (!lxc_sync_barrier_parent(handler, START_SYNC_CGROUP_LIMITS))
goto out_warn_father; goto out_warn_father;
ret = lxc_seccomp_send_notifier_fd(&handler->conf->seccomp, data_sock0);
if (ret < 0) {
SYSERROR("Failed to send seccomp notify fd to parent");
goto out_warn_father;
}
ret = lxc_send_devpts_to_parent(handler);
if (ret < 0) {
SYSERROR("Failed to send seccomp devpts fd to parent");
goto out_warn_father;
}
ret = lxc_send_ttys_to_parent(handler);
if (ret < 0) {
SYSERROR("Failed to send tty file descriptors to parent");
goto out_warn_father;
}
if (handler->ns_clone_flags & CLONE_NEWNET) {
ret = lxc_network_send_name_and_ifindex_to_parent(handler);
if (ret < 0) {
SYSERROR("Failed to send network device names and ifindices to parent");
goto out_warn_father;
}
}
if (!lxc_sync_wait_parent(handler, START_SYNC_READY_START))
goto out_warn_father;
/* Reset the environment variables the user requested in a clear /* Reset the environment variables the user requested in a clear
* environment. * environment.
*/ */
...@@ -1458,16 +1481,16 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler) ...@@ -1458,16 +1481,16 @@ static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
return -1; return -1;
for (i = 0; i < conf->ttys.max; i++) { for (i = 0; i < conf->ttys.max; i++) {
int ttyfds[2]; int ttyx = -EBADF, ttyy = -EBADF;
ret = lxc_abstract_unix_recv_two_fds(sock, ttyfds); ret = lxc_abstract_unix_recv_two_fds(sock, &ttyx, &ttyy);
if (ret < 0) if (ret < 0)
break; break;
tty = &ttys->tty[i]; tty = &ttys->tty[i];
tty->busy = -1; tty->busy = -1;
tty->ptx = ttyfds[0]; tty->ptx = ttyx;
tty->pty = ttyfds[1]; tty->pty = ttyy;
TRACE("Received pty with ptx fd %d and pty fd %d from child", tty->ptx, tty->pty); TRACE("Received pty with ptx fd %d and pty fd %d from child", tty->ptx, tty->pty);
} }
...@@ -1875,6 +1898,15 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1875,6 +1898,15 @@ static int lxc_spawn(struct lxc_handler *handler)
if (!lxc_sync_barrier_child(handler, START_SYNC_CGROUP_UNSHARE)) if (!lxc_sync_barrier_child(handler, START_SYNC_CGROUP_UNSHARE))
goto out_delete_net; goto out_delete_net;
ret = lxc_idmapped_mounts_parent(handler);
if (ret) {
ERROR("Failed to setup mount entries");
goto out_delete_net;
}
if (!lxc_sync_wait_child(handler, START_SYNC_CGROUP_LIMITS))
goto out_delete_net;
/* /*
* With isolation the limiting devices cgroup was already setup, so * With isolation the limiting devices cgroup was already setup, so
* only setup devices here if we have no namespace directory. * only setup devices here if we have no namespace directory.
...@@ -1924,21 +1956,13 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1924,21 +1956,13 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
/* Tell the child to complete its initialization and wait for it to exec if (!lxc_sync_wake_child(handler, START_SYNC_FDS))
* or return an error. (The child will never return
* START_SYNC_READY_START+1. It will either close the sync pipe, causing
* lxc_sync_barrier_child to return success, or return a different
* value, causing us to error out).
*/
if (!lxc_sync_barrier_child(handler, START_SYNC_READY_START))
goto out_delete_net; goto out_delete_net;
if (handler->ns_clone_flags & CLONE_NEWNET) { ret = lxc_seccomp_recv_notifier_fd(&handler->conf->seccomp, data_sock1);
ret = lxc_network_recv_name_and_ifindex_from_child(handler); if (ret < 0) {
if (ret < 0) { SYSERROR("Failed to receive seccomp notify fd from child");
ERROR("Failed to receive names and ifindices for network devices from child"); goto out_delete_net;
goto out_delete_net;
}
} }
ret = lxc_setup_devpts_parent(handler); ret = lxc_setup_devpts_parent(handler);
...@@ -1947,13 +1971,6 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1947,13 +1971,6 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
/* Now all networks are created, network devices are moved into place,
* and the correct names and ifindices in the respective namespaces have
* been recorded. The corresponding structs have now all been filled. So
* log them for debugging purposes.
*/
lxc_log_configured_netdevs(conf);
/* Read tty fds allocated by child. */ /* Read tty fds allocated by child. */
ret = lxc_recv_ttys_from_child(handler); ret = lxc_recv_ttys_from_child(handler);
if (ret < 0) { if (ret < 0) {
...@@ -1961,12 +1978,31 @@ static int lxc_spawn(struct lxc_handler *handler) ...@@ -1961,12 +1978,31 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net; goto out_delete_net;
} }
ret = lxc_seccomp_recv_notifier_fd(&handler->conf->seccomp, data_sock1); if (handler->ns_clone_flags & CLONE_NEWNET) {
if (ret < 0) { ret = lxc_network_recv_name_and_ifindex_from_child(handler);
SYSERROR("Failed to receive seccomp notify fd from child"); if (ret < 0) {
goto out_delete_net; ERROR("Failed to receive names and ifindices for network devices from child");
goto out_delete_net;
}
} }
/*
* Tell the child to complete its initialization and wait for it to
* exec or return an error. (The child will never return
* START_SYNC_READY_START+1. It will either close the sync pipe,
* causing lxc_sync_barrier_child to return success, or return a
* different value, causing us to error out).
*/
if (!lxc_sync_barrier_child(handler, START_SYNC_READY_START))
goto out_delete_net;
/* Now all networks are created, network devices are moved into place,
* and the correct names and ifindices in the respective namespaces have
* been recorded. The corresponding structs have now all been filled. So
* log them for debugging purposes.
*/
lxc_log_configured_netdevs(conf);
ret = handler->ops->post_start(handler, handler->data); ret = handler->ops->post_start(handler, handler->data);
if (ret < 0) if (ret < 0)
goto out_abort; goto out_abort;
......
...@@ -321,7 +321,6 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname, ...@@ -321,7 +321,6 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
.dfd_host = -EBADF, .dfd_host = -EBADF,
.fd_path_pin = -EBADF, .fd_path_pin = -EBADF,
.dfd_idmapped = -EBADF, .dfd_idmapped = -EBADF,
.mnt_opts.userns_fd = -EBADF,
}; };
if (!src) { if (!src) {
......
...@@ -74,6 +74,10 @@ static inline const char *start_sync_to_string(int state) ...@@ -74,6 +74,10 @@ static inline const char *start_sync_to_string(int state)
return "cgroup-unshare"; return "cgroup-unshare";
case START_SYNC_CGROUP_LIMITS: case START_SYNC_CGROUP_LIMITS:
return "cgroup-limits"; return "cgroup-limits";
case START_SYNC_IDMAPPED_MOUNTS:
return "idmapped-mounts";
case START_SYNC_FDS:
return "fds";
case START_SYNC_READY_START: case START_SYNC_READY_START:
return "ready-start"; return "ready-start";
case START_SYNC_RESTART: case START_SYNC_RESTART:
...@@ -109,13 +113,13 @@ bool lxc_sync_wake_parent(struct lxc_handler *handler, int sequence) ...@@ -109,13 +113,13 @@ bool lxc_sync_wake_parent(struct lxc_handler *handler, int sequence)
bool lxc_sync_wait_parent(struct lxc_handler *handler, int sequence) bool lxc_sync_wait_parent(struct lxc_handler *handler, int sequence)
{ {
TRACE("Parent waiting for child with sequence %s", start_sync_to_string(sequence)); TRACE("Child waiting for parent with sequence %s", start_sync_to_string(sequence));
return sync_wait(handler->sync_sock[0], sequence); return sync_wait(handler->sync_sock[0], sequence);
} }
bool lxc_sync_wait_child(struct lxc_handler *handler, int sequence) bool lxc_sync_wait_child(struct lxc_handler *handler, int sequence)
{ {
TRACE("Child waiting for parent with sequence %s", start_sync_to_string(sequence)); TRACE("Parent waiting for child with sequence %s", start_sync_to_string(sequence));
return sync_wait(handler->sync_sock[1], sequence); return sync_wait(handler->sync_sock[1], sequence);
} }
......
...@@ -19,10 +19,12 @@ enum /* start */ { ...@@ -19,10 +19,12 @@ enum /* start */ {
START_SYNC_POST_CONFIGURE = 2, START_SYNC_POST_CONFIGURE = 2,
START_SYNC_CGROUP = 3, START_SYNC_CGROUP = 3,
START_SYNC_CGROUP_UNSHARE = 4, START_SYNC_CGROUP_UNSHARE = 4,
START_SYNC_CGROUP_LIMITS = 5, START_SYNC_IDMAPPED_MOUNTS = 5,
START_SYNC_READY_START = 6, START_SYNC_CGROUP_LIMITS = 6,
START_SYNC_RESTART = 7, START_SYNC_FDS = 7,
START_SYNC_POST_RESTART = 8, START_SYNC_READY_START = 8,
START_SYNC_RESTART = 9,
START_SYNC_POST_RESTART = 10,
}; };
enum /* attach */ { enum /* attach */ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment