CFLAGS += -g -ggdb -gdwarf-4
endif
+ifneq ("$(wildcard kafel/include/kafel.h)","")
+ CFLAGS += -I./kafel/include/ -DUSE_KAFEL
+ LIBS += kafel/libkafel.a
+endif
+
ifeq ("$(wildcard /usr/include/libnl3/netlink/route/link/macvlan.h)","/usr/include/libnl3/netlink/route/link/macvlan.h")
CFLAGS += -DNSJAIL_NL3_WITH_MACVLAN -I/usr/include/libnl3
LDFLAGS += -lnl-3 -lnl-route-3
all: $(BIN)
-$(BIN): $(OBJS)
- $(CC) -o $(BIN) $(OBJS) $(LDFLAGS)
+$(BIN): $(OBJS) $(LIBS)
+ $(CC) -o $(BIN) $(OBJS) $(LIBS) $(LDFLAGS)
+
+ifneq ("$(wildcard kafel/Makefile)","")
+kafel/libkafel.a:
+ $(MAKE) -C kafel
+endif
clean:
$(RM) core Makefile.bak $(OBJS) $(BIN)
+ifneq ("$(wildcard kafel/Makefile)","")
+ $(MAKE) -C kafel clean
+endif
depend:
makedepend -Y. -- -- $(SRCS)
#include <sys/types.h>
#include <unistd.h>
+#if USE_KAFEL
+#include <kafel.h>
+#endif
+
#include "log.h"
#include "util.h"
.cgroup_mem_mount = "/sys/fs/cgroup/memory",
.cgroup_mem_parent = "NSJAIL",
.cgroup_mem_max = (size_t)0,
+ .seccomp_fprog = {0, NULL},
.iface_no_lo = false,
.iface = NULL,
.iface_vs_ip = "0.0.0.0",
{{"tmpfsmount", required_argument, NULL, 'T'}, "List of mountpoints to be mounted as RW/tmpfs inside the container. Can be specified multiple times. Supports 'dest' syntax"},
{{"tmpfs_size", required_argument, NULL, 0x0602}, "Number of bytes to allocate for tmpfsmounts (default: 4194304)"},
{{"disable_proc", no_argument, NULL, 0x0603}, "Disable mounting /proc in the jail"},
+#if USE_KAFEL
+ {{"seccomp_policy", required_argument, NULL, 0x0901}, "Seccomp policy filename"},
+#endif
{{"cgroup_mem_max", required_argument, NULL, 0x0801}, "Maximum number of bytes to use in the group (default: '0' - disabled)"},
{{"cgroup_mem_mount", required_argument, NULL, 0x0802}, "Location of memory cgroup FS (default: '/sys/fs/cgroup/memory')"},
{{"cgroup_mem_parent", required_argument, NULL, 0x0803}, "Which pre-existing memory cgroup to use as a parent (default: 'NSJAIL')"},
case 0x803:
nsjconf->cgroup_mem_parent = optarg;
break;
+#if USE_KAFEL
+ case 0x901:
+ {
+ FILE *f = fopen(optarg, "r");
+ if (f == NULL) {
+ LOG_E("Could not open policy file `%s'", optarg);
+ return false;
+ }
+ kafel_ctxt_t ctxt = kafel_ctxt_create();
+ kafel_set_input_file(ctxt, f);
+ if (kafel_compile(ctxt, &nsjconf->seccomp_fprog) != 0) {
+ fclose(f);
+ LOG_E("Could not compile policy: %s",
+ kafel_error_msg(ctxt));
+ kafel_ctxt_destroy(&ctxt);
+ return false;
+ }
+ fclose(f);
+ kafel_ctxt_destroy(&ctxt);
+ }
+ break;
+#endif
default:
cmdlineUsage(argv[0], custom_opts);
return false;
* A demo policy, it disallows syslog and ptrace syscalls, both in 32 and 64
* modes
*/
-static bool sandboxPrepareAndCommit(void)
+static bool sandboxPrepareAndCommit(struct nsjconf_t *nsjconf)
{
#if defined(__x86_64__) || defined(__i386__)
- struct bpf_labels l = {.count = 0 };
- struct sock_filter filter[] = {
- LOAD_ARCH,
- JEQ32(AUDIT_ARCH_I386, JUMP(&l, label_i386)),
- JEQ32(AUDIT_ARCH_X86_64, JUMP(&l, label_x86_64)),
-
- /* I386 */
- LABEL(&l, label_i386),
- LOAD_SYSCALL_NR,
+ if (nsjconf->seccomp_fprog.filter == NULL) {
+ struct bpf_labels l = {.count = 0 };
+ struct sock_filter filter[] = {
+ LOAD_ARCH,
+ JEQ32(AUDIT_ARCH_I386, JUMP(&l, label_i386)),
+ JEQ32(AUDIT_ARCH_X86_64, JUMP(&l, label_x86_64)),
+
+ /* I386 */
+ LABEL(&l, label_i386),
+ LOAD_SYSCALL_NR,
#define __NR_syslog_32 103
#define __NR_uselib_32 86
- JEQ32(__NR_syslog_32, ERRNO(ENOENT)),
- JEQ32(__NR_uselib_32, KILL),
- ALLOW,
+ JEQ32(__NR_syslog_32, ERRNO(ENOENT)),
+ JEQ32(__NR_uselib_32, KILL),
+ ALLOW,
- /* X86_64 */
- LABEL(&l, label_x86_64),
- LOAD_SYSCALL_NR,
+ /* X86_64 */
+ LABEL(&l, label_x86_64),
+ LOAD_SYSCALL_NR,
#define __NR_syslog_64 103
#define __NR_uselib_64 134
- JEQ32(__NR_syslog_64, ERRNO(ENOENT)),
- JEQ32(__NR_uselib_64, KILL),
- ALLOW,
- };
-
- struct sock_fprog prog = {
- .filter = filter,
- .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
- };
- if (bpf_resolve_jumps(&l, filter, sizeof(filter) / sizeof(*filter)) != 0) {
- LOG_W("bpf_resolve_jumps() failed");
- return false;
+ JEQ32(__NR_syslog_64, ERRNO(ENOENT)),
+ JEQ32(__NR_uselib_64, KILL),
+ ALLOW,
+ };
+ /* *INDENT-OFF* */
+ nsjconf->seccomp_fprog = (struct sock_fprog) {
+ .filter = filter,
+ .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
+ };
+ /* *INDENT-ON* */
+ if (bpf_resolve_jumps(&l, filter, sizeof(filter) / sizeof(*filter)) != 0) {
+ LOG_W("bpf_resolve_jumps() failed");
+ return false;
+ }
}
+#endif /* defined(__x86_64__) || defined(__i386__) */
+ if (nsjconf->seccomp_fprog.filter != NULL) {
#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
#endif /* PR_SET_NO_NEW_PRIVS */
- if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
- PLOG_W("prctl(PR_SET_NO_NEW_PRIVS, 1) failed");
- return false;
- }
- if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0)) {
- PLOG_W("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER) failed");
- return false;
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+ PLOG_W("prctl(PR_SET_NO_NEW_PRIVS, 1) failed");
+ return false;
+ }
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &nsjconf->seccomp_fprog, 0, 0)) {
+ PLOG_W("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER) failed");
+ return false;
+ }
}
-#endif /* defined(__x86_64__) || defined(__i386__) */
return true;
}
if (nsjconf->apply_sandbox == false) {
return true;
}
- if (sandboxPrepareAndCommit() == false) {
+ if (sandboxPrepareAndCommit(nsjconf) == false) {
return false;
}
return true;