caps: move to C++

This commit is contained in:
Robert Swiecki 2018-02-09 17:49:13 +01:00
parent ff282fb385
commit c4e57bf27e
6 changed files with 52 additions and 44 deletions

View File

@ -35,8 +35,8 @@ LDFLAGS += -pie -Wl,-z,noexecstack -lpthread $(shell pkg-config --libs protobuf)
BIN = nsjail
LIBS = kafel/libkafel.a
SRCS_C = caps.c log.c cgroup.c mount.c pid.c user.c util.c uts.c
SRCS_CXX = cmdline.cc config.cc contain.cc cpu.cc net.cc nsjail.cc sandbox.cc subproc.cc
SRCS_C = log.c cgroup.c mount.c pid.c user.c util.c uts.c
SRCS_CXX = caps.cc cmdline.cc config.cc contain.cc cpu.cc net.cc nsjail.cc sandbox.cc subproc.cc
SRCS_PROTO = config.proto
SRCS_PB_CXX = $(SRCS_PROTO:.proto=.pb.cc)
SRCS_PB_H = $(SRCS_PROTO:.proto=.pb.h)
@ -97,7 +97,6 @@ indent:
# DO NOT DELETE THIS LINE -- make depend depends on it.
caps.o: caps.h nsjail.h common.h log.h util.h
log.o: log.h nsjail.h
cgroup.o: cgroup.h nsjail.h log.h util.h
mount.o: mount.h nsjail.h common.h log.h subproc.h util.h
@ -105,12 +104,13 @@ pid.o: pid.h nsjail.h log.h subproc.h
user.o: user.h nsjail.h common.h log.h subproc.h util.h
util.o: util.h nsjail.h common.h log.h
uts.o: uts.h nsjail.h log.h
cmdline.o: cmdline.h nsjail.h caps.h common.h log.h mount.h user.h util.h
caps.o: caps.h nsjail.h common.h log.h util.h
cmdline.o: cmdline.h nsjail.h common.h log.h mount.h user.h util.h caps.h
cmdline.o: config.h sandbox.h
config.o: common.h caps.h nsjail.h config.h log.h mount.h user.h util.h
config.o: common.h config.h nsjail.h log.h mount.h user.h util.h caps.h
config.o: cmdline.h
contain.o: contain.h nsjail.h caps.h cgroup.h log.h mount.h pid.h user.h
contain.o: uts.h cpu.h net.h
contain.o: contain.h nsjail.h cgroup.h log.h mount.h pid.h user.h uts.h
contain.o: caps.h cpu.h net.h
cpu.o: cpu.h nsjail.h log.h util.h
net.o: net.h nsjail.h log.h subproc.h
nsjail.o: nsjail.h cmdline.h common.h log.h net.h subproc.h util.h

View File

@ -28,9 +28,13 @@
#include <sys/types.h>
#include <unistd.h>
extern "C" {
#include "common.h"
#include "log.h"
#include "util.h"
}
namespace caps {
static struct {
const int val;
@ -78,7 +82,7 @@ static struct {
#endif /* defined(CAP_AUDIT_READ) */
};
int capsNameToVal(const char* name) {
int nameToVal(const char* name) {
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (strcmp(name, capNames[i].name) == 0) {
return capNames[i].val;
@ -88,7 +92,7 @@ int capsNameToVal(const char* name) {
return -1;
}
static const char* capsValToStr(int val) {
static const char* valToStr(int val) {
static __thread char capsStr[1024];
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (val == capNames[i].val) {
@ -101,7 +105,7 @@ static const char* capsValToStr(int val) {
return capsStr;
}
static cap_user_data_t capsGet() {
static cap_user_data_t getCaps() {
static __thread struct __user_cap_data_struct cap_data[_LINUX_CAPABILITY_U32S_3];
const struct __user_cap_header_struct cap_hdr = {
.version = _LINUX_CAPABILITY_VERSION_3,
@ -114,7 +118,7 @@ static cap_user_data_t capsGet() {
return cap_data;
}
static bool capsSet(const cap_user_data_t cap_data) {
static bool setCaps(const cap_user_data_t cap_data) {
const struct __user_cap_header_struct cap_hdr = {
.version = _LINUX_CAPABILITY_VERSION_3,
.pid = 0,
@ -126,31 +130,31 @@ static bool capsSet(const cap_user_data_t cap_data) {
return true;
}
static void capsClearInheritable(cap_user_data_t cap_data) {
static void clearInheritable(cap_user_data_t cap_data) {
for (size_t i = 0; i < _LINUX_CAPABILITY_U32S_3; i++) {
cap_data[i].inheritable = 0U;
}
}
static bool capsGetPermitted(cap_user_data_t cap_data, unsigned int cap) {
static bool getPermitted(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->permitted) * 8);
size_t off_bit = cap % (sizeof(cap_data->permitted) * 8);
return cap_data[off_byte].permitted & (1U << off_bit);
}
static bool capsGetEffective(cap_user_data_t cap_data, unsigned int cap) {
static bool getEffective(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->effective) * 8);
size_t off_bit = cap % (sizeof(cap_data->effective) * 8);
return cap_data[off_byte].effective & (1U << off_bit);
}
static bool capsGetInheritable(cap_user_data_t cap_data, unsigned int cap) {
static bool getInheritable(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->inheritable) * 8);
size_t off_bit = cap % (sizeof(cap_data->inheritable) * 8);
return cap_data[off_byte].inheritable & (1U << off_bit);
}
static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap) {
static void setInheritable(cap_user_data_t cap_data, unsigned int cap) {
size_t off_byte = cap / (sizeof(cap_data->inheritable) * 8);
size_t off_bit = cap % (sizeof(cap_data->inheritable) * 8);
cap_data[off_byte].inheritable |= (1U << off_bit);
@ -161,27 +165,27 @@ static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap) {
#define PR_CAP_AMBIENT_RAISE 2
#define PR_CAP_AMBIENT_CLEAR_ALL 4
#endif /* !defined(PR_CAP_AMBIENT) */
static bool CapsInitNsKeepCaps(cap_user_data_t cap_data) {
static bool initNsKeepCaps(cap_user_data_t cap_data) {
char dbgmsg[4096];
/* Copy all permitted caps to the inheritable set */
dbgmsg[0] = '\0';
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (capsGetPermitted(cap_data, capNames[i].val)) {
if (getPermitted(cap_data, capNames[i].val)) {
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
capsSetInheritable(cap_data, capNames[i].val);
setInheritable(cap_data, capNames[i].val);
}
}
LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
if (capsSet(cap_data) == false) {
if (setCaps(cap_data) == false) {
return false;
}
/* Make sure the inheritable set is preserved across execve via the ambient set */
dbgmsg[0] = '\0';
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (capsGetPermitted(cap_data, capNames[i].val) == false) {
if (getPermitted(cap_data, capNames[i].val) == false) {
continue;
}
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val, 0UL,
@ -196,17 +200,17 @@ static bool CapsInitNsKeepCaps(cap_user_data_t cap_data) {
return true;
}
bool capsInitNs(struct nsjconf_t* nsjconf) {
bool initNs(struct nsjconf_t* nsjconf) {
char dbgmsg[4096];
struct ints_t* p;
cap_user_data_t cap_data = capsGet();
cap_user_data_t cap_data = getCaps();
if (cap_data == NULL) {
return false;
}
/* Let's start with an empty inheritable set to avoid any mistakes */
capsClearInheritable(cap_data);
clearInheritable(cap_data);
/*
* Remove all capabilities from the ambient set first. It works with newer kernel versions
* only, so don't panic() if it fails
@ -216,24 +220,23 @@ bool capsInitNs(struct nsjconf_t* nsjconf) {
}
if (nsjconf->keep_caps) {
return CapsInitNsKeepCaps(cap_data);
return initNsKeepCaps(cap_data);
}
/* Set all requested caps in the inheritable set if these are present in the permitted set
*/
dbgmsg[0] = '\0';
TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
if (capsGetPermitted(cap_data, p->val) == false) {
LOG_W("Capability %s is not permitted in the namespace",
capsValToStr(p->val));
if (getPermitted(cap_data, p->val) == false) {
LOG_W("Capability %s is not permitted in the namespace", valToStr(p->val));
return false;
}
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
capsSetInheritable(cap_data, p->val);
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
setInheritable(cap_data, p->val);
}
LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
if (capsSet(cap_data) == false) {
if (setCaps(cap_data) == false) {
return false;
}
@ -241,10 +244,10 @@ bool capsInitNs(struct nsjconf_t* nsjconf) {
* Make sure all other caps (those which were not explicitly requested) are removed from the
* bounding set. We need to have CAP_SETPCAP to do that now
*/
if (capsGetEffective(cap_data, CAP_SETPCAP)) {
if (getEffective(cap_data, CAP_SETPCAP)) {
dbgmsg[0] = '\0';
for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
if (capsGetInheritable(cap_data, capNames[i].val)) {
if (getInheritable(cap_data, capNames[i].val)) {
continue;
}
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
@ -262,13 +265,14 @@ bool capsInitNs(struct nsjconf_t* nsjconf) {
TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL, 0UL) ==
-1) {
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)",
capsValToStr(p->val));
PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", valToStr(p->val));
} else {
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
}
}
LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
return true;
}
} // namespace caps

8
caps.h
View File

@ -27,7 +27,11 @@
#include "nsjail.h"
int capsNameToVal(const char* name);
bool capsInitNs(struct nsjconf_t* nsjconf);
namespace caps {
int nameToVal(const char* name);
bool initNs(struct nsjconf_t* nsjconf);
} // namespace caps
#endif /* NS_CAPS_H */

View File

@ -45,7 +45,6 @@
#include <memory>
extern "C" {
#include "caps.h"
#include "common.h"
#include "log.h"
#include "mount.h"
@ -53,6 +52,7 @@ extern "C" {
#include "util.h"
}
#include "caps.h"
#include "config.h"
#include "sandbox.h"
@ -585,7 +585,7 @@ std::unique_ptr<struct nsjconf_t> parseArgs(int argc, char* argv[]) {
case 0x0509: {
struct ints_t* f =
reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = capsNameToVal(optarg);
f->val = caps::nameToVal(optarg);
if (f->val == -1) {
return nullptr;
}

View File

@ -30,7 +30,6 @@ extern "C" {
#include <sys/stat.h>
#include <sys/types.h>
#include "caps.h"
#include "config.h"
#include "log.h"
#include "mount.h"
@ -38,6 +37,7 @@ extern "C" {
#include "util.h"
}
#include "caps.h"
#include "cmdline.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>
@ -142,7 +142,7 @@ static bool configParseInternal(struct nsjconf_t* nsjconf, const nsjail::NsJailC
for (ssize_t i = 0; i < njc.cap_size(); i++) {
struct ints_t* f =
reinterpret_cast<struct ints_t*>(utilMalloc(sizeof(struct ints_t)));
f->val = capsNameToVal(njc.cap(i).c_str());
f->val = caps::nameToVal(njc.cap(i).c_str());
if (f->val == -1) {
return false;
}

View File

@ -38,7 +38,6 @@
#include <unistd.h>
extern "C" {
#include "caps.h"
#include "cgroup.h"
#include "log.h"
#include "mount.h"
@ -47,6 +46,7 @@ extern "C" {
#include "uts.h"
}
#include "caps.h"
#include "cpu.h"
#include "net.h"
@ -73,7 +73,7 @@ static bool containDropPrivs(struct nsjconf_t* nsjconf) {
}
}
if (capsInitNs(nsjconf) == false) {
if (caps::initNs(nsjconf) == false) {
return false;
}