2
0
mirror of git://github.com/lxc/lxc synced 2025-08-31 00:19:33 +00:00

Merge pull request #3920 from brauner/2021-08-02.fixes

mount_utils: introduce mount_at()
This commit is contained in:
Stéphane Graber
2021-08-02 14:33:37 -04:00
committed by GitHub
3 changed files with 82 additions and 78 deletions

View File

@@ -1089,7 +1089,7 @@ static int lxc_allocate_ttys(struct lxc_conf *conf)
void lxc_delete_tty(struct lxc_tty_info *ttys)
{
if (!ttys->tty)
if (!ttys || !ttys->tty)
return;
for (int i = 0; i < ttys->max; i++) {
@@ -1742,7 +1742,9 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
for (ret = -1, opts = mntopt_sets; opts && *opts; opts++) {
/* mount new devpts instance */
ret = mount_beneath_fd(rootfs->dfd_dev, "", "pts", "devpts", MS_NOSUID | MS_NOEXEC, *opts);
ret = mount_at(rootfs->dfd_dev, "", 0,
rootfs->dfd_dev, "pts", PROTECT_LOOKUP_BENEATH,
"devpts", MS_NOSUID | MS_NOEXEC, *opts);
if (ret == 0)
break;
}
@@ -1775,7 +1777,9 @@ static int lxc_setup_devpts_child(struct lxc_handler *handler)
DEBUG("Created \"/dev/ptmx\" file as bind mount target");
/* Main option: use a bind-mount to please AppArmor */
ret = mount_beneath_fd(rootfs->dfd_dev, "pts/ptmx", "ptmx", NULL, MS_BIND, NULL);
ret = mount_at(rootfs->dfd_dev, "pts/ptmx", (PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS & ~RESOLVE_NO_XDEV),
rootfs->dfd_dev, "ptmx", (PROTECT_LOOKUP_BENEATH_WITH_SYMLINKS & ~RESOLVE_NO_XDEV),
NULL, MS_BIND, NULL);
if (!ret)
return log_debug(0, "Bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
else
@@ -3026,7 +3030,7 @@ static int lxc_idmapped_mounts_child(struct lxc_handler *handler)
out:
ret = lxc_abstract_unix_send_credential(handler->data_sock[0], NULL, 0);
if (ret < 0)
return syserror("Failed to inform child that we are done setting up mounts");
return syserror("Failed to inform parent that we are done setting up mounts");
return fret;
}
@@ -4055,40 +4059,45 @@ int lxc_idmapped_mounts_parent(struct lxc_handler *handler)
static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
{
int i;
struct lxc_terminal_info *tty;
int ret = -1;
call_cleaner(lxc_delete_tty) struct lxc_tty_info *info_new = &(struct lxc_tty_info){};
int sock = handler->data_sock[1];
struct lxc_conf *conf = handler->conf;
struct lxc_tty_info *ttys = &conf->ttys;
struct lxc_tty_info *tty_info = &conf->ttys;
size_t ttys_max = tty_info->max;
struct lxc_terminal_info *terminal_info;
int ret;
if (!conf->ttys.max)
if (!ttys_max)
return 0;
ttys->tty = malloc(sizeof(*ttys->tty) * ttys->max);
if (!ttys->tty)
return -1;
info_new->tty = malloc(sizeof(*(info_new->tty)) * ttys_max);
if (!info_new->tty)
return ret_errno(ENOMEM);
for (i = 0; i < conf->ttys.max; i++) {
int ttyx = -EBADF, ttyy = -EBADF;
ret = lxc_abstract_unix_recv_two_fds(sock, &ttyx, &ttyy);
if (ret < 0)
break;
tty = &ttys->tty[i];
tty->busy = -1;
tty->ptx = ttyx;
tty->pty = ttyy;
TRACE("Received pty with ptx fd %d and pty fd %d from child", tty->ptx, tty->pty);
for (int i = 0; i < ttys_max; i++) {
terminal_info = &info_new->tty[i];
terminal_info->busy = -1;
terminal_info->ptx = -EBADF;
terminal_info->pty = -EBADF;
}
if (ret < 0)
SYSERROR("Failed to receive %zu ttys from child", ttys->max);
else
TRACE("Received %zu ttys from child", ttys->max);
for (int i = 0; i < ttys_max; i++) {
int ptx = -EBADF, pty = -EBADF;
return ret;
ret = lxc_abstract_unix_recv_two_fds(sock, &ptx, &pty);
if (ret < 0)
return syserror("Failed to receive %zu ttys from child", ttys_max);
terminal_info = &info_new->tty[i];
terminal_info->ptx = ptx;
terminal_info->pty = pty;
TRACE("Received pty with ptx fd %d and pty fd %d from child",
terminal_info->ptx, terminal_info->pty);
}
tty_info->tty = move_ptr(info_new->tty);
TRACE("Received %zu ttys from child", ttys_max);
return 0;
}
static int lxc_send_console_to_parent(struct lxc_handler *handler)

View File

@@ -606,66 +606,56 @@ bool can_use_bind_mounts(void)
return supported == 1;
}
int mount_beneath_fd(int fd, const char *source, const char *target,
const char *fs_name, unsigned int flags, const void *data)
int mount_at(int dfd_from, const char *path_from, __u64 resolve_flags_from,
int dfd_to, const char *path_to, __u64 resolve_flags_to,
const char *fs_name, unsigned int flags, const void *data)
{
int ret;
char buf_source[PATH_MAX], buf_target[PATH_MAX];
__do_close int __fd_from = -EBADF, __fd_to = -EBADF;
char *from = NULL, *to = NULL;
int fd_from, fd_to, ret;
char buf_from[LXC_PROC_SELF_FD_LEN], buf_to[LXC_PROC_SELF_FD_LEN];
if (abspath(source) || abspath(target))
if (dfd_from < 0 && !abspath(path_from))
return ret_errno(EINVAL);
ret = strnprintf(buf_target, sizeof(buf_target), "/proc/self/fd/%d/%s", fd, target);
if (ret < 0)
return syserror("Failed to create path");
if (dfd_to < 0 && !abspath(path_to))
return ret_errno(EINVAL);
if (is_empty_string(source)) {
ret = mount(fs_name ?: "", buf_target, fs_name, flags, data);
if (!is_empty_string(path_from)) {
__fd_from = open_at(dfd_from, path_from, PROTECT_OPATH_FILE, resolve_flags_from, 0);
if (__fd_from < 0)
return -errno;
fd_from = __fd_from;
} else {
ret = strnprintf(buf_source, sizeof(buf_source), "/proc/self/fd/%d/%s", fd, source);
fd_from = dfd_from;
}
if (fd_from >= 0) {
ret = strnprintf(buf_from, sizeof(buf_from), "/proc/self/fd/%d", fd_from);
if (ret < 0)
return syserror("Failed to create path");
source = buf_source;
ret = mount(source, buf_target, fs_name, flags, data);
from = buf_from;
}
if (ret < 0)
return syserror("Failed to mount \"%s\" to \"%s\"", source, buf_target);
TRACE("Mounted \"%s\" to \"%s\"", source, buf_target);
return 0;
}
int mount_fd(int fd_source, int fd_target, const char *fs_name,
unsigned int flags, const void *data)
{
int ret;
char buf_source[LXC_PROC_PID_FD_LEN], buf_target[LXC_PROC_PID_FD_LEN];
char *source = buf_source, *target = buf_target;
if (fd_source < 0) {
source = NULL;
if (!is_empty_string(path_to)) {
__fd_to = open_at(dfd_to, path_to, PROTECT_OPATH_FILE, resolve_flags_to, 0);
if (__fd_to < 0)
return -errno;
fd_to = __fd_to;
} else {
ret = strnprintf(buf_source, sizeof(buf_source),
"/proc/self/fd/%d", fd_source);
fd_to = dfd_to;
}
if (fd_to >= 0) {
ret = strnprintf(buf_to, sizeof(buf_to), "/proc/self/fd/%d", fd_to);
if (ret < 0)
return ret;
return syserror("Failed to create path");
to = buf_to;
}
if (fd_target < 0) {
target = NULL;
} else {
ret = strnprintf(buf_target, sizeof(buf_target),
"/proc/self/fd/%d", fd_target);
if (ret < 0)
return ret;
}
ret = mount(source, target, "none", MS_BIND, 0);
ret = mount(from ?: fs_name, to, fs_name, flags, data);
if (ret < 0)
return syserror("Failed to mount \"%s\" to \"%s\"",
maybe_empty(source), maybe_empty(target));
maybe_empty(from), maybe_empty(to));
TRACE("Mounted \"%s\" to \"%s\"", maybe_empty(source), maybe_empty(target));
TRACE("Mounted \"%s\" to \"%s\"", maybe_empty(from), maybe_empty(to));
return 0;
}

View File

@@ -221,10 +221,15 @@ __hidden extern unsigned long add_required_remount_flags(const char *s,
__hidden extern bool can_use_mount_api(void);
__hidden extern bool can_use_bind_mounts(void);
__hidden extern int mount_beneath_fd(int fd, const char *source,
const char *target, const char *fs_name,
unsigned int flags, const void *data);
__hidden extern int mount_fd(int fd_source, int fd_target, const char *fs_name,
unsigned int flags, const void *data);
__hidden extern int mount_at(int dfd_from, const char *path_from,
__u64 resolve_flags_from, int dfd_to,
const char *path_to, __u64 resolve_flags_to,
const char *fs_name, unsigned int flags,
const void *data);
static inline int mount_fd(int fd_from, int fd_to, const char *fs_name,
unsigned int flags, const void *data)
{
return mount_at(fd_from, "", 0, fd_to, "", 0, fs_name, flags, data);
}
#endif /* __LXC_MOUNT_UTILS_H */