mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-07 11:00:20 +00:00
Merge pull request #4066 from brauner/2022-01-18.fixes.2
conf, lxccontainer, build: fixes
This commit is contained in:
commit
55d6e49efe
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@ -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 }}
|
||||||
|
14
.github/workflows/coverity.yml
vendored
14
.github/workflows/coverity.yml
vendored
@ -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
|
||||||
|
38
.github/workflows/sanitizers.sh
vendored
38
.github/workflows/sanitizers.sh
vendored
@ -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
|
||||||
|
14
.github/workflows/sanitizers.yml
vendored
14
.github/workflows/sanitizers.yml
vendored
@ -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
|
||||||
|
@ -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
|
|
||||||
])
|
|
@ -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 \
|
||||||
|
@ -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 && \
|
||||||
|
@ -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 */
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user