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:
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
Reference in New Issue
Block a user