#include "namespace.h"
#include "network.h"
#include "parse.h"
+#include "raw_syscalls.h"
#include "ringbuf.h"
#include "start.h"
#include "storage.h"
#include "storage/overlay.h"
+#include "syscall_wrappers.h"
#include "terminal.h"
#include "utils.h"
struct lxc_conf *current_config;
#endif
-/* Define pivot_root() if missing from the C library */
-#ifndef HAVE_PIVOT_ROOT
-static int pivot_root(const char *new_root, const char *put_old)
-{
-#ifdef __NR_pivot_root
- return syscall(__NR_pivot_root, new_root, put_old);
-#else
- errno = ENOSYS;
- return -1;
-#endif
-}
-#else
-extern int pivot_root(const char *new_root, const char *put_old);
-#endif
-
char *lxchook_names[NUM_LXC_HOOKS] = {
"pre-start",
"pre-mount",
int pin_rootfs(const char *rootfs)
{
int fd, ret;
- char absrootfspin[MAXPATHLEN];
+ char absrootfspin[PATH_MAX];
char *absrootfs;
struct stat s;
struct statfs sfs;
return -2;
}
- ret = snprintf(absrootfspin, MAXPATHLEN, "%s/.lxc-keep", absrootfs);
+ ret = snprintf(absrootfspin, PATH_MAX, "%s/.lxc-keep", absrootfs);
free(absrootfs);
- if (ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR | S_IRUSR);
static int add_shmount_to_list(struct lxc_conf *conf)
{
- char new_mount[MAXPATHLEN];
+ char new_mount[PATH_MAX];
/* Offset for the leading '/' since the path_cont
* is absolute inside the container.
*/
static int lxc_setup_dev_symlinks(const struct lxc_rootfs *rootfs)
{
int i, ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
struct stat s;
for (i = 0; i < sizeof(dev_symlinks) / sizeof(dev_symlinks[0]); i++) {
ret = snprintf(path, sizeof(path), "%s/dev/%s",
rootfs->path ? rootfs->mount : "", d->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
/* Stat the path first. If we don't get an error accept it as
int i, ret;
const struct lxc_tty_info *ttys = &conf->ttys;
char *ttydir = ttys->dir;
- char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
+ char path[PATH_MAX], lxcpath[PATH_MAX];
if (!conf->rootfs.path)
return 0;
static int lxc_fill_autodev(const struct lxc_rootfs *rootfs)
{
int i, ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
mode_t cmask;
int use_mknod = LXC_DEVNODE_MKNOD;
- ret = snprintf(path, MAXPATHLEN, "%s/dev",
+ ret = snprintf(path, PATH_MAX, "%s/dev",
rootfs->path ? rootfs->mount : "");
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
/* ignore, just don't try to fill in */
cmask = umask(S_IXUSR | S_IXGRP | S_IXOTH);
for (i = 0; i < sizeof(lxc_devices) / sizeof(lxc_devices[0]); i++) {
- char hostpath[MAXPATHLEN];
+ char hostpath[PATH_MAX];
const struct lxc_device_node *device = &lxc_devices[i];
- ret = snprintf(path, MAXPATHLEN, "%s/dev/%s",
+ ret = snprintf(path, PATH_MAX, "%s/dev/%s",
rootfs->path ? rootfs->mount : "", device->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
if (use_mknod >= LXC_DEVNODE_MKNOD) {
}
/* Fallback to bind-mounting the device from the host. */
- ret = snprintf(hostpath, MAXPATHLEN, "/dev/%s", device->name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(hostpath, PATH_MAX, "/dev/%s", device->name);
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
ret = safe_mount(hostpath, path, 0, MS_BIND, NULL,
return -1;
}
- /* The following code cleans up inhereted mounts which are not required
+ /* The following code cleans up inherited mounts which are not required
* for CT.
*
* The mountinfo file shows not all mounts, if a few points have been
*/
static int lxc_pivot_root(const char *rootfs)
{
- int newroot = -1, oldroot = -1, ret = -1;
+ int oldroot;
+ int newroot = -1, ret = -1;
- oldroot = open("/", O_DIRECTORY | O_RDONLY);
+ oldroot = open("/", O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (oldroot < 0) {
SYSERROR("Failed to open old root directory");
return -1;
}
- newroot = open(rootfs, O_DIRECTORY | O_RDONLY);
+ newroot = open(rootfs, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
if (newroot < 0) {
SYSERROR("Failed to open new root directory");
goto on_error;
TRACE("pivot_root(\"%s\") successful", rootfs);
on_error:
- if (oldroot != -1)
- close(oldroot);
- if (newroot != -1)
+ close(oldroot);
+
+ if (newroot >= 0)
close(newroot);
return ret;
const struct lxc_terminal *console)
{
int ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
char *rootfs_path = rootfs->path ? rootfs->mount : "";
if (console->path && !strcmp(console->path, "none"))
char *ttydir)
{
int ret;
- char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
+ char path[PATH_MAX], lxcpath[PATH_MAX];
char *rootfs_path = rootfs->path ? rootfs->mount : "";
if (console->path && !strcmp(console->path, "none"))
bool dev, bool relative, const char *rootfs)
{
int ret;
- char srcbuf[MAXPATHLEN];
+ char srcbuf[PATH_MAX];
const char *srcpath = fsname;
#ifdef HAVE_STATVFS
struct statvfs sb;
#endif
if (relative) {
- ret = snprintf(srcbuf, MAXPATHLEN, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
- if (ret < 0 || ret >= MAXPATHLEN) {
+ ret = snprintf(srcbuf, PATH_MAX, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
+ if (ret < 0 || ret >= PATH_MAX) {
ERROR("source path is too long");
return -1;
}
static inline int mount_entry_on_systemfs(struct mntent *mntent)
{
int ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
/* For containers created without a rootfs all mounts are treated as
* absolute paths starting at / on the host.
int offset;
char *aux;
const char *lxcpath;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
int ret = 0;
lxcpath = lxc_global_config_value("lxc.lxcpath");
/* If rootfs->path is a blockdev path, allow container fstab to use
* <lxcpath>/<name>/rootfs" as the target prefix.
*/
- ret = snprintf(path, MAXPATHLEN, "%s/%s/rootfs", lxcpath, lxc_name);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, PATH_MAX, "%s/%s/rootfs", lxcpath, lxc_name);
+ if (ret < 0 || ret >= PATH_MAX)
goto skipvarlib;
aux = strstr(mntent->mnt_dir, path);
offset = strlen(rootfs->path);
skipabs:
- ret = snprintf(path, MAXPATHLEN, "%s/%s", rootfs->mount, aux + offset);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, PATH_MAX, "%s/%s", rootfs->mount, aux + offset);
+ if (ret < 0 || ret >= PATH_MAX)
return -1;
return mount_entry_on_generic(mntent, path, rootfs, lxc_name, lxc_path);
const char *lxc_path)
{
int ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
/* relative to root mount point */
ret = snprintf(path, sizeof(path), "%s/%s", rootfs->mount, mntent->mnt_dir);
TRACE("Created temporary mount file");
}
- if (fd < 0) {
- SYSERROR("Could not create temporary mount file");
- return NULL;
- }
lxc_list_for_each (iterator, mount) {
size_t len;
SYSERROR("Failed to set limit %s", lim->resource);
return -1;
}
+
+ TRACE("Setup \"%s\" limit", lim->resource);
#else
- ERROR("Cannot set limit %s as prlimit is missing", lim->resource);
+ ERROR("Cannot set limit \"%s\" as prlimit is missing", lim->resource);
return -1;
#endif
}
struct lxc_sysctl *elem;
int ret = 0;
char *tmp = NULL;
- char filename[MAXPATHLEN] = {0};
+ char filename[PATH_MAX] = {0};
lxc_list_for_each (it, sysctls) {
elem = it->elem;
struct lxc_proc *elem;
int ret = 0;
char *tmp = NULL;
- char filename[MAXPATHLEN] = {0};
+ char filename[PATH_MAX] = {0};
lxc_list_for_each (it, procs) {
elem = it->elem;
size_t buf_size)
{
int fd, ret;
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
if (geteuid() != 0 && idtype == ID_TYPE_GID) {
size_t buflen;
- ret = snprintf(path, MAXPATHLEN, "/proc/%d/setgroups", pid);
- if (ret < 0 || ret >= MAXPATHLEN)
+ ret = snprintf(path, PATH_MAX, "/proc/%d/setgroups", pid);
+ if (ret < 0 || ret >= PATH_MAX)
return -E2BIG;
fd = open(path, O_WRONLY);
}
}
- ret = snprintf(path, MAXPATHLEN, "/proc/%d/%cid_map", pid,
+ ret = snprintf(path, PATH_MAX, "/proc/%d/%cid_map", pid,
idtype == ID_TYPE_UID ? 'u' : 'g');
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return -E2BIG;
fd = open(path, O_WRONLY);
* of the doubt. Otherwise we might fail even though all the necessary
* file capabilities are set.
*/
- DEBUG("Cannot check for file capabilites as full capability support is "
+ DEBUG("Cannot check for file capabilities as full capability support is "
"missing. Manual intervention needed");
fret = 1;
#endif
int fill, left;
char u_or_g;
char *pos;
- char cmd_output[MAXPATHLEN];
+ char cmd_output[PATH_MAX];
struct id_map *map;
struct lxc_list *iterator;
enum idtype type;
if (!had_entry)
continue;
- /* Try to catch the ouput of new{g,u}idmap to make debugging
+ /* Try to catch the output of new{g,u}idmap to make debugging
* easier.
*/
if (use_shadow) {
"-m", map5,
"--", "chown", ugid, path,
NULL};
- char cmd_output[MAXPATHLEN];
+ char cmd_output[PATH_MAX];
hostuid = geteuid();
hostgid = getegid();
}
}
-#define __LXC_SENDFILE_MAX 0x7ffff000 /* maximum number of bytes sendfile can handle */
again:
- copied = sendfile(memfd, mntinfo_fd, NULL, __LXC_SENDFILE_MAX);
+ copied = lxc_sendfile_nointr(memfd, mntinfo_fd, NULL, LXC_SENDFILE_MAX);
if (copied < 0) {
if (errno == EINTR)
goto again;
static bool verify_start_hooks(struct lxc_conf *conf)
{
- char path[MAXPATHLEN];
+ char path[PATH_MAX];
struct lxc_list *it;
lxc_list_for_each (it, &conf->hooks[LXCHOOK_START]) {
int ret;
- struct stat st;
char *hookname = it->elem;
- ret = snprintf(path, MAXPATHLEN, "%s%s",
+ ret = snprintf(path, PATH_MAX, "%s%s",
conf->rootfs.path ? conf->rootfs.mount : "",
hookname);
- if (ret < 0 || ret >= MAXPATHLEN)
+ if (ret < 0 || ret >= PATH_MAX)
return false;
- ret = stat(path, &st);
+ ret = access(path, X_OK);
if (ret < 0) {
- SYSERROR("Start hook %s not found in container",
+ SYSERROR("Start hook \"%s\" not found in container",
hookname);
return false;
}
static bool execveat_supported(void)
{
-#ifdef __NR_execveat
- /*
- * We use the syscall here, because it was introduced in kernel 3.19,
- * while glibc got support for using the syscall much later, in 2.27.
- * We don't want to use glibc because it falls back to /proc, and the
- * container may not have /proc mounted depending on its configuration.
- */
- syscall(__NR_execveat, -1, "", NULL, NULL, AT_EMPTY_PATH);
+ lxc_raw_execveat(-1, "", NULL, NULL, AT_EMPTY_PATH);
if (errno == ENOSYS)
return false;
return true;
-#else
- return false;
-#endif
}
int lxc_setup(struct lxc_handler *handler)
}
}
+ ret = lxc_setup_keyring();
+ if (ret < 0)
+ return -1;
+
ret = lxc_setup_network_in_child_namespaces(lxc_conf, &lxc_conf->network);
if (ret < 0) {
ERROR("Failed to setup network");
return -1;
}
- /* Make sure any start hooks are in the container */
- if (!verify_start_hooks(lxc_conf))
- return -1;
-
if (lxc_conf->is_execute) {
if (execveat_supported()) {
int fd;
}
}
+ /* Make sure any start hooks are in the container */
+ if (!verify_start_hooks(lxc_conf)) {
+ ERROR("Failed to verify start hooks");
+ return -1;
+ }
+
ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
lxc_conf->ttys.dir);
if (ret < 0) {
* - the container root {g,u}id as seen from the host > user's host {g,u}id
* - the container root -> some sub{g,u}id
* The former we add, if the user did not specifiy a mapping. The latter we
- * retrieve from the ontainer's configured {g,u}id mappings as it must have been
+ * retrieve from the container's configured {g,u}id mappings as it must have been
* there to start the container in the first place.
*/
int userns_exec_1(struct lxc_conf *conf, int (*fn)(void *), void *data,