Commit 9795e880 by Stéphane Graber Committed by GitHub

Merge pull request #1613 from brauner/2017-06-03/af_unix

abstract lxc_abstract_unix_{send,recv}_fd, bugfixes, and improvements
parents 3b011155 a394f952
......@@ -22,6 +22,8 @@
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
......@@ -133,49 +135,66 @@ int lxc_abstract_unix_connect(const char *path)
return fd;
}
int lxc_abstract_unix_send_fd(int fd, int sendfd, void *data, size_t size)
int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
void *data, size_t size)
{
struct msghdr msg = { 0 };
int ret;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0};
struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
int *val;
char *cmsgbuf;
size_t cmsgbufsize = CMSG_SPACE(num_sendfds * sizeof(int));
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
cmsgbuf = malloc(cmsgbufsize);
if (!cmsgbuf)
return -1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_controllen = cmsgbufsize;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
val = (int *)(CMSG_DATA(cmsg));
*val = sendfd;
cmsg->cmsg_len = CMSG_LEN(num_sendfds * sizeof(int));
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_controllen = cmsg->cmsg_len;
memcpy(CMSG_DATA(cmsg), sendfds, num_sendfds * sizeof(int));
iov.iov_base = data ? data : buf;
iov.iov_len = data ? size : sizeof(buf);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
return sendmsg(fd, &msg, MSG_NOSIGNAL);
ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
free(cmsgbuf);
return ret;
}
int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size)
int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
void *data, size_t size)
{
struct msghdr msg = { 0 };
int ret;
struct msghdr msg;
struct iovec iov;
struct cmsghdr *cmsg;
int ret, *val;
char cmsgbuf[CMSG_SPACE(sizeof(int))] = {0};
struct cmsghdr *cmsg = NULL;
char buf[1] = {0};
char *cmsgbuf;
size_t cmsgbufsize = CMSG_SPACE(num_recvfds * sizeof(int));
memset(&msg, 0, sizeof(msg));
memset(&iov, 0, sizeof(iov));
cmsgbuf = malloc(cmsgbufsize);
if (!cmsgbuf)
return -1;
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
msg.msg_controllen = cmsgbufsize;
iov.iov_base = data ? data : buf;
iov.iov_len = data ? size : sizeof(buf);
......@@ -188,17 +207,14 @@ int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size)
cmsg = CMSG_FIRSTHDR(&msg);
/* if the message is wrong the variable will not be
* filled and the peer will notified about a problem */
*recvfd = -1;
if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type == SCM_RIGHTS) {
val = (int *) CMSG_DATA(cmsg);
*recvfd = *val;
memset(recvfds, -1, num_recvfds * sizeof(int));
if (cmsg && cmsg->cmsg_len == CMSG_LEN(num_recvfds * sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
memcpy(recvfds, CMSG_DATA(cmsg), num_recvfds * sizeof(int));
}
out:
free(cmsgbuf);
return ret;
}
......
......@@ -24,13 +24,17 @@
#ifndef __LXC_AF_UNIX_H
#define __LXC_AF_UNIX_H
#include <stdio.h>
/* does not enforce \0-termination */
extern int lxc_abstract_unix_open(const char *path, int type, int flags);
extern int lxc_abstract_unix_close(int fd);
/* does not enforce \0-termination */
extern int lxc_abstract_unix_connect(const char *path);
extern int lxc_abstract_unix_send_fd(int fd, int sendfd, void *data, size_t size);
extern int lxc_abstract_unix_recv_fd(int fd, int *recvfd, void *data, size_t size);
extern int lxc_abstract_unix_send_fds(int fd, int *sendfds, int num_sendfds,
void *data, size_t size);
extern int lxc_abstract_unix_recv_fds(int fd, int *recvfds, int num_recvfds,
void *data, size_t size);
extern int lxc_abstract_unix_send_credential(int fd, void *data, size_t size);
extern int lxc_abstract_unix_rcv_credential(int fd, void *data, size_t size);
......
......@@ -986,7 +986,7 @@ int lxc_attach(const char* name, const char* lxcpath, lxc_attach_exec_t exec_fun
goto on_error;
/* Send child fd of the LSM security module to write to. */
ret = lxc_abstract_unix_send_fd(ipc_sockets[0], labelfd, NULL, 0);
ret = lxc_abstract_unix_send_fds(ipc_sockets[0], &labelfd, 1, NULL, 0);
saved_errno = errno;
close(labelfd);
if (ret <= 0) {
......@@ -1273,7 +1273,7 @@ static int attach_child_main(void* data)
if ((options->namespaces & CLONE_NEWNS) && (options->attach_flags & LXC_ATTACH_LSM) && init_ctx->lsm_label) {
int on_exec;
/* Receive fd for LSM security module. */
ret = lxc_abstract_unix_recv_fd(ipc_socket, &lsm_labelfd, NULL, 0);
ret = lxc_abstract_unix_recv_fds(ipc_socket, &lsm_labelfd, 1, NULL, 0);
if (ret <= 0) {
ERROR("Expected to receive file descriptor: %s.", strerror(errno));
shutdown(ipc_socket, SHUT_RDWR);
......
......@@ -23,17 +23,13 @@
#ifndef __LXC_BDEV_H
#define __LXC_BDEV_H
/* blockdev operations for:
* aufs, dir, raw, btrfs, overlayfs, aufs, lvm, loop, zfs, nbd (qcow2, raw, vdi, qed)
*/
#include <lxc/lxccontainer.h>
#include "config.h"
#include <stdint.h>
#include <sys/mount.h>
#include "config.h"
#include <lxc/lxccontainer.h>
/* define constants if the kernel/glibc headers don't define them */
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#endif
......@@ -71,20 +67,21 @@ struct bdev_ops {
int (*umount)(struct bdev *bdev);
int (*destroy)(struct bdev *bdev);
int (*create)(struct bdev *bdev, const char *dest, const char *n,
struct bdev_specs *specs);
struct bdev_specs *specs);
/* given original mount, rename the paths for cloned container */
int (*clone_paths)(struct bdev *orig, struct bdev *new, const char *oldname,
const char *cname, const char *oldpath, const char *lxcpath,
int snap, uint64_t newsize, struct lxc_conf *conf);
int (*clone_paths)(struct bdev *orig, struct bdev *new,
const char *oldname, const char *cname,
const char *oldpath, const char *lxcpath, int snap,
uint64_t newsize, struct lxc_conf *conf);
bool can_snapshot;
bool can_backup;
};
/*
* When lxc-start (conf.c) is mounting a rootfs, then src will be the
* 'lxc.rootfs' value, dest will be mount dir (i.e. $libdir/lxc) When clone
* or create is doing so, then dest will be $lxcpath/$lxcname/rootfs, since
* we may need to rsync from one to the other.
* When lxc-start is mounting a rootfs, then src will be the "lxc.rootfs" value,
* dest will be mount dir (i.e. $libdir/lxc) When clone or create is doing so,
* then dest will be $lxcpath/$lxcname/rootfs, since we may need to rsync from
* one to the other.
* data is so far unused.
*/
struct bdev {
......@@ -93,10 +90,10 @@ struct bdev {
char *src;
char *dest;
char *mntopts;
// turn the following into a union if need be
// lofd is the open fd for the mounted loopback file
/* Turn the following into a union if need be. */
/* lofd is the open fd for the mounted loopback file. */
int lofd;
// index for the connected nbd device
/* index for the connected nbd device. */
int nbd_idx;
};
......@@ -104,27 +101,27 @@ bool bdev_is_dir(struct lxc_conf *conf, const char *path);
bool bdev_can_backup(struct lxc_conf *conf);
/*
* Instantiate a bdev object. The src is used to determine which blockdev
* type this should be. The dst and data are optional, and will be used
* in case of mount/umount.
* Instantiate a bdev object. The src is used to determine which blockdev type
* this should be. The dst and data are optional, and will be used in case of
* mount/umount.
*
* Optionally, src can be 'dir:/var/lib/lxc/c1' or 'lvm:/dev/lxc/c1'. For
* other backing stores, this will allow additional options. In particular,
* other backing stores, this will allow additional options. In particular,
* "overlayfs:/var/lib/lxc/canonical/rootfs:/var/lib/lxc/c1/delta" will mean
* use /var/lib/lxc/canonical/rootfs as lower dir, and /var/lib/lxc/c1/delta
* as the upper, writeable layer.
*/
struct bdev *bdev_init(struct lxc_conf *conf, const char *src, const char *dst,
const char *data);
const char *data);
struct bdev *bdev_copy(struct lxc_container *c0, const char *cname,
const char *lxcpath, const char *bdevtype,
int flags, const char *bdevdata, uint64_t newsize,
int *needs_rdep);
struct bdev *bdev_create(const char *dest, const char *type,
const char *cname, struct bdev_specs *specs);
const char *lxcpath, const char *bdevtype, int flags,
const char *bdevdata, uint64_t newsize, int *needs_rdep);
struct bdev *bdev_create(const char *dest, const char *type, const char *cname,
struct bdev_specs *specs);
void bdev_put(struct bdev *bdev);
bool bdev_destroy(struct lxc_conf *conf);
/* callback function to be used with userns_exec_1() */
int bdev_destroy_wrapper(void *data);
......@@ -134,11 +131,12 @@ int bdev_destroy_wrapper(void *data);
*/
int blk_getsize(struct bdev *bdev, uint64_t *size);
int detect_fs(struct bdev *bdev, char *type, int len);
int do_mkfs(const char *path, const char *fstype);
int do_mkfs_exec_wrapper(void *args);
int is_blktype(struct bdev *b);
int mount_unknown_fs(const char *rootfs, const char *target,
const char *options);
bool rootfs_is_blockdev(struct lxc_conf *conf);
/*
* these are really for qemu-nbd support, as container shutdown
* must explicitly request device detach.
......
......@@ -28,6 +28,7 @@
#include <string.h>
#include <unistd.h>
#include <linux/loop.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "bdev.h"
......@@ -157,8 +158,19 @@ int loop_destroy(struct bdev *orig)
int loop_detect(const char *path)
{
int ret;
struct stat s;
if (strncmp(path, "loop:", 5) == 0)
return 1;
ret = stat(path, &s);
if (ret < 0)
return 0;
if (__S_ISTYPE(s.st_mode, S_IFREG))
return 1;
return 0;
}
......@@ -166,15 +178,23 @@ int loop_mount(struct bdev *bdev)
{
int ret, loopfd;
char loname[MAXPATHLEN];
char *src = bdev->src;
if (strcmp(bdev->type, "loop"))
return -22;
if (!bdev->src || !bdev->dest)
return -22;
loopfd = lxc_prepare_loop_dev(bdev->src + 5, loname, LO_FLAGS_AUTOCLEAR);
if (loopfd < 0)
/* skip prefix */
if (!strncmp(bdev->src, "loop:", 5))
src += 5;
loopfd = lxc_prepare_loop_dev(src, loname, LO_FLAGS_AUTOCLEAR);
if (loopfd < 0) {
ERROR("failed to prepare loop device for loop file \"%s\"", src);
return -1;
}
DEBUG("prepared loop device \"%s\"", loname);
ret = mount_unknown_fs(loname, bdev->dest, bdev->mntopts);
......@@ -206,6 +226,9 @@ int loop_umount(struct bdev *bdev)
static int do_loop_create(const char *path, uint64_t size, const char *fstype)
{
int fd, ret;
const char *cmd_args[2] = {fstype, path};
char cmd_output[MAXPATHLEN];
// create the new loopback file.
fd = creat(path, S_IRUSR|S_IWUSR);
if (fd < 0)
......@@ -227,11 +250,10 @@ static int do_loop_create(const char *path, uint64_t size, const char *fstype)
}
// create an fs in the loopback file
if (do_mkfs(path, fstype) < 0) {
ERROR("Error creating filesystem type %s on %s", fstype,
path);
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
(void *)cmd_args);
if (ret < 0)
return -1;
}
return 0;
}
......@@ -282,6 +282,8 @@ int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
char fstype[100];
uint64_t size = newsize;
int len, ret;
const char *cmd_args[2];
char cmd_output[MAXPATHLEN];
if (!orig->src || !orig->dest)
return -1;
......@@ -348,11 +350,14 @@ int lvm_clonepaths(struct bdev *orig, struct bdev *new, const char *oldname,
ERROR("Error creating new lvm blockdev");
return -1;
}
if (do_mkfs(new->src, fstype) < 0) {
ERROR("Error creating filesystem type %s on %s", fstype,
new->src);
cmd_args[0] = fstype;
cmd_args[1] = new->src;
// create an fs in the loopback file
ret = run_command(cmd_output, sizeof(cmd_output),
do_mkfs_exec_wrapper, (void *)cmd_args);
if (ret < 0)
return -1;
}
}
return 0;
......@@ -378,6 +383,8 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
const char *vg, *thinpool, *fstype, *lv = n;
uint64_t sz;
int ret, len;
const char *cmd_args[2];
char cmd_output[MAXPATHLEN];
if (!specs)
return -1;
......@@ -416,11 +423,14 @@ int lvm_create(struct bdev *bdev, const char *dest, const char *n,
fstype = specs->fstype;
if (!fstype)
fstype = DEFAULT_FSTYPE;
if (do_mkfs(bdev->src, fstype) < 0) {
ERROR("Error creating filesystem type %s on %s", fstype,
bdev->src);
cmd_args[0] = fstype;
cmd_args[1] = bdev->src;
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
(void *)cmd_args);
if (ret < 0)
return -1;
}
if (!(bdev->dest = strdup(dest)))
return -1;
......
......@@ -51,6 +51,8 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
int ret, len;
char sz[24];
pid_t pid;
const char *cmd_args[2];
char cmd_output[MAXPATHLEN];
if (!specs)
return -1;
......@@ -104,11 +106,13 @@ int rbd_create(struct bdev *bdev, const char *dest, const char *n,
if (!fstype)
fstype = DEFAULT_FSTYPE;
if (do_mkfs(bdev->src, fstype) < 0) {
ERROR("Error creating filesystem type %s on %s", fstype,
bdev->src);
cmd_args[0] = fstype;
cmd_args[1] = bdev->src;
ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
(void *)cmd_args);
if (ret < 0)
return -1;
}
if (!(bdev->dest = strdup(dest)))
return -1;
......
......@@ -171,7 +171,7 @@ static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
int ret,rspfd;
struct lxc_cmd_rsp *rsp = &cmd->rsp;
ret = lxc_abstract_unix_recv_fd(sock, &rspfd, rsp, sizeof(*rsp));
ret = lxc_abstract_unix_recv_fds(sock, &rspfd, 1, rsp, sizeof(*rsp));
if (ret < 0) {
WARN("Command %s failed to receive response: %s.",
lxc_cmd_str(cmd->req.cmd), strerror(errno));
......@@ -756,7 +756,7 @@ static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
memset(&rsp, 0, sizeof(rsp));
rsp.data = INT_TO_PTR(ttynum);
if (lxc_abstract_unix_send_fd(fd, masterfd, &rsp, sizeof(rsp)) < 0) {
if (lxc_abstract_unix_send_fds(fd, &masterfd, 1, &rsp, sizeof(rsp)) < 0) {
ERROR("Failed to send tty to client.");
lxc_console_free(handler->conf, fd);
goto out_close;
......
......@@ -172,11 +172,6 @@ static int sethostname(const char * name, size_t len)
}
#endif
/* Define __S_ISTYPE if missing from the C library */
#ifndef __S_ISTYPE
#define __S_ISTYPE(mode, mask) (((mode) & S_IFMT) == (mask))
#endif
#ifndef MS_PRIVATE
#define MS_PRIVATE (1<<18)
#endif
......@@ -585,49 +580,6 @@ static int run_script(const char *name, const char *section, const char *script,
return run_buffer(buffer);
}
static int mount_rootfs_dir(const char *rootfs, const char *target,
const char *options)
{
unsigned long mntflags;
char *mntdata;
int ret;
if (parse_mntopts(options, &mntflags, &mntdata) < 0) {
free(mntdata);
return -1;
}
ret = mount(rootfs, target, "none", MS_BIND | MS_REC | mntflags, mntdata);
free(mntdata);
return ret;
}
static int lxc_mount_rootfs_file(const char *rootfs, const char *target,
const char *options)
{
int ret, loopfd;
char path[MAXPATHLEN];
loopfd = lxc_prepare_loop_dev(rootfs, path, LO_FLAGS_AUTOCLEAR);
if (loopfd < 0)
return -1;
DEBUG("prepared loop device \"%s\"", path);
ret = mount_unknown_fs(path, target, options);
close(loopfd);
DEBUG("mounted rootfs \"%s\" on loop device \"%s\" via loop device \"%s\"", rootfs, target, path);
return ret;
}
static int mount_rootfs_block(const char *rootfs, const char *target,
const char *options)
{
return mount_unknown_fs(rootfs, target, options);
}
/*
* pin_rootfs
* if rootfs is a directory, then open ${rootfs}/lxc.hold for writing for
......@@ -836,49 +788,6 @@ static int lxc_mount_auto_mounts(struct lxc_conf *conf, int flags, struct lxc_ha
return 0;
}
static int mount_rootfs(const char *rootfs, const char *target, const char *options)
{
char absrootfs[MAXPATHLEN];
struct stat s;
int i;
typedef int (*rootfs_cb)(const char *, const char *, const char *);
struct rootfs_type {
int type;
rootfs_cb cb;
} rtfs_type[] = {
{ S_IFDIR, mount_rootfs_dir },
{ S_IFBLK, mount_rootfs_block },
{ S_IFREG, lxc_mount_rootfs_file },
};
if (!realpath(rootfs, absrootfs)) {
SYSERROR("Failed to get real path for \"%s\".", rootfs);
return -1;
}
if (access(absrootfs, F_OK)) {
SYSERROR("The rootfs \"%s\" is not accessible.", absrootfs);
return -1;
}
if (stat(absrootfs, &s)) {
SYSERROR("Failed to stat the rootfs \"%s\".", absrootfs);
return -1;
}
for (i = 0; i < sizeof(rtfs_type)/sizeof(rtfs_type[0]); i++) {
if (!__S_ISTYPE(s.st_mode, rtfs_type[i].type))
continue;
return rtfs_type[i].cb(absrootfs, target, options);
}
ERROR("Unsupported rootfs type for rootfs \"%s\".", absrootfs);
return -1;
}
static int setup_utsname(struct utsname *utsname)
{
if (!utsname)
......@@ -1258,8 +1167,9 @@ static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
return 0;
}
static int setup_rootfs(struct lxc_conf *conf)
static int lxc_setup_rootfs(struct lxc_conf *conf)
{
int ret;
struct bdev *bdev;
const struct lxc_rootfs *rootfs;
......@@ -1278,18 +1188,17 @@ static int setup_rootfs(struct lxc_conf *conf)
return -1;
}
/* First try mounting rootfs using a bdev. */
bdev = bdev_init(conf, rootfs->path, rootfs->mount, rootfs->options);
if (bdev && !bdev->ops->mount(bdev)) {
bdev_put(bdev);
DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\".",
if (!bdev) {
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)");
return 0;
return -1;
}
if (bdev)
bdev_put(bdev);
if (mount_rootfs(rootfs->path, rootfs->mount, rootfs->options)) {
ret = bdev->ops->mount(bdev);
bdev_put(bdev);
if (ret < 0) {
ERROR("Failed to mount rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)");
......@@ -1299,6 +1208,7 @@ static int setup_rootfs(struct lxc_conf *conf)
DEBUG("Mounted rootfs \"%s\" onto \"%s\" with options \"%s\".",
rootfs->path, rootfs->mount,
rootfs->options ? rootfs->options : "(null)");
return 0;
}
......@@ -3418,7 +3328,14 @@ static int write_id_mapping(enum idtype idtype, pid_t pid, const char *buf,
return 0;
}
/* Check whether a binary exist and has either CAP_SETUID, CAP_SETGID or both. */
/* Check whether a binary exist and has either CAP_SETUID, CAP_SETGID or both.
*
* @return 1 if functional binary was found
* @return 0 if binary exists but is lacking privilege
* @return -ENOENT if binary does not exist
* @return -EINVAL if cap to check is neither CAP_SETUID nor CAP_SETGID
*
*/
static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
{
char *path;
......@@ -3426,6 +3343,9 @@ static int idmaptool_on_path_and_privileged(const char *binary, cap_value_t cap)
struct stat st;
int fret = 0;
if (cap != CAP_SETUID && cap != CAP_SETGID)
return -EINVAL;
path = on_path(binary, NULL);
if (!path)
return -ENOENT;
......@@ -3514,7 +3434,17 @@ int lxc_map_ids(struct lxc_list *idmap, pid_t pid)
* range by shadow.
*/
uidmap = idmaptool_on_path_and_privileged("newuidmap", CAP_SETUID);
if (uidmap == -ENOENT)
WARN("newuidmap binary is missing");
else if (!uidmap)
WARN("newuidmap is lacking necessary privileges");
gidmap = idmaptool_on_path_and_privileged("newgidmap", CAP_SETGID);
if (gidmap == -ENOENT)
WARN("newgidmap binary is missing");
else if (!gidmap)
WARN("newgidmap is lacking necessary privileges");
if (uidmap > 0 && gidmap > 0) {
DEBUG("Functional newuidmap and newgidmap binary found.");
use_shadow = true;
......@@ -3916,16 +3846,21 @@ int chown_mapped_root(char *path, struct lxc_conf *conf)
return ret;
}
int ttys_shift_ids(struct lxc_conf *c)
int lxc_ttys_shift_ids(struct lxc_conf *c)
{
if (lxc_list_empty(&c->id_map))
return 0;
if (strcmp(c->console.name, "") !=0 && chown_mapped_root(c->console.name, c) < 0) {
ERROR("Failed to chown %s", c->console.name);
if (!strcmp(c->console.name, ""))
return 0;
if (chown_mapped_root(c->console.name, c) < 0) {
ERROR("failed to chown console \"%s\"", c->console.name);
return -1;
}
TRACE("chowned console \"%s\"", c->console.name);
return 0;
}
......@@ -4059,7 +3994,7 @@ int do_rootfs_setup(struct lxc_conf *conf, const char *name, const char *lxcpath
return -1;
}
if (setup_rootfs(conf)) {
if (lxc_setup_rootfs(conf)) {
ERROR("failed to setup rootfs for '%s'", name);
return -1;
}
......@@ -4093,55 +4028,46 @@ static bool verify_start_hooks(struct lxc_conf *conf)
return true;
}
static int send_fd(int sock, int fd)
{
int ret = lxc_abstract_unix_send_fd(sock, fd, NULL, 0);
if (ret < 0) {
SYSERROR("Error sending tty fd to parent");
return -1;
}
return 0;
}
static int send_ttys_to_parent(struct lxc_handler *handler)
static int lxc_send_ttys_to_parent(struct lxc_handler *handler)
{
int i, ret;
int i;
int *ttyfds;
struct lxc_pty_info *pty_info;
struct lxc_conf *conf = handler->conf;
const struct lxc_tty_info *tty_info = &conf->tty_info;
int sock = handler->ttysock[0];
int ret = -1;
size_t num_ttyfds = (2 * conf->tty);
for (i = 0; i < tty_info->nbtty; i++) {
struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
ret = send_fd(sock, pty_info->slave);
if (ret >= 0)
send_fd(sock, pty_info->master);
TRACE("sending pty \"%s\" with master fd %d and slave fd %d to "
ttyfds = malloc(num_ttyfds * sizeof(int));
if (!ttyfds)
return -1;
for (i = 0; i < num_ttyfds; i++) {
pty_info = &tty_info->pty_info[i / 2];
ttyfds[i++] = pty_info->slave;
ttyfds[i] = pty_info->master;
TRACE("send pty \"%s\" with master fd %d and slave fd %d to "
"parent",
pty_info->name, pty_info->master, pty_info->slave);
close(pty_info->slave);
pty_info->slave = -1;
close(pty_info->master);
pty_info->master = -1;
if (ret < 0) {
ERROR("failed to send pty \"%s\" with master fd %d and "
"slave fd %d to parent : %s",
pty_info->name, pty_info->master, pty_info->slave,
strerror(errno));
goto bad;
}
}
ret = lxc_abstract_unix_send_fds(sock, ttyfds, num_ttyfds, NULL, 0);
if (ret < 0)
ERROR("failed to send %d ttys to parent: %s", conf->tty,
strerror(errno));
else
TRACE("sent %d ttys to parent", conf->tty);
close(handler->ttysock[0]);
close(handler->ttysock[1]);
return 0;
for (i = 0; i < num_ttyfds; i++)
close(ttyfds[i]);
bad:
ERROR("Error writing tty fd to parent");
return -1;
free(ttyfds);
return ret;
}
int lxc_setup(struct lxc_handler *handler)
......@@ -4260,7 +4186,7 @@ int lxc_setup(struct lxc_handler *handler)
return -1;
}
if (send_ttys_to_parent(handler) < 0) {
if (lxc_send_ttys_to_parent(handler) < 0) {
ERROR("failure sending console info to parent");
return -1;
}
......
......@@ -472,7 +472,7 @@ extern void lxc_restore_phys_nics_to_netns(int netnsfd, struct lxc_conf *conf);
extern int find_unmapped_nsid(struct lxc_conf *conf, enum idtype idtype);
extern int mapped_hostid(unsigned id, struct lxc_conf *conf, enum idtype idtype);
extern int chown_mapped_root(char *path, struct lxc_conf *conf);
extern int ttys_shift_ids(struct lxc_conf *c);
extern int lxc_ttys_shift_ids(struct lxc_conf *c);
extern int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,
const char *fn_name);
extern int parse_mntopts(const char *mntopts, unsigned long *mntflags,
......
......@@ -481,7 +481,7 @@ struct lxc_handler *lxc_init(const char *name, struct lxc_conf *conf, const char
goto out_restore_sigmask;
}
if (ttys_shift_ids(conf) < 0) {
if (lxc_ttys_shift_ids(conf) < 0) {
ERROR("Failed to shift tty into container.");
goto out_restore_sigmask;
}
......@@ -1008,23 +1008,16 @@ static int save_phys_nics(struct lxc_conf *conf)
return 0;
}
static int recv_fd(int sock, int *fd)
static int lxc_recv_ttys_from_child(struct lxc_handler *handler)
{
if (lxc_abstract_unix_recv_fd(sock, fd, NULL, 0) < 0) {
SYSERROR("Error receiving tty file descriptor from child process.");
return -1;
}
if (*fd == -1)
return -1;
return 0;
}
static int recv_ttys_from_child(struct lxc_handler *handler)
{
int i, ret;
int i;
int *ttyfds;
struct lxc_pty_info *pty_info;
int ret = -1;
int sock = handler->ttysock[1];
struct lxc_conf *conf = handler->conf;
struct lxc_tty_info *tty_info = &conf->tty_info;
size_t num_ttyfds = (2 * conf->tty);
if (!conf->tty)
return 0;
......@@ -1033,25 +1026,31 @@ static int recv_ttys_from_child(struct lxc_handler *handler)
if (!tty_info->pty_info)
return -1;
for (i = 0; i < conf->tty; i++) {
struct lxc_pty_info *pty_info = &tty_info->pty_info[i];
ttyfds = malloc(num_ttyfds * sizeof(int));
if (!ttyfds)
return -1;
ret = lxc_abstract_unix_recv_fds(sock, ttyfds, num_ttyfds, NULL, 0);
for (i = 0; (ret >= 0 && *ttyfds != -1) && (i < num_ttyfds); i++) {
pty_info = &tty_info->pty_info[i / 2];
pty_info->busy = 0;
ret = recv_fd(sock, &pty_info->slave);
if (ret >= 0)
recv_fd(sock, &pty_info->master);
if (ret < 0) {
ERROR("failed to receive pty with master fd %d and "
"slave fd %d from child: %s",
pty_info->master, pty_info->slave,
strerror(errno));
return -1;
}
TRACE("received pty with master fd %d and slave fd %d from child",
pty_info->master, pty_info->slave);
pty_info->slave = ttyfds[i++];
pty_info->master = ttyfds[i];
TRACE("received pty with master fd %d and slave fd %d from "
"parent", pty_info->master, pty_info->slave);
}
tty_info->nbtty = conf->tty;
return 0;
free(ttyfds);
if (ret < 0)
ERROR("failed to receive %d ttys from child: %s", conf->tty,
strerror(errno));
else
TRACE("received %d ttys from child", conf->tty);
return ret;
}
void resolve_clone_flags(struct lxc_handler *handler)
......@@ -1294,7 +1293,7 @@ static int lxc_spawn(struct lxc_handler *handler)
cgroups_connected = false;
/* Read tty fds allocated by child. */
if (recv_ttys_from_child(handler) < 0) {
if (lxc_recv_ttys_from_child(handler) < 0) {
ERROR("Failed to receive tty info from child process.");
goto out_delete_net;
}
......
......@@ -315,7 +315,7 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *
conf->console.descr = &descr;
/* Shift ttys to container. */
if (ttys_shift_ids(conf) < 0) {
if (lxc_ttys_shift_ids(conf) < 0) {
ERROR("Failed to shift tty into container");
goto err1;
}
......
......@@ -39,6 +39,11 @@
#include "initutils.h"
/* Define __S_ISTYPE if missing from the C library. */
#ifndef __S_ISTYPE
#define __S_ISTYPE(mode, mask) (((mode)&S_IFMT) == (mask))
#endif
/* Useful macros */
/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
#define LXC_NUMSTRLEN64 21
......
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