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 \ log.h \
lxc.h \ lxc.h \
lxclock.h \ lxclock.h \
macro.h \
monitor.h \ monitor.h \
namespace.h \ namespace.h \
start.h \ start.h \
@ -99,6 +100,7 @@ liblxc_la_SOURCES = af_unix.c af_unix.h \
lxccontainer.c lxccontainer.h \ lxccontainer.c lxccontainer.h \
lxclock.c lxclock.h \ lxclock.c lxclock.h \
lxcseccomp.h \ lxcseccomp.h \
macro.h \
mainloop.c mainloop.h \ mainloop.c mainloop.h \
namespace.c namespace.h \ namespace.c namespace.h \
nl.c nl.h \ nl.c nl.h \
@ -342,6 +344,7 @@ init_lxc_static_SOURCES = cmd/lxc_init.c \
error.c error.h \ error.c error.h \
initutils.c initutils.h \ initutils.c initutils.h \
log.c log.h \ log.c log.h \
macro.h \
namespace.c namespace.h \ namespace.c namespace.h \
parse.c parse.h parse.c parse.h

View File

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

View File

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