src/tests/lxc-test-config-jump-table
src/tests/lxc-test-parse-config-file
src/tests/lxc-test-shortlived
+src/tests/lxc-test-api-reboot
+src/tests/lxc-test-criu-check-feature
+src/tests/lxc-test-raw-clone
+src/tests/lxc-test-share-ns
+src/tests/lxc-test-state-server
config/compile
config/config.guess
<arg choice="opt">-R, --remount-sys-proc</arg>
<arg choice="opt">--keep-env</arg>
<arg choice="opt">--clear-env</arg>
- <arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
<arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
<arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
<arg choice="opt">-- <replaceable>command</replaceable></arg>
</listitem>
</varlistentry>
- <varlistentry>
- <term>
- <option>-L, --pty-log <replaceable>file</replaceable></option>
- </term>
- <listitem>
- <para>
- <!--
- Specify a file where the output of <command>lxc-attach</command> will be
- logged.
- -->
- <command>lxc-attach</command> の出力を記録するファイルを指定します。
- </para>
- <para>
- <!--
- <emphasis>Important:</emphasis> When a standard file descriptor
- does not refer to a pty output produced on it will not be logged.
- -->
- <emphasis>重要:</emphasis> 標準ファイルディスクリプタが pty を参照していない場合、それらに対する出力は記録されないでしょう。
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term>
<option>-v, --set-var <replaceable>variable</replaceable></option>
</varlistentry>
<varlistentry>
<term>
- <option>lxc.log</option>
+ <option>lxc.log.file</option>
</term>
<listitem>
<para>
p->pty_fd = -EBADF;
}
- if (p->init_ctx)
+ if (p->init_ctx) {
lxc_proc_put_context_info(p->init_ctx);
+ p->init_ctx = NULL;
+ }
}
static int attach_child_main(struct attach_clone_payload *payload)
pid_t attached_pid, init_pid, pid;
struct lxc_proc_context_info *init_ctx;
struct lxc_console pty;
+ struct lxc_conf *conf;
struct attach_clone_payload payload = {0};
ret = access("/proc/self/ns", X_OK);
return -ENOMEM;
}
}
+ conf = init_ctx->container->lxc_conf;
if (!fetch_seccomp(init_ctx->container, options))
WARN("Failed to get seccomp policy.");
}
if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
- ret = lxc_attach_pty(init_ctx->container->lxc_conf, &pty);
+ ret = lxc_attach_pty(conf, &pty);
if (ret < 0) {
ERROR("Failed to allocate pty");
free(cwd);
}
pty.log_fd = options->log_fd;
+ } else {
+ lxc_pty_init(&pty);
}
/* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
"cgroups", pid);
}
+ /* Setup /proc limits */
+ if (!lxc_list_empty(&conf->procs)) {
+ ret = setup_proc_filesystem(&conf->procs, pid);
+ if (ret < 0)
+ goto on_error;
+ }
+
/* Setup resource limits */
- if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits)) {
- ret = setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid);
+ if (!lxc_list_empty(&conf->limits)) {
+ ret = setup_resource_limits(&conf->limits, pid);
if (ret < 0)
goto on_error;
}
char *pathname;
struct stat mystat;
- if (!direntp)
- break;
-
if (!strcmp(direntp->d_name, ".") ||
!strcmp(direntp->d_name, ".."))
continue;
"The controller seems to be unused by \"cgfsng\" cgroup "
"driver or not enabled on the cgroup hierarchy",
controller);
+ errno = ENOENT;
return -1;
}
{
char path[MAXPATHLEN];
int ret, fd;
+ char *rootfs_path = rootfs->path ? rootfs->mount : "";
if (console->path && !strcmp(console->path, "none"))
return 0;
- ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
+ ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) {
- ERROR("failed to unmount \"%s\": %s", path, strerror(errno));
+ ERROR("Failed to unmount \"%s\": %s", path, strerror(errno));
return -ret;
} else {
- DEBUG("cleared all (%d) mounts from \"%s\"", ret, path);
- }
-
- ret = unlink(path);
- if (ret < 0) {
- SYSERROR("error unlinking %s", path);
- return -errno;
+ DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
}
}
fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
if (fd < 0) {
if (errno != EEXIST) {
- SYSERROR("failed to create console");
+ SYSERROR("Failed to create console");
return -errno;
}
} else {
close(fd);
}
- if (chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH)) {
- SYSERROR("failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name);
+ ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH);
+ if (ret < 0) {
+ SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name);
return -errno;
}
- if (safe_mount(console->name, path, "none", MS_BIND, 0, rootfs->mount) < 0) {
- ERROR("failed to mount '%s' on '%s'", console->name, path);
+ ret = safe_mount(console->name, path, "none", MS_BIND, 0, rootfs_path);
+ if (ret < 0) {
+ ERROR("Failed to mount '%s' on '%s'", console->name, path);
return -1;
}
- DEBUG("mounted pts device \"%s\" onto \"%s\"", console->name, path);
+ DEBUG("Mounted pts device \"%s\" onto \"%s\"", console->name, path);
return 0;
}
const struct lxc_console *console,
char *ttydir)
{
- int ret;
+ int ret, fd;
char path[MAXPATHLEN], lxcpath[MAXPATHLEN];
+ char *rootfs_path = rootfs->path ? rootfs->mount : "";
+
+ if (console->path && !strcmp(console->path, "none"))
+ return 0;
/* create rootfs/dev/<ttydir> directory */
- ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs->mount, ttydir);
+ ret = snprintf(path, sizeof(path), "%s/dev/%s", rootfs_path, ttydir);
if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
ret = mkdir(path, 0755);
if (ret && errno != EEXIST) {
- SYSERROR("failed with errno %d to create %s", errno, path);
+ SYSERROR("Failed with errno %d to create %s", errno, path);
return -errno;
}
DEBUG("Created directory for console and tty devices at \"%s\"", path);
- ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs->mount, ttydir);
+ ret = snprintf(lxcpath, sizeof(lxcpath), "%s/dev/%s/console", rootfs_path, ttydir);
if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
return -1;
ret = creat(lxcpath, 0660);
if (ret == -1 && errno != EEXIST) {
- SYSERROR("error %d creating %s", errno, lxcpath);
+ SYSERROR("Error %d creating %s", errno, lxcpath);
return -errno;
}
if (ret >= 0)
close(ret);
- ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs->mount);
- if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
+ ret = snprintf(path, sizeof(path), "%s/dev/console", rootfs_path);
+ if (ret < 0 || (size_t)ret >= sizeof(path))
return -1;
- /* When we are asked to setup a console we remove any previous
- * /dev/console bind-mounts.
- */
- if (console->path && !strcmp(console->path, "none")) {
- struct stat st;
- ret = stat(path, &st);
- if (ret < 0) {
- if (errno == ENOENT)
- return 0;
- SYSERROR("failed stat() \"%s\"", path);
- return -errno;
- }
-
- /* /dev/console must be character device with major number 5 and
- * minor number 1. If not, give benefit of the doubt and assume
- * the user has mounted something else right there on purpose.
- */
- if (((st.st_mode & S_IFMT) != S_IFCHR) || major(st.st_rdev) != 5 || minor(st.st_rdev) != 1)
- return 0;
-
- /* In case the user requested a bind-mount for /dev/console and
- * requests a ttydir we move the mount to the
- * /dev/<ttydir/console.
- * Note, we only move the uppermost mount and clear all other
- * mounts underneath for safety.
- * If it is a character device created via mknod() we simply
- * rename it.
- */
- ret = safe_mount(path, lxcpath, "none", MS_MOVE, NULL, rootfs->mount);
- if (ret < 0) {
- if (errno != EINVAL) {
- ERROR("failed to MS_MOVE \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno));
- return -errno;
- }
- /* path was not a mountpoint */
- ret = rename(path, lxcpath);
- if (ret < 0) {
- ERROR("failed to rename \"%s\" to \"%s\": %s", path, lxcpath, strerror(errno));
- return -errno;
- }
- DEBUG("renamed \"%s\" to \"%s\"", path, lxcpath);
- } else {
- DEBUG("moved mount \"%s\" to \"%s\"", path, lxcpath);
- }
-
- /* Clear all remaining bind-mounts. */
+ if (file_exists(path)) {
ret = lxc_unstack_mountpoint(path, false);
if (ret < 0) {
- ERROR("failed to unmount \"%s\": %s", path, strerror(errno));
+ ERROR("Failed to unmount \"%s\": %s", path, strerror(errno));
return -ret;
} else {
- DEBUG("cleared all (%d) mounts from \"%s\"", ret, path);
- }
- } else {
- if (file_exists(path)) {
- ret = lxc_unstack_mountpoint(path, false);
- if (ret < 0) {
- ERROR("failed to unmount \"%s\": %s", path, strerror(errno));
- return -ret;
- } else {
- DEBUG("cleared all (%d) mounts from \"%s\"", ret, path);
- }
+ DEBUG("Cleared all (%d) mounts from \"%s\"", ret, path);
}
+ }
- if (safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs->mount) < 0) {
- ERROR("failed to mount '%s' on '%s'", console->name, lxcpath);
- return -1;
+ fd = open(path, O_CREAT | O_EXCL, S_IXUSR | S_IXGRP | S_IXOTH);
+ if (fd < 0) {
+ if (errno != EEXIST) {
+ SYSERROR("Failed to create console");
+ return -errno;
}
- DEBUG("mounted \"%s\" onto \"%s\"", console->name, lxcpath);
+ } else {
+ close(fd);
}
- /* create symlink from rootfs /dev/console to '<ttydir>/console' */
- ret = snprintf(lxcpath, sizeof(lxcpath), "%s/console", ttydir);
- if (ret < 0 || (size_t)ret >= sizeof(lxcpath))
- return -1;
-
- ret = unlink(path);
- if (ret && errno != ENOENT) {
- SYSERROR("error unlinking %s", path);
+ ret = chmod(console->name, S_IXUSR | S_IXGRP | S_IXOTH);
+ if (ret < 0) {
+ SYSERROR("Failed to set mode '0%o' to '%s'", S_IXUSR | S_IXGRP | S_IXOTH, console->name);
return -errno;
}
- ret = symlink(lxcpath, path);
+ /* bind mount console->name to '/dev/<ttydir>/console' */
+ ret = safe_mount(console->name, lxcpath, "none", MS_BIND, 0, rootfs_path);
+ if (ret < 0) {
+ ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath);
+ return -1;
+ }
+ DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
+
+ /* bind mount '/dev/<ttydir>/console' to '/dev/console' */
+ ret = safe_mount(lxcpath, path, "none", MS_BIND, 0, rootfs_path);
if (ret < 0) {
- SYSERROR("failed to create symlink for console from \"%s\" to \"%s\"", lxcpath, path);
+ ERROR("Failed to mount '%s' on '%s'", console->name, lxcpath);
return -1;
}
+ DEBUG("Mounted \"%s\" onto \"%s\"", console->name, lxcpath);
+
+ DEBUG("Console has been setup under \"%s\" and mounted to \"%s\"", lxcpath, path);
- DEBUG("console has been setup under \"%s\" and symlinked to \"%s\"", lxcpath, path);
return 0;
}
static int lxc_setup_console(const struct lxc_rootfs *rootfs,
const struct lxc_console *console, char *ttydir)
{
- /* We don't have a rootfs, /dev/console will be shared. */
- if (!rootfs->path) {
- DEBUG("/dev/console will be shared with the host");
- return 0;
- }
if (!ttydir)
return lxc_setup_dev_console(rootfs, console);
return -1;
}
- buflen = sizeof("deny\n") - 1;
- errno = 0;
- ret = lxc_write_nointr(fd, "deny\n", buflen);
- if (ret != buflen) {
- SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid);
+ if (fd >= 0) {
+ buflen = sizeof("deny\n") - 1;
+ errno = 0;
+ ret = lxc_write_nointr(fd, "deny\n", buflen);
+ if (ret != buflen) {
+ SYSERROR("Failed to write \"deny\" to \"/proc/%d/setgroups\"", pid);
+ close(fd);
+ return -1;
+ }
close(fd);
- return -1;
}
- close(fd);
}
ret = snprintf(path, MAXPATHLEN, "/proc/%d/%cid_map", pid,
int ret;
struct lxc_console *console = &conf->console;
- if (!conf->rootfs.path) {
- INFO("Container does not have a rootfs. The console will be "
- "shared with the host");
- return 0;
- }
-
if (console->path && !strcmp(console->path, "none")) {
INFO("No console was requested");
return 0;
}
on_error:
- if (fd >= 0)
- close(fd);
free(line);
fclose(f);
}
static void remove_self(void)
{
- char path[PATH_MAX];
+ int ret;
ssize_t n;
+ char path[MAXPATHLEN] = {0};
n = readlink("/proc/self/exe", path, sizeof(path));
- if (n < 0) {
+ if (n < 0 || n >= MAXPATHLEN) {
SYSERROR("Failed to readlink \"/proc/self/exe\"");
return;
}
+ path[n] = '\0';
- path[n] = 0;
-
- if (umount2(path, MNT_DETACH) < 0) {
+ ret = umount2(path, MNT_DETACH);
+ if (ret < 0) {
SYSERROR("Failed to unmount \"%s\"", path);
return;
}
- if (unlink(path) < 0) {
+ ret = unlink(path);
+ if (ret < 0) {
SYSERROR("Failed to unlink \"%s\"", path);
return;
}
static bool do_destroy_container(struct lxc_conf *conf) {
int ret;
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = userns_exec_full(conf, storage_destroy_wrapper, conf,
"storage_destroy_wrapper");
if (ret < 0)
if (ret < 0 || (size_t)ret >= len)
goto out;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_1(conf, lxc_unlink_exec_wrapper, path,
"lxc_unlink_exec_wrapper");
else
ret = snprintf(path, len, "%s/%s", p1, c->name);
if (ret < 0 || (size_t)ret >= len)
goto out;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_full(conf, lxc_rmdir_onedev_wrapper, path,
"lxc_rmdir_onedev_wrapper");
else
}
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
if (chown_mapped_root(newpath, c->lxc_conf) < 0) {
ERROR("Error chowning %s to container root", newpath);
goto out;
data.c1 = c2;
data.flags = flags;
data.hookargs = hookargs;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_full(c->lxc_conf, clone_update_rootfs_wrapper,
&data, "clone_update_rootfs_wrapper");
else
static bool do_lxcapi_add_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
{
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
return false;
}
static bool do_lxcapi_remove_device_node(struct lxc_container *c, const char *src_path, const char *dest_path)
{
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
return false;
}
pid_t init_pid;
int ret = 0;
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
return false;
}
int ret;
pid_t pid, pid_outside;
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ERROR(NOT_SUPPORTED_ERROR, __FUNCTION__);
return false;
}
int fd;
size_t retry;
size_t len;
- int ret = -1;
int backoff_ms[] = {10, 50, 100};
if (lxc_monitor_sock_name(lxcpath, &addr) < 0)
fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
ERROR("Failed to create socket: %s.", strerror(errno));
- return -errno;
+ return -1;
}
len = strlen(&addr.sun_path[1]);
DEBUG("opening monitor socket %s with len %zu", &addr.sun_path[1], len);
if (len >= sizeof(addr.sun_path) - 1) {
errno = ENAMETOOLONG;
- ret = -errno;
ERROR("name of monitor socket too long (%zu bytes): %s", len, strerror(errno));
- goto on_error;
+ close(fd);
+ return -1;
}
for (retry = 0; retry < sizeof(backoff_ms) / sizeof(backoff_ms[0]); retry++) {
}
if (fd < 0) {
- ret = -errno;
ERROR("Failed to connect to monitor socket: %s.", strerror(errno));
- goto on_error;
+ close(fd);
+ return -1;
}
return fd;
-
-on_error:
- close(fd);
- return ret;
}
int lxc_monitor_read_fdset(struct pollfd *fds, nfds_t nfds, struct lxc_msg *msg,
return err;
}
-static int ip_forward_set(const char *ifname, int family, int flag)
-{
- int rc;
- char path[MAXPATHLEN];
-
- if (family != AF_INET && family != AF_INET6)
- return -EINVAL;
-
- rc = snprintf(path, MAXPATHLEN, "/proc/sys/net/%s/conf/%s/forwarding",
- family == AF_INET ? "ipv4" : "ipv6", ifname);
- if (rc < 0 || (size_t)rc >= MAXPATHLEN)
- return -E2BIG;
-
- return proc_sys_net_write(path, flag ? "1" : "0");
-}
-
-int lxc_ip_forward_on(const char *ifname, int family)
-{
- return ip_forward_set(ifname, family, 1);
-}
-
-int lxc_ip_forward_off(const char *ifname, int family)
-{
- return ip_forward_set(ifname, family, 0);
-}
-
static int neigh_proxy_set(const char *ifname, int family, int flag)
{
int ret;
char ifname[IFNAMSIZ];
struct lxc_list *iterator;
- if (am_unpriv())
+ if (am_host_unpriv())
return 0;
lxc_list_for_each(iterator, network) {
{
struct lxc_list *iterator;
- if (!am_unpriv())
+ if (!am_host_unpriv())
return 0;
lxc_list_for_each(iterator, network) {
extern int lxc_vlan_create(const char *master, const char *name,
unsigned short vid);
-/* Activate forwarding.*/
-extern int lxc_ip_forward_on(const char *name, int family);
-
-/* Disable forwarding. */
-extern int lxc_ip_forward_off(const char *name, int family);
-
/* Set ip address. */
extern int lxc_ipv6_addr_add(int ifindex, struct in6_addr *addr,
struct in6_addr *mcast,
static enum scmp_compare parse_v2_rule_op(char *s)
{
- enum scmp_compare ret;
-
if (strcmp(s, "SCMP_CMP_NE") == 0 || strcmp(s, "!=") == 0)
- ret = SCMP_CMP_NE;
+ return SCMP_CMP_NE;
else if (strcmp(s, "SCMP_CMP_LT") == 0 || strcmp(s, "<") == 0)
- ret = SCMP_CMP_LT;
+ return SCMP_CMP_LT;
else if (strcmp(s, "SCMP_CMP_LE") == 0 || strcmp(s, "<=") == 0)
- ret = SCMP_CMP_LE;
+ return SCMP_CMP_LE;
else if (strcmp(s, "SCMP_CMP_EQ") == 0 || strcmp(s, "==") == 0)
- ret = SCMP_CMP_EQ;
+ return SCMP_CMP_EQ;
else if (strcmp(s, "SCMP_CMP_GE") == 0 || strcmp(s, ">=") == 0)
- ret = SCMP_CMP_GE;
+ return SCMP_CMP_GE;
else if (strcmp(s, "SCMP_CMP_GT") == 0 || strcmp(s, ">") == 0)
- ret = SCMP_CMP_GT;
+ return SCMP_CMP_GT;
else if (strcmp(s, "SCMP_CMP_MASKED_EQ") == 0 || strcmp(s, "&=") == 0)
- ret = SCMP_CMP_MASKED_EQ;
- else
- ret = _SCMP_CMP_MAX;
+ return SCMP_CMP_MASKED_EQ;
- return ret;
+ return _SCMP_CMP_MAX;
}
/* This function is used to parse the args string into the structure.
int lxc_poll(const char *name, struct lxc_handler *handler)
{
int ret;
- bool has_console = (handler->conf->rootfs.path != NULL);
+ bool has_console = true;
struct lxc_epoll_descr descr, descr_console;
+ if (handler->conf->console.path && !strcmp(handler->conf->console.path, "none"))
+ has_console = false;
+
ret = lxc_mainloop_open(&descr);
if (ret < 0) {
ERROR("Failed to create mainloop");
close(descr.epfd);
descr.epfd = -EBADF;
if (ret < 0 || !handler->init_died)
- goto out_mainloop;
+ goto out_mainloop_console;
if (has_console)
ret = lxc_mainloop(&descr_console, 0);
-
-out_mainloop:
- lxc_mainloop_close(&descr);
- TRACE("Closed mainloop");
-
out_mainloop_console:
if (has_console) {
lxc_mainloop_close(&descr_console);
TRACE("Closed console mainloop");
}
+out_mainloop:
+ lxc_mainloop_close(&descr);
+ TRACE("Closed mainloop");
+
out_sigfd:
close(handler->sigfd);
TRACE("Closed signal file descriptor %d", handler->sigfd);
memset(handler, 0, sizeof(*handler));
- /* Note that am_unpriv() checks the effective uid. We probably don't
+ /* Note that am_host_unpriv() checks the effective uid. We probably don't
* care if we are real root only if we are running as root so this
* should be fine.
*/
- handler->am_root = !am_unpriv();
+ handler->am_root = !am_host_unpriv();
handler->data_sock[0] = handler->data_sock[1] = -1;
handler->conf = conf;
handler->lxcpath = lxcpath;
if (mkdir_p(new->dest, 0755) < 0)
return -1;
- if (am_unpriv() && chown_mapped_root(new->dest, conf) < 0)
+ if (am_host_unpriv() && chown_mapped_root(new->dest, conf) < 0)
WARN("Failed to update ownership of %s", new->dest);
if (strcmp(orig->type, "dir") == 0) {
free(delta);
return -1;
}
- if (am_unpriv() && chown_mapped_root(delta, conf) < 0)
+ if (am_host_unpriv() && chown_mapped_root(delta, conf) < 0)
WARN("Failed to update ownership of %s", delta);
// the src will be 'aufs:lowerdir:upperdir'
free(ndelta);
return -1;
}
- if (am_unpriv() && chown_mapped_root(ndelta, conf) < 0)
+ if (am_host_unpriv() && chown_mapped_root(ndelta, conf) < 0)
WARN("Failed to update ownership of %s", ndelta);
struct rsync_data_char rdata;
rdata.src = odelta;
rdata.dest = ndelta;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_full(conf, lxc_rsync_delta_wrapper,
&rdata, "lxc_rsync_delta_wrapper");
else
/* rsync the contents from source to target */
data.orig = orig;
data.new = new;
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = userns_exec_full(conf, lxc_storage_rsync_exec_wrapper,
&data, "lxc_storage_rsync_exec_wrapper");
if (ret < 0) {
if (ret < 0 && errno != ENOENT)
return false;
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
struct rsync_data_char args;
args.src = orig->src;
return -1;
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(new->dest, conf);
if (ret < 0)
WARN("Failed to update ownership of %s", new->dest);
return -1;
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(delta, conf);
if (ret < 0)
WARN("Failed to update ownership of %s", delta);
return -1;
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(work, conf);
if (ret < 0)
WARN("Failed to update ownership of %s", work);
return -1;
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(ndelta, conf);
if (ret < 0)
WARN("Failed to update ownership of %s",
return -1;
}
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(work, conf);
if (ret < 0)
WARN("Failed to update ownership of %s", work);
rdata.src = (char *)src;
rdata.dest = (char *)dest;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_full(conf, lxc_rsync_exec_wrapper, &rdata,
"lxc_rsync_exec_wrapper");
else
if (!bdevtype && !keepbdevtype && snap && !strcmp(orig->type, "dir"))
bdevtype = "overlay";
- if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
+ if (am_host_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
ERROR("Unsupported snapshot type \"%s\" for unprivileged users",
bdevtype ? bdevtype : "(null)");
goto on_error_put_orig;
else
src_no_prefix = lxc_storage_get_path(new->src, new->type);
- if (am_unpriv()) {
+ if (am_host_unpriv()) {
ret = chown_mapped_root(src_no_prefix, c->lxc_conf);
if (ret < 0)
WARN("Failed to chown \"%s\"", new->src);
/* rsync the contents from source to target */
data.orig = orig;
data.new = new;
- if (am_unpriv())
+ if (am_host_unpriv())
ret = userns_exec_full(c->lxc_conf,
lxc_storage_rsync_exec_wrapper, &data,
"lxc_storage_rsync_exec_wrapper");
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <lxc/lxccontainer.h>
-#include <sys/types.h>
-#include <sys/stat.h>
#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <lxc/lxccontainer.h>
+
+#include "arguments.h"
#include "caps.h"
-#include "lxc.h"
-#include "log.h"
#include "conf.h"
-#include "confile.h"
-#include "arguments.h"
#include "config.h"
+#include "confile.h"
+#include "log.h"
+#include "lxc.h"
#include "start.h"
#include "utils.h"
{
char *rundir;
const char *homedir;
+ struct stat sb;
+
+ if (stat(RUNTIME_PATH, &sb) < 0) {
+ return NULL;
+ }
- if (geteuid() == 0) {
+ if (geteuid() == sb.st_uid || getegid() == sb.st_gid) {
rundir = strdup(RUNTIME_PATH);
return rundir;
}
if (suffix_len > 0 && (end - 2) == dup && !isdigit(*(end - 2)))
return -EINVAL;
- if (suffix_len > 0 && isalpha(*(end - 2))) {
- if (suffix_len == 1)
- suffix_len++;
- else
- return -EINVAL;
- }
+ if (suffix_len > 0 && isalpha(*(end - 2)))
+ suffix_len++;
if (suffix_len > 0) {
memcpy(suffix, end - suffix_len, suffix_len);
/* initialize rand with urandom */
extern int randseed(bool);
-inline static bool am_unpriv(void) {
- return geteuid() != 0;
+inline static bool am_host_unpriv(void)
+{
+ FILE *f;
+ uid_t user, host, count;
+ int ret;
+
+ if (geteuid() != 0)
+ return true;
+
+ /* Now: are we in a user namespace? Because then we're also
+ * unprivileged.
+ */
+ f = fopen("/proc/self/uid_map", "r");
+ if (!f) {
+ return false;
+ }
+
+ ret = fscanf(f, "%u %u %u", &user, &host, &count);
+ fclose(f);
+ if (ret != 3) {
+ return false;
+ }
+
+ if (user != 0 || host != 0 || count != UINT32_MAX)
+ return true;
+ return false;
}
/*
isc-dhcp-client,\
netbase,\
net-tools,\
-iproute,\
+iproute2,\
openssh-server
cache=$1