Merge pull request #2508 from brauner/2018-08-04/cap_fixes

macro: add new macro header, caps: bugfixes, log: bugfixes
This commit is contained in:
Stéphane Graber 2018-08-04 15:55:32 -04:00 committed by GitHub
commit 1a64ff41a1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 259 additions and 222 deletions

View File

@ -16,6 +16,7 @@ noinst_HEADERS = attach.h \
log.h \
lxc.h \
lxclock.h \
macro.h \
monitor.h \
namespace.h \
start.h \
@ -99,6 +100,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
lxccontainer.c lxccontainer.h \
lxclock.c lxclock.h \
lxcseccomp.h \
macro.h \
mainloop.c mainloop.h \
namespace.c namespace.h \
nl.c nl.h \
@ -342,6 +344,7 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \
error.c error.h \
initutils.c initutils.h \
log.c log.h \
macro.h \
namespace.c namespace.h \
parse.c parse.h

View File

@ -33,6 +33,7 @@
#include "caps.h"
#include "log.h"
#include "macro.h"
lxc_log_define(caps, lxc);
@ -66,51 +67,52 @@ lxc_log_define(caps, lxc);
int lxc_caps_down(void)
{
cap_t caps;
int ret;
int ret = -1;
/* when we are run as root, we don't want to play
* with the capabilities */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;
caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to cap_get_proc");
return -1;
SYSERROR("Failed to retrieve capabilities");
return ret;
}
ret = cap_clear_flag(caps, CAP_EFFECTIVE);
if (ret) {
SYSERROR("Failed to cap_clear_flag");
goto out;
SYSERROR("Failed to clear effective capabilities");
goto on_error;
}
ret = cap_set_proc(caps);
if (ret) {
SYSERROR("Failed to cap_set_proc");
goto out;
SYSERROR("Failed to change effective capabilities");
goto on_error;
}
out:
ret = 0;
on_error:
cap_free(caps);
return 0;
return ret;
}
int lxc_caps_up(void)
{
cap_t caps;
cap_value_t cap;
int ret;
int ret = -1;
/* when we are run as root, we don't want to play
* with the capabilities */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;
caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to cap_get_proc");
return -1;
SYSERROR("Failed to retrieve capabilities");
return ret;
}
for (cap = 0; cap <= CAP_LAST_CAP; cap++) {
@ -119,30 +121,34 @@ int lxc_caps_up(void)
ret = cap_get_flag(caps, cap, CAP_PERMITTED, &flag);
if (ret) {
if (errno == EINVAL) {
INFO("Last supported cap was %d", cap-1);
INFO("Last supported cap was %d", cap - 1);
break;
} else {
SYSERROR("Failed to cap_get_flag");
goto out;
SYSERROR("Failed to retrieve setting for "
"permitted capability %d", cap - 1);
goto on_error;
}
}
ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, flag);
if (ret) {
SYSERROR("Failed to cap_set_flag");
goto out;
SYSERROR("Failed to set effective capability %d", cap - 1);
goto on_error;
}
}
ret = cap_set_proc(caps);
if (ret) {
SYSERROR("Failed to cap_set_proc");
goto out;
SYSERROR("Failed to change effective capabilities");
goto on_error;
}
out:
ret = 0;
on_error:
cap_free(caps);
return 0;
return ret;
}
int lxc_ambient_caps_up(void)
@ -153,7 +159,7 @@ int lxc_ambient_caps_up(void)
int last_cap = CAP_LAST_CAP;
char *cap_names = NULL;
/* When we are run as root, we don't want to play with the capabilities. */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;
@ -220,7 +226,7 @@ int lxc_ambient_caps_down(void)
cap_t caps;
cap_value_t cap;
/* When we are run as root, we don't want to play with the capabilities. */
/* When we are root, we don't want to play with capabilities. */
if (!getuid())
return 0;
@ -257,79 +263,84 @@ out:
int lxc_caps_init(void)
{
uid_t uid = getuid();
gid_t gid = getgid();
uid_t euid = geteuid();
uid_t euid, uid;
if (!uid) {
INFO("command is run as 'root'");
uid = getuid();
if (!uid)
return 0;
}
euid = geteuid();
if (uid && !euid) {
INFO("command is run as setuid root (uid : %d)", uid);
int ret;
gid_t gid;
if (prctl(PR_SET_KEEPCAPS, 1)) {
SYSERROR("Failed to 'PR_SET_KEEPCAPS'");
INFO("Command is run as setuid root (uid: %d)", uid);
ret = prctl(PR_SET_KEEPCAPS, 1);
if (ret < 0) {
SYSERROR("Failed to set PR_SET_KEEPCAPS");
return -1;
}
if (setresgid(gid, gid, gid)) {
SYSERROR("Failed to change gid to '%d'", gid);
gid = getgid();
ret = setresgid(gid, gid, gid);
if (ret < 0) {
SYSERROR("Failed to change rgid, egid, and sgid to %d", gid);
return -1;
}
if (setresuid(uid, uid, uid)) {
SYSERROR("Failed to change uid to '%d'", uid);
ret = setresuid(uid, uid, uid);
if (ret < 0) {
SYSERROR("Failed to change ruid, euid, and suid to %d", uid);
return -1;
}
if (lxc_caps_up()) {
ret = lxc_caps_up();
if (ret < 0) {
SYSERROR("Failed to restore capabilities");
return -1;
}
}
if (uid == euid)
INFO("command is run as user '%d'", uid);
INFO("Command is run with uid %d", uid);
return 0;
}
static int _real_caps_last_cap(void)
{
int fd;
int result = -1;
int fd, result = -1;
/* try to get the maximum capability over the kernel
* interface introduced in v3.2 */
fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
/* Try to get the maximum capability over the kernel interface
* introduced in v3.2.
*/
fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
char buf[32];
ssize_t n;
char *ptr;
int n;
char buf[LXC_NUMSTRLEN64 + 1];
again:
n = read(fd, buf, 31);
n = read(fd, buf, LXC_NUMSTRLEN64);
if (n < 0 && errno == EINTR) {
goto again;
} else if (n >= 0) {
buf[n] = '\0';
errno = 0;
errno = 0;
result = strtol(buf, &ptr, 10);
if (!ptr || (*ptr != '\0' && *ptr != '\n') || errno != 0)
result = -1;
}
close(fd);
}
/* try to get it manually by trying to get the status of
* each capability indiviually from the kernel */
if (result < 0) {
} else {
int cap = 0;
/* Try to get it manually by trying to get the status of each
* capability individually from the kernel.
*/
while (prctl(PR_CAPBSET_READ, cap) >= 0)
cap++;
@ -356,7 +367,7 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)
ret = cap_get_flag(caps, cap, flag, &flagval);
if (ret < 0) {
SYSERROR("Failed to perform cap_get_flag()");
SYSERROR("Failed to retrieve current setting for capability %d", cap);
return false;
}
@ -365,7 +376,7 @@ static bool lxc_cap_is_set(cap_t caps, cap_value_t cap, cap_flag_t flag)
bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
{
#if LIBCAP_SUPPORTS_FILE_CAPABILITIES
#if LIBCAP_SUPPORTS_FILE_CAPABILITIES
bool cap_is_set;
cap_t caps;
@ -377,7 +388,7 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
* case errno will be set to ENODATA.
*/
if (errno != ENODATA)
SYSERROR("Failed to perform cap_get_file()");
SYSERROR("Failed to retrieve capabilities for file %s", path);
return false;
}
@ -385,10 +396,10 @@ bool lxc_file_cap_is_set(const char *path, cap_value_t cap, cap_flag_t flag)
cap_is_set = lxc_cap_is_set(caps, cap, flag);
cap_free(caps);
return cap_is_set;
#else
#else
errno = ENODATA;
return false;
#endif
#endif
}
bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
@ -398,7 +409,7 @@ bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
caps = cap_get_proc();
if (!caps) {
SYSERROR("Failed to perform cap_get_proc()");
SYSERROR("Failed to retrieve capabilities");
return false;
}
@ -406,5 +417,4 @@ bool lxc_proc_cap_is_set(cap_value_t cap, cap_flag_t flag)
cap_free(caps);
return cap_is_set;
}
#endif

View File

@ -384,30 +384,28 @@ struct lxc_log_category lxc_log_category_lxc = {
/*---------------------------------------------------------------------------*/
static int build_dir(const char *name)
{
int ret;
char *e, *n, *p;
/* Make copy of string since we'll be modifying it. */
/* Make copy of the string since we'll be modifying it. */
n = strdup(name);
if (!n) {
ERROR("Out of memory while creating directory '%s'", name);
if (!n)
return -1;
}
e = &n[strlen(n)];
for (p = n+1; p < e; p++) {
for (p = n + 1; p < e; p++) {
int ret;
if (*p != '/')
continue;
*p = '\0';
if (access(n, F_OK)) {
ret = lxc_unpriv(mkdir(n, 0755));
if (ret && errno != EEXIST) {
SYSERROR("Failed to create directory '%s'", n);
free(n);
return -1;
}
ret = lxc_unpriv(mkdir(n, 0755));
if (ret && errno != EEXIST) {
SYSERROR("Failed to create directory %s", n);
free(n);
return -1;
}
*p = '/';
}
@ -421,9 +419,8 @@ static int log_open(const char *name)
int fd;
int newfd;
fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY |
O_APPEND | O_CLOEXEC, 0666));
if (fd == -1) {
fd = lxc_unpriv(open(name, O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC, 0666));
if (fd < 0) {
SYSERROR("Failed to open log file \"%s\"", name);
return -1;
}
@ -431,7 +428,7 @@ static int log_open(const char *name)
if (fd > 2)
return fd;
newfd = fcntl(fd, F_DUPFD_CLOEXEC, 3);
newfd = fcntl(fd, F_DUPFD_CLOEXEC, STDERR_FILENO);
if (newfd == -1)
SYSERROR("Failed to dup log fd %d", fd);
@ -448,15 +445,17 @@ static int log_open(const char *name)
static char *build_log_path(const char *name, const char *lxcpath)
{
char *p;
int len, ret, use_dir;
int ret;
size_t len;
bool use_dir;
if (!name)
return NULL;
#if USE_CONFIGPATH_LOGS
use_dir = 1;
use_dir = true;
#else
use_dir = 0;
use_dir = false;
#endif
/*
@ -469,7 +468,7 @@ static char *build_log_path(const char *name, const char *lxcpath)
*/
len = strlen(name) + 6; /* 6 == '/' + '.log' + '\0' */
if (lxcpath)
use_dir = 1;
use_dir = true;
else
lxcpath = LOGPATH;
@ -486,7 +485,7 @@ static char *build_log_path(const char *name, const char *lxcpath)
ret = snprintf(p, len, "%s/%s/%s.log", lxcpath, name, name);
else
ret = snprintf(p, len, "%s/%s.log", lxcpath, name);
if (ret < 0 || ret >= len) {
if (ret < 0 || (size_t)ret >= len) {
free(p);
return NULL;
}
@ -494,7 +493,7 @@ static char *build_log_path(const char *name, const char *lxcpath)
return p;
}
extern void lxc_log_close(void)
void lxc_log_close(void)
{
closelog();
@ -562,12 +561,13 @@ static int _lxc_log_set_file(const char *name, const char *lxcpath, int create_d
ERROR("Could not build log path");
return -1;
}
ret = __lxc_log_set_file(logfile, create_dirs);
free(logfile);
return ret;
}
extern int lxc_log_syslog(int facility)
int lxc_log_syslog(int facility)
{
struct lxc_log_appender *appender;
@ -595,7 +595,7 @@ extern int lxc_log_syslog(int facility)
return 0;
}
extern void lxc_log_enable_syslog(void)
inline void lxc_log_enable_syslog(void)
{
syslog_enable = 1;
}
@ -605,13 +605,13 @@ extern void lxc_log_enable_syslog(void)
* Called from lxc front-end programs (like lxc-create, lxc-start) to
* initalize the log defaults.
*/
extern int lxc_log_init(struct lxc_log *log)
int lxc_log_init(struct lxc_log *log)
{
int lxc_priority = LXC_LOG_LEVEL_ERROR;
int ret;
int lxc_priority = LXC_LOG_LEVEL_ERROR;
if (lxc_log_fd != -1) {
WARN("lxc_log_init called with log already initialized");
WARN("Log already initialized");
return 0;
}
@ -637,6 +637,7 @@ extern int lxc_log_init(struct lxc_log *log)
if (log->file) {
if (strcmp(log->file, "none") == 0)
return 0;
ret = __lxc_log_set_file(log->file, 1);
lxc_log_use_global_fd = 1;
} else {
@ -679,7 +680,7 @@ extern int lxc_log_init(struct lxc_log *log)
* happens after processing command line arguments, which override the .conf
* settings. So only set the level if previously unset.
*/
extern int lxc_log_set_level(int *dest, int level)
int lxc_log_set_level(int *dest, int level)
{
if (level < 0 || level >= LXC_LOG_LEVEL_NOTSET) {
ERROR("Invalid log priority %d", level);
@ -690,15 +691,16 @@ extern int lxc_log_set_level(int *dest, int level)
return 0;
}
extern int lxc_log_get_level(void)
inline int lxc_log_get_level(void)
{
return lxc_log_category_lxc.priority;
}
extern bool lxc_log_has_valid_level(void)
bool lxc_log_has_valid_level(void)
{
int log_level = lxc_log_get_level();
int log_level;
log_level = lxc_log_get_level();
if (log_level < 0 || log_level >= LXC_LOG_LEVEL_NOTSET)
return false;
@ -710,42 +712,40 @@ extern bool lxc_log_has_valid_level(void)
* happens after processing command line arguments, which override the .conf
* settings. So only set the file if previously unset.
*/
extern int lxc_log_set_file(int *fd, const char *fname)
int lxc_log_set_file(int *fd, const char *fname)
{
if (*fd != -1) {
if (*fd >= 0) {
close(*fd);
*fd = -1;
}
if (build_dir(fname)) {
SYSERROR("Failed to create dir for log file \"%s\"", fname);
if (build_dir(fname))
return -1;
}
*fd = log_open(fname);
if (*fd == -1)
return -errno;
if (*fd < 0)
return -1;
return 0;
}
extern const char *lxc_log_get_file(void)
inline const char *lxc_log_get_file(void)
{
return log_fname;
}
extern void lxc_log_set_prefix(const char *prefix)
inline void lxc_log_set_prefix(const char *prefix)
{
/* We don't care if thte prefix is truncated. */
(void)strlcpy(log_prefix, prefix, sizeof(log_prefix));
}
extern const char *lxc_log_get_prefix(void)
inline const char *lxc_log_get_prefix(void)
{
return log_prefix;
}
extern void lxc_log_options_no_override()
inline void lxc_log_options_no_override()
{
lxc_quiet_specified = 1;
lxc_loglevel_specified = 1;

139
src/lxc/macro.h Normal file
View File

@ -0,0 +1,139 @@
/* liblxcapi
*
* Copyright © 2018 Christian Brauner <christian.brauner@ubuntu.com>.
* Copyright © 2018 Canonical Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __LXC_MACRO_H
#define __LXC_MACRO_H
/* Define __S_ISTYPE if missing from the C library. */
#ifndef __S_ISTYPE
#define __S_ISTYPE(mode, mask) (((mode)&S_IFMT) == (mask))
#endif
#if HAVE_LIBCAP
#ifndef CAP_SETFCAP
#define CAP_SETFCAP 31
#endif
#ifndef CAP_MAC_OVERRIDE
#define CAP_MAC_OVERRIDE 32
#endif
#ifndef CAP_MAC_ADMIN
#define CAP_MAC_ADMIN 33
#endif
#endif
#ifndef PR_CAPBSET_DROP
#define PR_CAPBSET_DROP 24
#endif
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef CAP_SETUID
#define CAP_SETUID 7
#endif
#ifndef CAP_SETGID
#define CAP_SETGID 6
#endif
/* needed for cgroup automount checks, regardless of whether we
* have included linux/capability.h or not */
#ifndef CAP_SYS_ADMIN
#define CAP_SYS_ADMIN 21
#endif
#ifndef CGROUP_SUPER_MAGIC
#define CGROUP_SUPER_MAGIC 0x27e0eb
#endif
#ifndef CGROUP2_SUPER_MAGIC
#define CGROUP2_SUPER_MAGIC 0x63677270
#endif
/* Useful macros */
/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
#define LXC_NUMSTRLEN64 21
#define LXC_LINELEN 4096
#define LXC_IDMAPLEN 4096
#define LXC_MAX_BUFFER 4096
/* /proc/ = 6
* +
* <pid-as-str> = LXC_NUMSTRLEN64
* +
* /fd/ = 4
* +
* <fd-as-str> = LXC_NUMSTRLEN64
* +
* \0 = 1
*/
#define LXC_PROC_PID_FD_LEN (6 + LXC_NUMSTRLEN64 + 4 + LXC_NUMSTRLEN64 + 1)
/* loop devices */
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef LOOP_CTL_GET_FREE
#define LOOP_CTL_GET_FREE 0x4C82
#endif
/* memfd_create() */
#ifndef MFD_CLOEXEC
#define MFD_CLOEXEC 0x0001U
#endif
#ifndef MFD_ALLOW_SEALING
#define MFD_ALLOW_SEALING 0x0002U
#endif
/**
* BUILD_BUG_ON - break compile if a condition is true.
* @condition: the condition which the compiler should know is false.
*
* If you have some code which relies on certain constants being equal, or
* other compile-time-evaluated condition, you should use BUILD_BUG_ON to
* detect if someone changes it.
*
* The implementation uses gcc's reluctance to create a negative array, but
* gcc (as of 4.4) only emits that error for obvious cases (eg. not arguments
* to inline functions). So as a fallback we use the optimizer; if it can't
* prove the condition is false, it will cause a link error on the undefined
* "__build_bug_on_failed". This error message can be harder to track down
* though, hence the two different methods.
*/
#ifndef __OPTIMIZE__
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#else
extern int __build_bug_on_failed;
#define BUILD_BUG_ON(condition) \
do { \
((void)sizeof(char[1 - 2*!!(condition)])); \
if (condition) __build_bug_on_failed = 1; \
} while(0)
#endif
#define lxc_iterate_parts(__iterator, __splitme, __separators) \
for (char *__p = NULL, *__it = strtok_r(__splitme, __separators, &__p); \
(__iterator = __it); \
__iterator = __it = strtok_r(NULL, __separators, &__p))
#endif /* __LXC_MACRO_H */

View File

@ -45,73 +45,7 @@
#endif
#include "initutils.h"
/* Define __S_ISTYPE if missing from the C library. */
#ifndef __S_ISTYPE
#define __S_ISTYPE(mode, mask) (((mode)&S_IFMT) == (mask))
#endif
#if HAVE_LIBCAP
#ifndef CAP_SETFCAP
#define CAP_SETFCAP 31
#endif
#ifndef CAP_MAC_OVERRIDE
#define CAP_MAC_OVERRIDE 32
#endif
#ifndef CAP_MAC_ADMIN
#define CAP_MAC_ADMIN 33
#endif
#endif
#ifndef PR_CAPBSET_DROP
#define PR_CAPBSET_DROP 24
#endif
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef CAP_SETUID
#define CAP_SETUID 7
#endif
#ifndef CAP_SETGID
#define CAP_SETGID 6
#endif
/* needed for cgroup automount checks, regardless of whether we
* have included linux/capability.h or not */
#ifndef CAP_SYS_ADMIN
#define CAP_SYS_ADMIN 21
#endif
#ifndef CGROUP_SUPER_MAGIC
#define CGROUP_SUPER_MAGIC 0x27e0eb
#endif
#ifndef CGROUP2_SUPER_MAGIC
#define CGROUP2_SUPER_MAGIC 0x63677270
#endif
/* Useful macros */
/* Maximum number for 64 bit integer is a string with 21 digits: 2^64 - 1 = 21 */
#define LXC_NUMSTRLEN64 21
#define LXC_LINELEN 4096
#define LXC_IDMAPLEN 4096
#define LXC_MAX_BUFFER 4096
/* /proc/ = 6
* +
* <pid-as-str> = LXC_NUMSTRLEN64
* +
* /fd/ = 4
* +
* <fd-as-str> = LXC_NUMSTRLEN64
* +
* \0 = 1
*/
#define LXC_PROC_PID_FD_LEN (6 + LXC_NUMSTRLEN64 + 4 + LXC_NUMSTRLEN64 + 1)
#include "macro.h"
/* returns 1 on success, 0 if there were any failures */
extern int lxc_rmdir_onedev(const char *path, const char *exclude);
@ -265,24 +199,6 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
}
#endif
/* loop devices */
#ifndef LO_FLAGS_AUTOCLEAR
#define LO_FLAGS_AUTOCLEAR 4
#endif
#ifndef LOOP_CTL_GET_FREE
#define LOOP_CTL_GET_FREE 0x4C82
#endif
/* memfd_create() */
#ifndef MFD_CLOEXEC
#define MFD_CLOEXEC 0x0001U
#endif
#ifndef MFD_ALLOW_SEALING
#define MFD_ALLOW_SEALING 0x0002U
#endif
#ifndef HAVE_MEMFD_CREATE
static inline int memfd_create(const char *name, unsigned int flags) {
#ifndef __NR_memfd_create
@ -359,32 +275,6 @@ extern struct lxc_popen_FILE *lxc_popen(const char *command);
*/
extern int lxc_pclose(struct lxc_popen_FILE *fp);
/**
* BUILD_BUG_ON - break compile if a condition is true.
* @condition: the condition which the compiler should know is false.
*
* If you have some code which relies on certain constants being equal, or
* other compile-time-evaluated condition, you should use BUILD_BUG_ON to
* detect if someone changes it.
*
* The implementation uses gcc's reluctance to create a negative array, but
* gcc (as of 4.4) only emits that error for obvious cases (eg. not arguments
* to inline functions). So as a fallback we use the optimizer; if it can't
* prove the condition is false, it will cause a link error on the undefined
* "__build_bug_on_failed". This error message can be harder to track down
* though, hence the two different methods.
*/
#ifndef __OPTIMIZE__
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#else
extern int __build_bug_on_failed;
#define BUILD_BUG_ON(condition) \
do { \
((void)sizeof(char[1 - 2*!!(condition)])); \
if (condition) __build_bug_on_failed = 1; \
} while(0)
#endif
/*
* wait on a child we forked
*/
@ -620,9 +510,4 @@ extern int lxc_set_death_signal(int signal);
extern int fd_cloexec(int fd, bool cloexec);
extern int recursive_destroy(char *dirname);
#define lxc_iterate_parts(__iterator, __splitme, __separators) \
for (char *__p = NULL, *__it = strtok_r(__splitme, __separators, &__p); \
(__iterator = __it); \
__iterator = __it = strtok_r(NULL, __separators, &__p))
#endif /* __LXC_UTILS_H */