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)
# 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
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
+++ /dev/null
-/*
-
- nsjail - capability-related operations
- -----------------------------------------
-
- Copyright 2014 Google Inc. All Rights Reserved.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-*/
-
-#include "caps.h"
-
-#include <linux/capability.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "common.h"
-#include "log.h"
-#include "util.h"
-
-static struct {
- const int val;
- const char* const name;
-} const capNames[] = {
- NS_VALSTR_STRUCT(CAP_CHOWN),
- NS_VALSTR_STRUCT(CAP_DAC_OVERRIDE),
- NS_VALSTR_STRUCT(CAP_DAC_READ_SEARCH),
- NS_VALSTR_STRUCT(CAP_FOWNER),
- NS_VALSTR_STRUCT(CAP_FSETID),
- NS_VALSTR_STRUCT(CAP_KILL),
- NS_VALSTR_STRUCT(CAP_SETGID),
- NS_VALSTR_STRUCT(CAP_SETUID),
- NS_VALSTR_STRUCT(CAP_SETPCAP),
- NS_VALSTR_STRUCT(CAP_LINUX_IMMUTABLE),
- NS_VALSTR_STRUCT(CAP_NET_BIND_SERVICE),
- NS_VALSTR_STRUCT(CAP_NET_BROADCAST),
- NS_VALSTR_STRUCT(CAP_NET_ADMIN),
- NS_VALSTR_STRUCT(CAP_NET_RAW),
- NS_VALSTR_STRUCT(CAP_IPC_LOCK),
- NS_VALSTR_STRUCT(CAP_IPC_OWNER),
- NS_VALSTR_STRUCT(CAP_SYS_MODULE),
- NS_VALSTR_STRUCT(CAP_SYS_RAWIO),
- NS_VALSTR_STRUCT(CAP_SYS_CHROOT),
- NS_VALSTR_STRUCT(CAP_SYS_PTRACE),
- NS_VALSTR_STRUCT(CAP_SYS_PACCT),
- NS_VALSTR_STRUCT(CAP_SYS_ADMIN),
- NS_VALSTR_STRUCT(CAP_SYS_BOOT),
- NS_VALSTR_STRUCT(CAP_SYS_NICE),
- NS_VALSTR_STRUCT(CAP_SYS_RESOURCE),
- NS_VALSTR_STRUCT(CAP_SYS_TIME),
- NS_VALSTR_STRUCT(CAP_SYS_TTY_CONFIG),
- NS_VALSTR_STRUCT(CAP_MKNOD),
- NS_VALSTR_STRUCT(CAP_LEASE),
- NS_VALSTR_STRUCT(CAP_AUDIT_WRITE),
- NS_VALSTR_STRUCT(CAP_AUDIT_CONTROL),
- NS_VALSTR_STRUCT(CAP_SETFCAP),
- NS_VALSTR_STRUCT(CAP_MAC_OVERRIDE),
- NS_VALSTR_STRUCT(CAP_MAC_ADMIN),
- NS_VALSTR_STRUCT(CAP_SYSLOG),
- NS_VALSTR_STRUCT(CAP_WAKE_ALARM),
- NS_VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
-#if defined(CAP_AUDIT_READ)
- NS_VALSTR_STRUCT(CAP_AUDIT_READ),
-#endif /* defined(CAP_AUDIT_READ) */
-};
-
-int capsNameToVal(const char* name) {
- for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
- if (strcmp(name, capNames[i].name) == 0) {
- return capNames[i].val;
- }
- }
- LOG_W("Uknown capability: '%s'", name);
- return -1;
-}
-
-static const char* capsValToStr(int val) {
- static __thread char capsStr[1024];
- for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
- if (val == capNames[i].val) {
- snprintf(capsStr, sizeof(capsStr), "%s", capNames[i].name);
- return capsStr;
- }
- }
-
- snprintf(capsStr, sizeof(capsStr), "CAP_UNKNOWN(%d)", val);
- return capsStr;
-}
-
-static cap_user_data_t capsGet() {
- 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,
- .pid = 0,
- };
- if (syscall(__NR_capget, &cap_hdr, &cap_data) == -1) {
- PLOG_W("capget() failed");
- return NULL;
- }
- return cap_data;
-}
-
-static bool capsSet(const cap_user_data_t cap_data) {
- const struct __user_cap_header_struct cap_hdr = {
- .version = _LINUX_CAPABILITY_VERSION_3,
- .pid = 0,
- };
- if (syscall(__NR_capset, &cap_hdr, cap_data) == -1) {
- PLOG_W("capset() failed");
- return false;
- }
- return true;
-}
-
-static void capsClearInheritable(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) {
- 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) {
- 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) {
- 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) {
- 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);
-}
-
-#if !defined(PR_CAP_AMBIENT)
-#define PR_CAP_AMBIENT 47
-#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) {
- 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)) {
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
- capsSetInheritable(cap_data, capNames[i].val);
- }
- }
- LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
-
- if (capsSet(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) {
- continue;
- }
- if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val, 0UL,
- 0UL) == -1) {
- PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", capNames[i].name);
- } else {
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
- }
- }
- LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
-
- return true;
-}
-
-bool capsInitNs(struct nsjconf_t* nsjconf) {
- char dbgmsg[4096];
- struct ints_t* p;
-
- cap_user_data_t cap_data = capsGet();
- if (cap_data == NULL) {
- return false;
- }
-
- /* Let's start with an empty inheritable set to avoid any mistakes */
- capsClearInheritable(cap_data);
- /*
- * Remove all capabilities from the ambient set first. It works with newer kernel versions
- * only, so don't panic() if it fails
- */
- if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0UL, 0UL, 0UL) == -1) {
- PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL)");
- }
-
- if (nsjconf->keep_caps) {
- return CapsInitNsKeepCaps(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));
- return false;
- }
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
- capsSetInheritable(cap_data, p->val);
- }
- LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
-
- if (capsSet(cap_data) == false) {
- return false;
- }
-
- /*
- * 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)) {
- dbgmsg[0] = '\0';
- for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
- if (capsGetInheritable(cap_data, capNames[i].val)) {
- continue;
- }
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
- if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) ==
- -1) {
- PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
- return false;
- }
- }
- LOG_D("Dropped the following capabilities from the bounding set:%s", dbgmsg);
- }
-
- /* Make sure inheritable set is preserved across execve via the modified ambient set */
- dbgmsg[0] = '\0';
- 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));
- } else {
- utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capsValToStr(p->val));
- }
- }
- LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
-
- return true;
-}
--- /dev/null
+/*
+
+ nsjail - capability-related operations
+ -----------------------------------------
+
+ Copyright 2014 Google Inc. All Rights Reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+#include "caps.h"
+
+#include <linux/capability.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <sys/syscall.h>
+#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;
+ const char* const name;
+} const capNames[] = {
+ NS_VALSTR_STRUCT(CAP_CHOWN),
+ NS_VALSTR_STRUCT(CAP_DAC_OVERRIDE),
+ NS_VALSTR_STRUCT(CAP_DAC_READ_SEARCH),
+ NS_VALSTR_STRUCT(CAP_FOWNER),
+ NS_VALSTR_STRUCT(CAP_FSETID),
+ NS_VALSTR_STRUCT(CAP_KILL),
+ NS_VALSTR_STRUCT(CAP_SETGID),
+ NS_VALSTR_STRUCT(CAP_SETUID),
+ NS_VALSTR_STRUCT(CAP_SETPCAP),
+ NS_VALSTR_STRUCT(CAP_LINUX_IMMUTABLE),
+ NS_VALSTR_STRUCT(CAP_NET_BIND_SERVICE),
+ NS_VALSTR_STRUCT(CAP_NET_BROADCAST),
+ NS_VALSTR_STRUCT(CAP_NET_ADMIN),
+ NS_VALSTR_STRUCT(CAP_NET_RAW),
+ NS_VALSTR_STRUCT(CAP_IPC_LOCK),
+ NS_VALSTR_STRUCT(CAP_IPC_OWNER),
+ NS_VALSTR_STRUCT(CAP_SYS_MODULE),
+ NS_VALSTR_STRUCT(CAP_SYS_RAWIO),
+ NS_VALSTR_STRUCT(CAP_SYS_CHROOT),
+ NS_VALSTR_STRUCT(CAP_SYS_PTRACE),
+ NS_VALSTR_STRUCT(CAP_SYS_PACCT),
+ NS_VALSTR_STRUCT(CAP_SYS_ADMIN),
+ NS_VALSTR_STRUCT(CAP_SYS_BOOT),
+ NS_VALSTR_STRUCT(CAP_SYS_NICE),
+ NS_VALSTR_STRUCT(CAP_SYS_RESOURCE),
+ NS_VALSTR_STRUCT(CAP_SYS_TIME),
+ NS_VALSTR_STRUCT(CAP_SYS_TTY_CONFIG),
+ NS_VALSTR_STRUCT(CAP_MKNOD),
+ NS_VALSTR_STRUCT(CAP_LEASE),
+ NS_VALSTR_STRUCT(CAP_AUDIT_WRITE),
+ NS_VALSTR_STRUCT(CAP_AUDIT_CONTROL),
+ NS_VALSTR_STRUCT(CAP_SETFCAP),
+ NS_VALSTR_STRUCT(CAP_MAC_OVERRIDE),
+ NS_VALSTR_STRUCT(CAP_MAC_ADMIN),
+ NS_VALSTR_STRUCT(CAP_SYSLOG),
+ NS_VALSTR_STRUCT(CAP_WAKE_ALARM),
+ NS_VALSTR_STRUCT(CAP_BLOCK_SUSPEND),
+#if defined(CAP_AUDIT_READ)
+ NS_VALSTR_STRUCT(CAP_AUDIT_READ),
+#endif /* defined(CAP_AUDIT_READ) */
+};
+
+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;
+ }
+ }
+ LOG_W("Uknown capability: '%s'", name);
+ return -1;
+}
+
+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) {
+ snprintf(capsStr, sizeof(capsStr), "%s", capNames[i].name);
+ return capsStr;
+ }
+ }
+
+ snprintf(capsStr, sizeof(capsStr), "CAP_UNKNOWN(%d)", val);
+ return capsStr;
+}
+
+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,
+ .pid = 0,
+ };
+ if (syscall(__NR_capget, &cap_hdr, &cap_data) == -1) {
+ PLOG_W("capget() failed");
+ return NULL;
+ }
+ return 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,
+ };
+ if (syscall(__NR_capset, &cap_hdr, cap_data) == -1) {
+ PLOG_W("capset() failed");
+ return false;
+ }
+ return true;
+}
+
+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 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 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 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 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);
+}
+
+#if !defined(PR_CAP_AMBIENT)
+#define PR_CAP_AMBIENT 47
+#define PR_CAP_AMBIENT_RAISE 2
+#define PR_CAP_AMBIENT_CLEAR_ALL 4
+#endif /* !defined(PR_CAP_AMBIENT) */
+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 (getPermitted(cap_data, capNames[i].val)) {
+ utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+ setInheritable(cap_data, capNames[i].val);
+ }
+ }
+ LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
+
+ 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 (getPermitted(cap_data, capNames[i].val) == false) {
+ continue;
+ }
+ if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)capNames[i].val, 0UL,
+ 0UL) == -1) {
+ PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, %s)", capNames[i].name);
+ } else {
+ utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+ }
+ }
+ LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
+
+ return true;
+}
+
+bool initNs(struct nsjconf_t* nsjconf) {
+ char dbgmsg[4096];
+ struct ints_t* p;
+
+ 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 */
+ 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
+ */
+ if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0UL, 0UL, 0UL) == -1) {
+ PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL)");
+ }
+
+ if (nsjconf->keep_caps) {
+ 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 (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", valToStr(p->val));
+ setInheritable(cap_data, p->val);
+ }
+ LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
+
+ if (setCaps(cap_data) == false) {
+ return false;
+ }
+
+ /*
+ * 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 (getEffective(cap_data, CAP_SETPCAP)) {
+ dbgmsg[0] = '\0';
+ for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
+ if (getInheritable(cap_data, capNames[i].val)) {
+ continue;
+ }
+ utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+ if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) ==
+ -1) {
+ PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
+ return false;
+ }
+ }
+ LOG_D("Dropped the following capabilities from the bounding set:%s", dbgmsg);
+ }
+
+ /* Make sure inheritable set is preserved across execve via the modified ambient set */
+ dbgmsg[0] = '\0';
+ 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)", valToStr(p->val));
+ } else {
+ utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", valToStr(p->val));
+ }
+ }
+ LOG_D("Added the following capabilities to the ambient set:%s", dbgmsg);
+
+ return true;
+}
+
+} // namespace caps
#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 */
#include <memory>
extern "C" {
-#include "caps.h"
#include "common.h"
#include "log.h"
#include "mount.h"
#include "util.h"
}
+#include "caps.h"
#include "config.h"
#include "sandbox.h"
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;
}
#include <sys/stat.h>
#include <sys/types.h>
-#include "caps.h"
#include "config.h"
#include "log.h"
#include "mount.h"
#include "util.h"
}
+#include "caps.h"
#include "cmdline.h"
#include <google/protobuf/io/zero_copy_stream_impl.h>
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;
}
#include <unistd.h>
extern "C" {
-#include "caps.h"
#include "cgroup.h"
#include "log.h"
#include "mount.h"
#include "uts.h"
}
+#include "caps.h"
#include "cpu.h"
#include "net.h"
}
}
- if (capsInitNs(nsjconf) == false) {
+ if (caps::initNs(nsjconf) == false) {
return false;
}