Merge pull request #4066 from brauner/2022-01-18.fixes.2

conf, lxccontainer, build: fixes
This commit is contained in:
Stéphane Graber 2022-01-20 08:43:50 -05:00 committed by GitHub
commit 55d6e49efe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 228 additions and 118 deletions

View File

@ -30,6 +30,14 @@ jobs:
run: | run: |
${CC} --version ${CC} --version
- name: Kernel version
run: |
uname -a
- name: Mount table
run: |
findmnt
- name: Build - name: Build
env: env:
CC: ${{ matrix.compiler }} CC: ${{ matrix.compiler }}

View File

@ -24,6 +24,20 @@ jobs:
sudo apt-get install -qq gcc clang sudo apt-get install -qq gcc clang
sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev libselinux1-dev linux-libc-dev docbook2x sudo apt-get install -qq libapparmor-dev libcap-dev libseccomp-dev libselinux1-dev linux-libc-dev docbook2x
- name: Compiler version
env:
CC: ${{ matrix.compiler }}
run: |
${CC} --version
- name: Kernel version
run: |
uname -a
- name: Mount table
run: |
findmnt
- name: Run coverity - name: Run coverity
run: | run: |
# Configure # Configure

View File

@ -18,9 +18,43 @@ apt-get install --yes --no-install-recommends \
libpam0g-dev libseccomp-dev libselinux1-dev libtool linux-libc-dev \ libpam0g-dev libseccomp-dev libselinux1-dev libtool linux-libc-dev \
llvm lsb-release make openssl pkg-config python3-all-dev \ llvm lsb-release make openssl pkg-config python3-all-dev \
python3-setuptools rsync squashfs-tools uidmap unzip uuid-runtime \ python3-setuptools rsync squashfs-tools uidmap unzip uuid-runtime \
wget xz-utils wget xz-utils systemd-coredump
apt-get remove --yes lxc-utils liblxc-common liblxc1 liblxc-dev
ARGS="--enable-sanitizers \
--prefix=/usr/ \
--disable-no-undefined \
--build=x86_64-linux-gnu \
--includedir=\${prefix}/include \
--mandir=\${prefix}/share/man \
--infodir=\${prefix}/share/info \
--sysconfdir=/etc \
--localstatedir=/var \
--disable-silent-rules \
--libdir=\${prefix}/lib/x86_64-linux-gnu \
--libexecdir=\${prefix}/lib/x86_64-linux-gnu \
--disable-maintainer-mode \
--disable-dependency-tracking \
--libdir=\${prefix}/lib/x86_64-linux-gnu \
--libexecdir=\${prefix}/lib/x86_64-linux-gnu \
--with-rootfs-path=\${prefix}/lib/x86_64-linux-gnu/lxc \
--enable-doc \
--disable-rpath \
--with-distro=ubuntu \
--enable-commands \
--enable-pam \
--enable-tests \
--enable-memfd-rexec \
--disable-static-binaries \
--enable-static \
--enable-silent-rules \
--enable-apparmor \
--enable-capabilities \
--enable-seccomp \
--enable-selinux \
--disable-liburing \
--enable-werror"
ARGS="--enable-sanitizers --enable-tests --prefix=/usr/ --sysconfdir=/etc/ --localstatedir=/var/ --disable-no-undefined"
case "$CC" in clang*) case "$CC" in clang*)
ARGS="$ARGS --enable-fuzzers" ARGS="$ARGS --enable-fuzzers"
esac esac

View File

@ -15,6 +15,20 @@ jobs:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Compiler version
env:
CC: ${{ matrix.compiler }}
run: |
${CC} --version
- name: Kernel version
run: |
uname -a
- name: Mount table
run: |
findmnt
- name: Build - name: Build
run: | run: |
sudo CC=${{ matrix.compiler }} CXX=${{ matrix.compiler }}++ .github/workflows/sanitizers.sh sudo CC=${{ matrix.compiler }} CXX=${{ matrix.compiler }}++ .github/workflows/sanitizers.sh

View File

@ -1,14 +0,0 @@
# See if we have working TLS. We only check to see if it compiles, and that
# the resulting program actually runs, not whether the resulting TLS variables
# work properly; that check is done at runtime, since we can run binaries
# compiled with __thread on systems without TLS.
AC_DEFUN([LXC_CHECK_TLS],
[
AC_MSG_CHECKING(for TLS)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([[ static __thread int val; int main() { return 0; } ]])],[have_tls=yes],[have_tls=no],[have_tls=no ])
AC_MSG_RESULT($have_tls)
if test "$have_tls" = "yes"; then
AC_DEFINE([HAVE_TLS],[1],[Define if the compiler supports __thread])
AC_DEFINE([thread_local],[__thread],[Define to the compiler TLS keyword])
fi
])

View File

@ -500,7 +500,9 @@ if test "x$enable_fuzzers" = "xyes"; then
CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[ \ CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[ \
-DRUN_ON_OSS_FUZZ=1]) -DRUN_ON_OSS_FUZZ=1])
fi fi
else fi
if test "x$enable_fuzzers" = "xno" -a "x$enable_sanitizers" = "xno"; then
CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[-flto=thin]) CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[-flto=thin])
fi fi
AC_SUBST(AM_CFLAGS) AC_SUBST(AM_CFLAGS)
@ -775,9 +777,6 @@ AC_CHECK_TYPES([struct rtnl_link_stats64], [], [], [[#include <linux/if_link.h>]
AX_PTHREAD AX_PTHREAD
AC_SEARCH_LIBS(clock_gettime, [rt]) AC_SEARCH_LIBS(clock_gettime, [rt])
# See if we support thread-local storage.
LXC_CHECK_TLS
# Hardening flags # Hardening flags
CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[ \ CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[ \
-fPIE \ -fPIE \

View File

@ -5,8 +5,14 @@
#include "config.h" #include "config.h"
#include <stdbool.h> #include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <linux/types.h> #include <linux/types.h>
#include <stdbool.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#ifndef thread_local #ifndef thread_local
#if __STDC_VERSION__ >= 201112L && \ #if __STDC_VERSION__ >= 201112L && \

View File

@ -5505,11 +5505,20 @@ int userns_exec_mapped_root(const char *path, int path_fd,
close_prot_errno_disarm(sock_fds[0]); close_prot_errno_disarm(sock_fds[0]);
if (!lxc_switch_uid_gid(0, 0)) if (!lxc_drop_groups() && errno != EPERM)
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
if (!lxc_drop_groups()) ret = setresgid(0, 0, 0);
if (ret < 0) {
SYSERROR("Failed to setresgid(0, 0, 0)");
_exit(EXIT_FAILURE); _exit(EXIT_FAILURE);
}
ret = setresuid(0, 0, 0);
if (ret < 0) {
SYSERROR("Failed to setresuid(0, 0, 0)");
_exit(EXIT_FAILURE);
}
ret = fchown(target_fd, 0, st.st_gid); ret = fchown(target_fd, 0, st.st_gid);
if (ret) { if (ret) {
@ -5557,9 +5566,12 @@ on_error:
/* Wait for child to finish. */ /* Wait for child to finish. */
if (pid < 0) if (pid < 0)
return log_error(-1, "Failed to create child process");
if (!wait_exited(pid))
return -1; return -1;
return wait_for_pid(pid); return 0;
} }
/* not thread-safe, do not use from api without first forking */ /* not thread-safe, do not use from api without first forking */

View File

@ -170,41 +170,32 @@ static int ongoing_create(struct lxc_container *c)
return LXC_CREATE_INCOMPLETE; return LXC_CREATE_INCOMPLETE;
} }
static int create_partial(struct lxc_container *c) static int create_partial(int fd_rootfs, struct lxc_container *c)
{ {
__do_free char *path = NULL; __do_close int fd_partial = -EBADF;
int fd, ret; int ret;
size_t len;
struct flock lk = {0}; struct flock lk = {0};
/* $lxcpath + '/' + $name + '/partial' + \0 */ fd_partial = openat(fd_rootfs, LXC_PARTIAL_FNAME, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
len = strlen(c->config_path) + 1 + strlen(c->name) + 1 + strlen(LXC_PARTIAL_FNAME) + 1; if (fd_partial < 0)
path = must_realloc(NULL, len); return syserror("errno(%d) - Failed to create \"%d/" LXC_PARTIAL_FNAME "\" to mark container as partially created", errno, fd_rootfs);
ret = strnprintf(path, len, "%s/%s/%s", c->config_path, c->name, LXC_PARTIAL_FNAME);
if (ret < 0)
return -1;
fd = open(path, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, 0000);
if (fd < 0)
return -1;
lk.l_type = F_WRLCK; lk.l_type = F_WRLCK;
lk.l_whence = SEEK_SET; lk.l_whence = SEEK_SET;
ret = fcntl(fd, F_OFD_SETLKW, &lk); ret = fcntl(fd_partial, F_OFD_SETLKW, &lk);
if (ret < 0) { if (ret < 0) {
if (errno == EINVAL) { if (errno == EINVAL) {
ret = flock(fd, LOCK_EX); ret = flock(fd_partial, LOCK_EX);
if (ret == 0) if (ret == 0)
return fd; return move_fd(fd_partial);
} }
SYSERROR("Failed to lock partial file %s", path); return syserror("Failed to lock partial file \"%d/" LXC_PARTIAL_FNAME"\"", fd_rootfs);
close(fd);
return -1;
} }
return fd; TRACE("Created \"%d/" LXC_PARTIAL_FNAME "\" to mark container as partially created", fd_rootfs);
return move_fd(fd_partial);
} }
static void remove_partial(struct lxc_container *c, int fd) static void remove_partial(struct lxc_container *c, int fd)
@ -452,7 +443,26 @@ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3) \
return ret; \ return ret; \
} }
#define WRAP_API_6(rettype, fnname, t1, t2, t3, t4, t5, t6) \ #define WRAP_API_5(rettype, fnname, t1, t2, t3, t4, t5) \
static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3, \
t4 a4, t5 a5) \
{ \
rettype ret; \
bool reset_config = false; \
\
if (!current_config && c && c->lxc_conf) { \
current_config = c->lxc_conf; \
reset_config = true; \
} \
\
ret = do_##fnname(c, a1, a2, a3, a4, a5); \
if (reset_config) \
current_config = NULL; \
\
return ret; \
}
#define WRAP_API_6(rettype, fnname, t1, t2, t3, t4, t5, t6) \
static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3, \ static rettype fnname(struct lxc_container *c, t1 a1, t2 a2, t3 a3, \
t4 a4, t5 a5, t6 a6) \ t4 a4, t5 a5, t6 a6) \
{ \ { \
@ -1203,32 +1213,31 @@ WRAP_API(bool, lxcapi_stop)
static int do_create_container_dir(const char *path, struct lxc_conf *conf) static int do_create_container_dir(const char *path, struct lxc_conf *conf)
{ {
int lasterr; __do_close int fd_rootfs = -EBADF;
int ret = -1; int ret = -1;
mode_t mask = umask(0002); mode_t mask = umask(0002);
ret = mkdir(path, 0770); ret = mkdir(path, 0770);
lasterr = errno;
umask(mask); umask(mask);
errno = lasterr; if (ret < 0 && errno != EEXIST)
if (ret) { return -errno;
if (errno != EEXIST)
return -1;
ret = 0; fd_rootfs = open_at(-EBADF, path, O_DIRECTORY | O_CLOEXEC, PROTECT_LOOKUP_ABSOLUTE_WITH_SYMLINKS, 0);
} if (fd_rootfs < 0)
return syserror("Failed to open container directory \"%d(%s)\"", fd_rootfs, path);
if (!list_empty(&conf->id_map)) { if (list_empty(&conf->id_map))
ret = chown_mapped_root(path, conf); return move_fd(fd_rootfs);
if (ret < 0)
ret = -1;
}
return ret; ret = userns_exec_mapped_root(NULL, fd_rootfs, conf);
if (ret < 0)
return syserror_ret(-1, "Failed to chown rootfs \"%s\"", path);
return move_fd(fd_rootfs);
} }
/* Create the standard expected container dir. */ /* Create the standard expected container dir. */
static bool create_container_dir(struct lxc_container *c) static int create_container_dir(struct lxc_container *c)
{ {
__do_free char *s = NULL; __do_free char *s = NULL;
int ret; int ret;
@ -1237,13 +1246,13 @@ static bool create_container_dir(struct lxc_container *c)
len = strlen(c->config_path) + strlen(c->name) + 2; len = strlen(c->config_path) + strlen(c->name) + 2;
s = malloc(len); s = malloc(len);
if (!s) if (!s)
return false; return ret_errno(ENOMEM);
ret = strnprintf(s, len, "%s/%s", c->config_path, c->name); ret = strnprintf(s, len, "%s/%s", c->config_path, c->name);
if (ret < 0) if (ret < 0)
return false; return -errno;
return do_create_container_dir(s, c->lxc_conf) == 0; return do_create_container_dir(s, c->lxc_conf);
} }
/* do_storage_create: thin wrapper around storage_create(). Like /* do_storage_create: thin wrapper around storage_create(). Like
@ -1769,15 +1778,16 @@ static void lxcapi_clear_config(struct lxc_container *c)
* @argv: the arguments to pass to the template, terminated by NULL. If no * @argv: the arguments to pass to the template, terminated by NULL. If no
* arguments, you can just pass NULL. * arguments, you can just pass NULL.
*/ */
static bool do_lxcapi_create(struct lxc_container *c, const char *t, static bool __lxcapi_create(struct lxc_container *c, const char *t,
const char *bdevtype, struct bdev_specs *specs, const char *bdevtype, struct bdev_specs *specs,
int flags, char *const argv[]) int flags, char *const argv[])
{ {
__do_close int fd_rootfs = -EBADF;
__do_free char *path_template = NULL; __do_free char *path_template = NULL;
int partial_fd; int partial_fd;
mode_t mask; mode_t mask;
pid_t pid; pid_t pid;
bool ret = false, rootfs_managed = true; bool bret = false, rootfs_managed = true;
if (!c) if (!c)
return false; return false;
@ -1785,7 +1795,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
if (t) { if (t) {
path_template = get_template_path(t); path_template = get_template_path(t);
if (!path_template) if (!path_template)
return syserror_set(ENOENT, "Template \"%s\" not found", t); return log_error(false, "Template \"%s\" not found", t);
} }
/* If a template is passed in, and the rootfs already is defined in the /* If a template is passed in, and the rootfs already is defined in the
@ -1794,15 +1804,17 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
*/ */
if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path && if (do_lxcapi_is_defined(c) && c->lxc_conf && c->lxc_conf->rootfs.path &&
access(c->lxc_conf->rootfs.path, F_OK) == 0 && path_template) access(c->lxc_conf->rootfs.path, F_OK) == 0 && path_template)
return syserror_set(EEXIST, "Container \"%s\" already exists in \"%s\"", c->name, c->config_path); return log_error(false, "Container \"%s\" already exists in \"%s\"",
c->name, c->config_path);
if (!c->lxc_conf && if (!c->lxc_conf &&
!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) !do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config")))
return syserror_set(EINVAL, "Failed to load default configuration file %s", return log_error(false, "Failed to load default configuration file %s",
lxc_global_config_value("lxc.default_config")); lxc_global_config_value("lxc.default_config"));
if (!create_container_dir(c)) fd_rootfs = create_container_dir(c);
return syserror_set(EINVAL, "Failed to create container %s", c->name); if (fd_rootfs < 0)
return log_error(false, "Failed to create container %s", c->name);
if (c->lxc_conf->rootfs.path) if (c->lxc_conf->rootfs.path)
rootfs_managed = false; rootfs_managed = false;
@ -1817,13 +1829,16 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
ERROR("Failed to save initial config for \"%s\"", c->name); ERROR("Failed to save initial config for \"%s\"", c->name);
goto out; goto out;
} }
ret = true;
bret = true;
goto out; goto out;
} }
/* Rootfs passed into configuration, but does not exist. */ /* Rootfs passed into configuration, but does not exist. */
if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) != 0) if (c->lxc_conf->rootfs.path && access(c->lxc_conf->rootfs.path, F_OK) != 0) {
ERROR("The rootfs \"%s\" does not exist", c->lxc_conf->rootfs.path);
goto out; goto out;
}
if (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !path_template) { if (do_lxcapi_is_defined(c) && c->lxc_conf->rootfs.path && !path_template) {
/* Rootfs already existed, user just wanted to save the loaded /* Rootfs already existed, user just wanted to save the loaded
@ -1832,14 +1847,16 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
if (!c->save_config(c, NULL)) if (!c->save_config(c, NULL))
ERROR("Failed to save initial config for \"%s\"", c->name); ERROR("Failed to save initial config for \"%s\"", c->name);
ret = true; bret = true;
goto out; goto out;
} }
/* Mark that this container is being created */ /* Mark that this container as being created */
partial_fd = create_partial(c); partial_fd = create_partial(fd_rootfs, c);
if (partial_fd < 0) if (partial_fd < 0) {
SYSERROR("Failed to mark container as being partially created");
goto out; goto out;
}
/* No need to get disk lock bc we have the partial lock. */ /* No need to get disk lock bc we have the partial lock. */
@ -1881,7 +1898,7 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
_exit(EXIT_SUCCESS); _exit(EXIT_SUCCESS);
} }
if (wait_for_pid(pid) != 0) if (!wait_exited(pid))
goto out_unlock; goto out_unlock;
/* Reload config to get the rootfs. */ /* Reload config to get the rootfs. */
@ -1906,14 +1923,14 @@ static bool do_lxcapi_create(struct lxc_container *c, const char *t,
} }
} }
ret = load_config_locked(c, c->configfile); bret = load_config_locked(c, c->configfile);
out_unlock: out_unlock:
umask(mask); umask(mask);
remove_partial(c, partial_fd); remove_partial(c, partial_fd);
out: out:
if (!ret) { if (!bret) {
bool reset_managed = c->lxc_conf->rootfs.managed; bool reset_managed = c->lxc_conf->rootfs.managed;
/* /*
@ -1926,22 +1943,19 @@ out:
c->lxc_conf->rootfs.managed = reset_managed; c->lxc_conf->rootfs.managed = reset_managed;
} }
return ret; return bret;
} }
static bool lxcapi_create(struct lxc_container *c, const char *t, static bool do_lxcapi_create(struct lxc_container *c, const char *t,
const char *bdevtype, struct bdev_specs *specs, const char *bdevtype, struct bdev_specs *specs,
int flags, char *const argv[]) int flags, char *const argv[])
{ {
bool ret; return __lxcapi_create(c, t, bdevtype, specs, flags, argv);
current_config = c ? c->lxc_conf : NULL;
ret = do_lxcapi_create(c, t, bdevtype, specs, flags, argv);
current_config = NULL;
return ret;
} }
WRAP_API_5(bool, lxcapi_create, const char *, const char *,
struct bdev_specs *, int, char *const *)
static bool do_lxcapi_reboot(struct lxc_container *c) static bool do_lxcapi_reboot(struct lxc_container *c)
{ {
__do_close int pidfd = -EBADF; __do_close int pidfd = -EBADF;
@ -2169,7 +2183,7 @@ static bool lxcapi_createl(struct lxc_container *c, const char *t,
goto out; goto out;
} }
bret = do_lxcapi_create(c, t, bdevtype, specs, flags, args); bret = __lxcapi_create(c, t, bdevtype, specs, flags, args);
out: out:
free(args); free(args);
@ -2605,28 +2619,27 @@ WRAP_API_3(int, lxcapi_get_keys, const char *, char *, int)
static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file) static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
{ {
int fd, lret; __do_close int fd_config = -EBADF, fd_rootfs = -EBADF;
bool ret = false, need_disklock = false; int lret = -1;
bool bret = false, need_disklock = false;
if (!alt_file) if (!alt_file)
alt_file = c->configfile; alt_file = c->configfile;
if (!alt_file) if (!alt_file)
return false; return log_error(false, "No config file found");
/* If we haven't yet loaded a config, load the stock config. */ /* If we haven't yet loaded a config, load the stock config. */
if (!c->lxc_conf) { if (!c->lxc_conf) {
if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) { if (!do_lxcapi_load_config(c, lxc_global_config_value("lxc.default_config"))) {
ERROR("Error loading default configuration file %s " return log_error(false, "Error loading default configuration file %s while saving %s",
"while saving %s", lxc_global_config_value("lxc.default_config"), c->name);
lxc_global_config_value("lxc.default_config"),
c->name);
return false;
} }
} }
if (!create_container_dir(c)) fd_rootfs = create_container_dir(c);
return false; if (fd_rootfs < 0)
return log_error(false, "Failed to create container directory");
/* If we're writing to the container's config file, take the disk lock. /* If we're writing to the container's config file, take the disk lock.
* Otherwise just take the memlock to protect the struct lxc_container * Otherwise just take the memlock to protect the struct lxc_container
@ -2640,19 +2653,23 @@ static bool do_lxcapi_save_config(struct lxc_container *c, const char *alt_file)
else else
lret = container_mem_lock(c); lret = container_mem_lock(c);
if (lret) if (lret)
return false; return log_error(false, "Failed to acquire lock");
fd = open(alt_file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, fd_config = open(alt_file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
if (fd < 0) if (fd_config < 0) {
SYSERROR("Failed to open config file \"%s\"", alt_file);
goto on_error; goto on_error;
}
lret = write_config(fd, c->lxc_conf); lret = write_config(fd_config, c->lxc_conf);
close(fd); if (lret < 0) {
if (lret < 0) SYSERROR("Failed to write config file \"%s\"", alt_file);
goto on_error; goto on_error;
}
ret = true; bret = true;
TRACE("Saved config file \"%s\"", alt_file);
on_error: on_error:
if (need_disklock) if (need_disklock)
@ -2660,7 +2677,7 @@ on_error:
else else
container_mem_unlock(c); container_mem_unlock(c);
return ret; return bret;
} }
WRAP_API_1(bool, lxcapi_save_config, const char *) WRAP_API_1(bool, lxcapi_save_config, const char *)
@ -3742,17 +3759,18 @@ only rootfs gets converted (copied/snapshotted) on clone.
static int create_file_dirname(char *path, struct lxc_conf *conf) static int create_file_dirname(char *path, struct lxc_conf *conf)
{ {
char *p = strrchr(path, '/'); __do_close int fd_rootfs = -EBADF;
int ret = -1; char *p;
p = strrchr(path, '/');
if (!p) if (!p)
return -1; return -1;
*p = '\0'; *p = '\0';
ret = do_create_container_dir(path, conf); fd_rootfs = do_create_container_dir(path, conf);
*p = '/'; *p = '/';
return ret; return fd_rootfs >= 0;
} }
static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char *newname, static struct lxc_container *do_lxcapi_clone(struct lxc_container *c, const char *newname,

View File

@ -329,6 +329,24 @@ again:
return status; return status;
} }
bool wait_exited(pid_t pid)
{
int status;
status = lxc_wait_for_pid_status(pid);
if (status < 0)
return log_error(false, "Failed to reap on child process %d", pid);
if (WIFSIGNALED(status))
return log_error(false, "Child process %d terminated by signal %d", pid, WTERMSIG(status));
if (!WIFEXITED(status))
return log_error(false, "Child did not termiate correctly");
if (WEXITSTATUS(status))
return log_error(false, "Child terminated with error %d", WEXITSTATUS(status));
TRACE("Reaped child process %d", pid);
return true;
}
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
#include <openssl/evp.h> #include <openssl/evp.h>

View File

@ -81,6 +81,7 @@ static inline void __auto_lxc_pclose__(struct lxc_popen_FILE **f)
__hidden extern int wait_for_pid(pid_t pid); __hidden extern int wait_for_pid(pid_t pid);
__hidden extern int lxc_wait_for_pid_status(pid_t pid); __hidden extern int lxc_wait_for_pid_status(pid_t pid);
__hidden extern int wait_for_pidfd(int pidfd); __hidden extern int wait_for_pidfd(int pidfd);
__hidden extern bool wait_exited(pid_t pid);
#if HAVE_OPENSSL #if HAVE_OPENSSL
__hidden extern int sha1sum_file(char *fnam, unsigned char *md_value, unsigned int *md_len); __hidden extern int sha1sum_file(char *fnam, unsigned char *md_value, unsigned int *md_len);