Unverified Commit 15090139 by Serge Hallyn Committed by GitHub

Merge pull request #2042 from brauner/2017-12-15/bugfixes

start: tweaks + bugfixes
parents da5f5e3f c3184275
......@@ -290,7 +290,7 @@ lxc_create_SOURCES = tools/lxc_create.c tools/arguments.c
lxc_snapshot_SOURCES = tools/lxc_snapshot.c tools/arguments.c
lxc_usernsexec_SOURCES = tools/lxc_usernsexec.c tools/arguments.c
lxc_checkpoint_SOURCES = tools/lxc_checkpoint.c tools/arguments.c
lxc_user_nic_SOURCES = lxc_user_nic.c network.c network.h tools/arguments.c
lxc_user_nic_SOURCES = lxc_user_nic.c namespace.c network.c tools/arguments.c
lxc_monitord_SOURCES = lxc_monitord.c tools/arguments.c
if ENABLE_DEPRECATED
......@@ -304,7 +304,7 @@ endif
if HAVE_STATIC_LIBCAP
sbin_PROGRAMS += init.lxc.static
init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c parse.c
init_lxc_static_SOURCES = lxc_init.c error.c log.c initutils.c caps.c parse.c namespace.c
if !HAVE_GETLINE
if HAVE_FGETLN
......
......@@ -34,6 +34,7 @@
#include <sys/un.h>
#include "log.h"
#include "utils.h"
lxc_log_define(lxc_af_unix, lxc);
......@@ -217,7 +218,7 @@ int lxc_abstract_unix_send_credential(int fd, void *data, size_t size)
struct iovec iov;
struct cmsghdr *cmsg;
struct ucred cred = {
.pid = getpid(), .uid = getuid(), .gid = getgid(),
.pid = lxc_raw_getpid(), .uid = getuid(), .gid = getgid(),
};
char cmsgbuf[CMSG_SPACE(sizeof(cred))] = {0};
char buf[1] = {0};
......
......@@ -1121,7 +1121,7 @@ int lxc_attach(const char *name, const char *lxcpath,
}
}
pid = syscall(SYS_getpid);
pid = lxc_raw_getpid();
for (i = 0; i < LXC_NS_MAX; i++) {
int j, saved_errno;
......
......@@ -764,7 +764,7 @@ static struct cgroup_process_info *lxc_cgroup_process_info_get_self(struct cgrou
struct cgroup_process_info *i;
i = lxc_cgroup_process_info_getx("/proc/self/cgroup", meta);
if (!i)
i = lxc_cgroup_process_info_get(getpid(), meta);
i = lxc_cgroup_process_info_get(lxc_raw_getpid(), meta);
return i;
}
......@@ -2480,7 +2480,7 @@ static bool cgfs_escape(void *hdata)
if (!f)
goto out;
written = fprintf(f, "%d\n", getpid());
written = fprintf(f, "%d\n", lxc_raw_getpid());
fclose(f);
if (written < 0) {
SYSERROR("writing tasks failed\n");
......
......@@ -44,6 +44,7 @@
#include "error.h"
#include "commands.h"
#include "list.h"
#include "namespace.h"
#include "conf.h"
#include "utils.h"
#include "log.h"
......@@ -303,7 +304,7 @@ static bool lxc_cgmanager_create(const char *controller, const char *cgroup_path
static bool cgm_escape(void *hdata)
{
bool ret = true, cgm_needs_disconnect = false;
pid_t me = getpid();
pid_t me = lxc_raw_getpid();
char **slist = subsystems;
int i;
......@@ -359,6 +360,7 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
uid_t newuid)
{
int sv[2] = {-1, -1}, optval = 1, ret = -1;
pid_t pid_self;
char buf[1];
struct pollfd fds;
......@@ -395,7 +397,9 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
ERROR("Error getting reply from server over socketpair");
goto out;
}
if (send_creds(sv[0], getpid(), getuid(), getgid())) {
pid_self = lxc_raw_getpid();
if (send_creds(sv[0], pid_self, getuid(), getgid())) {
SYSERROR("Error sending pid over SCM_CREDENTIAL");
goto out;
}
......@@ -410,7 +414,7 @@ static int do_chown_cgroup(const char *controller, const char *cgroup_path,
ERROR("Error getting reply from server over socketpair");
goto out;
}
if (send_creds(sv[0], getpid(), newuid, 0)) {
if (send_creds(sv[0], pid_self, newuid, 0)) {
SYSERROR("Error sending pid over SCM_CREDENTIAL");
goto out;
}
......@@ -898,7 +902,7 @@ static void do_cgm_get(const char *name, const char *lxcpath, const char *filena
exit(1);
}
*cglast = '\0';
if (!lxc_cgmanager_enter(getpid(), controller, cgroup, abs_cgroup_supported())) {
if (!lxc_cgmanager_enter(lxc_raw_getpid(), controller, cgroup, abs_cgroup_supported())) {
WARN("Failed to enter container cgroup %s:%s", controller, cgroup);
ret = write(outp, &len, sizeof(len));
if (ret != sizeof(len))
......@@ -1038,7 +1042,7 @@ static void do_cgm_set(const char *name, const char *lxcpath, const char *filena
exit(1);
}
*cglast = '\0';
if (!lxc_cgmanager_enter(getpid(), controller, cgroup, abs_cgroup_supported())) {
if (!lxc_cgmanager_enter(lxc_raw_getpid(), controller, cgroup, abs_cgroup_supported())) {
ERROR("Failed to enter container cgroup %s:%s", controller, cgroup);
ret = write(outp, &retval, sizeof(retval));
if (ret != sizeof(retval))
......@@ -1278,7 +1282,7 @@ static bool verify_final_subsystems(const char *cgroup_use)
}
cgroup_pattern = lxc_global_config_value("lxc.cgroup.pattern");
i = snprintf(tmpnam, 50, "lxcprobe-%d", getpid());
i = snprintf(tmpnam, 50, "lxcprobe-%d", lxc_raw_getpid());
if (i < 0 || i >= 50) {
ERROR("Attack - format string modified?");
return false;
......
......@@ -414,7 +414,7 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd)
console->peerpty.busy = sockfd;
lxc_console_mainloop_add_peer(console);
DEBUG("%d %s peermaster:%d sockfd:%d", getpid(), __FUNCTION__, console->peerpty.master, sockfd);
DEBUG("%d %s peermaster:%d sockfd:%d", lxc_raw_getpid(), __FUNCTION__, console->peerpty.master, sockfd);
return 0;
err1:
......
......@@ -135,7 +135,7 @@ again:
*/
static bool apparmor_am_unconfined(void)
{
char *p = apparmor_process_label_get(getpid());
char *p = apparmor_process_label_get(lxc_raw_getpid());
bool ret = false;
if (!p || strcmp(p, "unconfined") == 0)
ret = true;
......@@ -186,7 +186,7 @@ static int apparmor_process_label_set(const char *inlabel, struct lxc_conf *conf
return 0;
}
curlabel = apparmor_process_label_get(getpid());
curlabel = apparmor_process_label_get(lxc_raw_getpid());
if (!aa_stacking_supported() && aa_needs_transition(curlabel)) {
/* we're already confined, and stacking isn't supported */
......
......@@ -40,12 +40,13 @@
#include "error.h"
#include "initutils.h"
#include "log.h"
#include "namespace.h"
#include "parse.h"
#include "version.h"
/* option keys for long only options */
#define OPT_USAGE 0x1000
#define OPT_VERSION OPT_USAGE - 1
#define OPT_VERSION OPT_USAGE - 1
#define QUOTE(macro) #macro
#define QUOTEVAL(macro) QUOTE(macro)
......@@ -61,14 +62,14 @@ static void interrupt_handler(int sig)
}
static struct option long_options[] = {
{ "name", required_argument, 0, 'n' },
{ "help", no_argument, 0, 'h' },
{ "usage", no_argument, 0, OPT_USAGE },
{ "version", no_argument, 0, OPT_VERSION },
{ "quiet", no_argument, 0, 'q' },
{ "logfile", required_argument, 0, 'o' },
{ "logpriority", required_argument, 0, 'l' },
{ "lxcpath", required_argument, 0, 'P' },
{ "name", required_argument, 0, 'n' },
{ "help", no_argument, 0, 'h' },
{ "usage", no_argument, 0, OPT_USAGE },
{ "version", no_argument, 0, OPT_VERSION },
{ "quiet", no_argument, 0, 'q' },
{ "logfile", required_argument, 0, 'o' },
{ "logpriority", required_argument, 0, 'l' },
{ "lxcpath", required_argument, 0, 'P' },
{ 0, 0, 0, 0 }
};
static char short_options[] = "n:hqo:l:P:";
......@@ -359,7 +360,7 @@ int main(int argc, char *argv[])
case SIGPWR:
case SIGTERM:
if (!shutdown) {
pid_t mypid = getpid();
pid_t mypid = lxc_raw_getpid();
shutdown = 1;
prevent_forking();
......@@ -375,7 +376,7 @@ int main(int argc, char *argv[])
}
break;
case SIGALRM: {
pid_t mypid = getpid();
pid_t mypid = lxc_raw_getpid();
prevent_forking();
if (mypid != 1) {
......
......@@ -427,7 +427,7 @@ int main(int argc, char *argv[])
}
NOTICE("lxc-monitord with pid %d is now monitoring lxcpath %s.",
getpid(), mon.lxcpath);
lxc_raw_getpid(), mon.lxcpath);
for (;;) {
ret = lxc_mainloop(&mon.descr, 1000 * 30);
if (ret) {
......
......@@ -46,6 +46,7 @@
#include <sys/types.h>
#include "config.h"
#include "namespace.h"
#include "network.h"
#include "utils.h"
......@@ -814,14 +815,16 @@ static char *lxc_secure_rename_in_ns(int pid, char *oldname, char *newname,
int *container_veth_ifidx)
{
int ret;
pid_t pid_self;
uid_t ruid, suid, euid;
char ifname[IFNAMSIZ];
char *string_ret = NULL, *name = NULL;
int fd = -1, ifindex = -1, ofd = -1;
ofd = lxc_preserve_ns(getpid(), "net");
pid_self = lxc_raw_getpid();
ofd = lxc_preserve_ns(pid_self, "net");
if (ofd < 0) {
usernic_error("Failed opening network namespace path for %d", getpid());
usernic_error("Failed opening network namespace path for %d", pid_self);
return NULL;
}
......@@ -993,13 +996,15 @@ struct user_nic_args {
static bool is_privileged_over_netns(int netns_fd)
{
int ret;
pid_t pid_self;
uid_t euid, ruid, suid;
bool bret = false;
int ofd = -1;
ofd = lxc_preserve_ns(getpid(), "net");
pid_self = lxc_raw_getpid();
ofd = lxc_preserve_ns(pid_self, "net");
if (ofd < 0) {
usernic_error("Failed opening network namespace path for %d", getpid());
usernic_error("Failed opening network namespace path for %d", pid_self);
return false;
}
......
......@@ -941,7 +941,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
/* become session leader */
ret = setsid();
if (ret < 0)
TRACE("Process %d is already process group leader", getpid());
TRACE("Process %d is already process group leader", lxc_raw_getpid());
} else {
if (!am_single_threaded()) {
ERROR("Cannot start non-daemonized container when threaded");
......@@ -966,7 +966,7 @@ static bool do_lxcapi_start(struct lxc_container *c, int useinit, char * const a
return false;
}
if (fprintf(pid_fp, "%d\n", getpid()) < 0) {
if (fprintf(pid_fp, "%d\n", lxc_raw_getpid()) < 0) {
SYSERROR("Failed to write '%s'", c->pidfile);
fclose(pid_fp);
pid_fp = NULL;
......@@ -4451,7 +4451,7 @@ static bool do_lxcapi_detach_interface(struct lxc_container *c,
return false;
}
pid_outside = getpid();
pid_outside = lxc_raw_getpid();
pid = fork();
if (pid < 0) {
ERROR("Failed to fork");
......
......@@ -127,6 +127,23 @@ pid_t lxc_raw_clone(unsigned long flags)
#endif
}
pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args, unsigned long flags)
{
pid_t pid;
pid = lxc_raw_clone(flags);
if (pid < 0)
return -1;
/* exit() is not thread-safe and might mess with the parent's signal
* handlers and other stuff when exec() fails.
*/
if (pid == 0)
_exit(fn(args));
return pid;
}
/* Leave the user namespace at the first position in the array of structs so
* that we always attach to it first when iterating over the struct and using
* setns() to switch namespaces. This especially affects lxc_attach(): Suppose
......
......@@ -23,8 +23,9 @@
#ifndef __LXC_NAMESPACE_H
#define __LXC_NAMESPACE_H
#include <sys/syscall.h>
#include <sched.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "config.h"
......@@ -112,11 +113,83 @@ int clone(int (*fn)(void *), void *child_stack,
/* pid_t *ptid, struct user_desc *tls, pid_t *ctid */ );
#endif
/**
* lxc_clone() - create a new process
*
* - allocate stack:
* This function allocates a new stack the size of page and passes it to the
* kernel.
*
* - support all CLONE_*flags:
* This function supports all CLONE_* flags. If in doubt or not sufficiently
* familiar with process creation in the kernel and interactions with libcs
* this function should be used.
*
* - pthread_atfork() handlers depending on libc:
* Whether this function runs pthread_atfork() handlers depends on the
* corresponding libc wrapper. glibc currently does not run pthread_atfork()
* handlers but does not guarantee that they are not. Other libcs might or
* might not run pthread_atfork() handlers. If you require guarantees please
* refer to the lxc_raw_clone*() functions below.
*
* - should call lxc_raw_getpid():
* The child should use lxc_raw_getpid() to retrieve its pid.
*/
extern pid_t lxc_clone(int (*fn)(void *), void *arg, int flags);
/**
* lxc_raw_clone() - create a new process
*
* - fork() behavior:
* This function returns 0 in the child and > 0 in the parent.
*
* - copy-on-write:
* This function does not allocate a new stack and relies on copy-on-write
* semantics.
*
* - supports subset of ClONE_* flags:
* lxc_raw_clone() intentionally only supports a subset of the flags available
* to the actual system call. Please refer to the implementation what flags
* cannot be used. Also, please don't assume that just because a flag isn't
* explicitly checked for as being unsupported that it is supported. If in
* doubt or not sufficiently familiar with process creation in the kernel and
* interactions with libcs this function should be used.
*
* - no pthread_atfork() handlers:
* This function circumvents - as much as this this is possible - any libc
* wrappers and thus does not run any pthread_atfork() handlers. Make sure
* that this is safe to do in the context you are trying to call this
* function.
*
* - must call lxc_raw_getpid():
* The child must use lxc_raw_getpid() to retrieve its pid.
*/
extern pid_t lxc_raw_clone(unsigned long flags);
/**
* lxc_raw_clone_cb() - create a new process
*
* - non-fork() behavior:
* Function does return pid of the child or -1 on error. Pass in a callback
* function via the "fn" argument that gets executed in the child process. The
* "args" argument is passed to "fn".
*
* All other comments that apply to lxc_raw_clone() apply to lxc_raw_clone_cb()
* as well.
*/
extern pid_t lxc_raw_clone_cb(int (*fn)(void *), void *args,
unsigned long flags);
extern int lxc_namespace_2_cloneflag(const char *namespace);
extern int lxc_namespace_2_ns_idx(const char *namespace);
extern int lxc_fill_namespace_flags(char *flaglist, int *flags);
/**
* Because of older glibc's pid cache (up to 2.25) whenever clone() is called
* the child must must retrieve it's own pid via lxc_raw_getpid().
*/
static inline pid_t lxc_raw_getpid(void)
{
return (pid_t) syscall(SYS_getpid);
}
#endif
......@@ -2369,7 +2369,7 @@ bool lxc_delete_network_unpriv(struct lxc_handler *handler)
}
ret = snprintf(netns_path, sizeof(netns_path), "/proc/%d/fd/%d",
getpid(), handler->nsfd[LXC_NS_NET]);
lxc_raw_getpid(), handler->nsfd[LXC_NS_NET]);
if (ret < 0 || ret >= sizeof(netns_path))
return false;
......@@ -2693,7 +2693,7 @@ int lxc_restore_phys_nics_to_netns(struct lxc_handler *handler)
TRACE("Moving physical network devices back to parent network namespace");
oldfd = lxc_preserve_ns(getpid(), "net");
oldfd = lxc_preserve_ns(lxc_raw_getpid(), "net");
if (oldfd < 0) {
SYSERROR("Failed to preserve network namespace");
return -1;
......
......@@ -726,7 +726,7 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
*/
lxc_set_state(name, handler, STOPPING);
self = getpid();
self = lxc_raw_getpid();
for (i = 0; i < LXC_NS_MAX; i++) {
if (handler->nsfd[i] < 0)
continue;
......@@ -784,11 +784,6 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
cgroup_destroy(handler);
/* This function will try to connect to the legacy lxc-monitord state
* server and only exists for backwards compatibility.
*/
lxc_monitor_send_state(name, STOPPED, handler->lxcpath);
if (handler->conf->reboot == 0) {
/* For all new state clients simply close the command socket.
* This will inform all state clients that the container is
......@@ -798,6 +793,18 @@ void lxc_fini(const char *name, struct lxc_handler *handler)
*/
close(handler->conf->maincmd_fd);
handler->conf->maincmd_fd = -1;
TRACE("Closed command socket");
/* This function will try to connect to the legacy lxc-monitord
* state server and only exists for backwards compatibility.
*/
lxc_monitor_send_state(name, STOPPED, handler->lxcpath);
/* The command socket is closed so no one can acces the command
* socket anymore so there's no need to lock it.
*/
handler->state = STOPPED;
TRACE("Set container state to \"STOPPED\"");
} else {
lxc_set_state(name, handler, STOPPED);
}
......@@ -1006,7 +1013,7 @@ static int do_start(void *data)
}
if (handler->clone_flags & CLONE_NEWCGROUP) {
fd = lxc_preserve_ns(syscall(SYS_getpid), "cgroup");
fd = lxc_preserve_ns(lxc_raw_getpid(), "cgroup");
if (fd < 0) {
ERROR("%s - Failed to preserve cgroup namespace", strerror(errno));
close(handler->data_sock[0]);
......@@ -1263,8 +1270,8 @@ int resolve_clone_flags(struct lxc_handler *handler)
* not reset anymore.
* However, if for whatever reason you - dear commiter - somehow need to get the
* pid of the dummy intermediate process for do_share_ns() you need to call
* syscall(__NR_getpid) directly. The next lxc_clone() call does not employ
* CLONE_VM and will be fine.
* lxc_raw_getpid(). The next lxc_raw_clone() call does not employ CLONE_VM and
* will be fine.
*/
static inline int do_share_ns(void *arg)
{
......@@ -1284,7 +1291,7 @@ static inline int do_share_ns(void *arg)
flags = handler->on_clone_flags;
flags |= CLONE_PARENT;
handler->pid = lxc_clone(do_start, handler, flags);
handler->pid = lxc_raw_clone_cb(do_start, handler, flags);
if (handler->pid < 0)
return -1;
......@@ -1414,7 +1421,7 @@ static int lxc_spawn(struct lxc_handler *handler)
goto out_delete_net;
}
} else {
handler->pid = lxc_clone(do_start, handler, handler->on_clone_flags);
handler->pid = lxc_raw_clone_cb(do_start, handler, handler->on_clone_flags);
}
if (handler->pid < 0) {
SYSERROR(LXC_CLONE_ERROR);
......
......@@ -1701,7 +1701,7 @@ int lxc_mount_proc_if_needed(const char *rootfs)
return -1;
}
mypid = getpid();
mypid = lxc_raw_getpid();
INFO("I am %d, /proc/self points to \"%s\"", mypid, link);
if (lxc_safe_int(link, &link_to_pid) < 0)
......@@ -2389,17 +2389,6 @@ int lxc_make_tmpfile(char *template, bool rm)
return fd;
}
uint64_t lxc_getpagesize(void)
{
int64_t pgsz;
pgsz = sysconf(_SC_PAGESIZE);
if (pgsz <= 0)
pgsz = 1 << 12;
return pgsz;
}
int parse_byte_size_string(const char *s, int64_t *converted)
{
int ret, suffix_len;
......
......@@ -519,7 +519,17 @@ extern bool has_fs_type(const char *path, fs_type_magic magic_val);
extern bool is_fs_type(const struct statfs *fs, fs_type_magic magic_val);
extern bool lxc_nic_exists(char *nic);
extern int lxc_make_tmpfile(char *template, bool rm);
extern uint64_t lxc_getpagesize(void);
static inline uint64_t lxc_getpagesize(void)
{
int64_t pgsz;
pgsz = sysconf(_SC_PAGESIZE);
if (pgsz <= 0)
pgsz = 1 << 12;
return pgsz;
}
/* If n is not a power of 2 this function will return the next power of 2
* greater than that number. Note that this function always returns the *next*
......
......@@ -116,9 +116,16 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
pid = lxc_raw_clone(CLONE_NEWUSER | CLONE_NEWCGROUP | CLONE_NEWNS |
CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWIPC |
CLONE_NEWPID | CLONE_NEWUTS);
flags |= CLONE_NEWUSER;
if (cgns_supported())
flags |= CLONE_NEWCGROUP;
flags |= CLONE_NEWNS;
flags |= CLONE_NEWIPC;
flags |= CLONE_NEWNET;
flags |= CLONE_NEWIPC;
flags |= CLONE_NEWPID;
flags |= CLONE_NEWUTS;
pid = lxc_raw_clone(flags);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
"| CLONE_NEWCGROUP | CLONE_NEWNS | "
......@@ -138,15 +145,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
flags |= CLONE_NEWUSER;
if (cgns_supported())
flags |= CLONE_NEWCGROUP;
flags |= CLONE_NEWNS;
flags |= CLONE_NEWIPC;
flags |= CLONE_NEWNET;
flags |= CLONE_NEWIPC;
flags |= CLONE_NEWPID;
flags |= CLONE_NEWUTS;
pid = lxc_raw_clone(flags);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_NEWUSER "
......@@ -165,9 +163,81 @@ int main(int argc, char *argv[])
status = wait_for_pid(pid);
if (status == 0) {
lxc_error("%s\n", "Failed to retrieve correct exit status");
exit(EXIT_FAILURE);
}
pid = lxc_raw_clone(CLONE_VFORK);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
exit(EXIT_FAILURE);
}
if (pid == 0) {
lxc_error("%s\n", "Child will exit(EXIT_SUCCESS)");
exit(EXIT_SUCCESS);
}
status = wait_for_pid(pid);
if (status != 0) {
lxc_error("%s\n", "Failed to retrieve correct exit status");
exit(EXIT_FAILURE);
}
pid = lxc_raw_clone(CLONE_VFORK);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_VFORK);");
exit(EXIT_FAILURE);
}
if (pid == 0) {
lxc_error("%s\n", "Child will exit(EXIT_FAILURE)");
exit(EXIT_FAILURE);
}
status = wait_for_pid(pid);
if (status == 0) {
lxc_error("%s\n", "Failed to retrieve correct exit status");
exit(EXIT_FAILURE);
}
pid = lxc_raw_clone(CLONE_FILES);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
exit(EXIT_FAILURE);
}
if (pid == 0) {
lxc_error("%s\n", "Child will exit(EXIT_SUCCESS)");
exit(EXIT_SUCCESS);
}
status = wait_for_pid(pid);
if (status != 0) {
lxc_error("%s\n", "Failed to retrieve correct exit status");
exit(EXIT_FAILURE);
}
pid = lxc_raw_clone(CLONE_FILES);
if (pid < 0) {
lxc_error("%s\n", "Failed to call lxc_raw_clone(CLONE_FILES);");
exit(EXIT_FAILURE);
}
if (pid == 0) {
lxc_error("%s\n", "Child will exit(EXIT_FAILURE)");
exit(EXIT_FAILURE);
}
status = wait_for_pid(pid);
if (status == 0) {
lxc_error("%s\n", "Failed to retrieve correct exit status");
exit(EXIT_FAILURE);
}
lxc_debug("%s\n", "All lxc_raw_clone() tests successful");
exit(EXIT_SUCCESS);
}
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