aboutgitcodelistschat:MatrixIRC
diff options
context:
space:
mode:
-rw-r--r--common/util.h1
-rw-r--r--cooker/Makefile6
-rw-r--r--cooker/emit.c14
-rw-r--r--cooker/emit.h2
-rw-r--r--cooker/main.c39
-rw-r--r--cooker/match.c18
-rw-r--r--cooker/seccomp_profile.c305
-rw-r--r--cooker/seccomp_profile.h196
8 files changed, 560 insertions, 21 deletions
diff --git a/common/util.h b/common/util.h
index b11edb6..a587665 100644
--- a/common/util.h
+++ b/common/util.h
@@ -8,6 +8,7 @@
#include <string.h>
#include <stdint.h>
+#include <stdlib.h>
#include <errno.h>
#define BIT(n) (1UL << (n))
diff --git a/cooker/Makefile b/cooker/Makefile
index 31b52c9..8cf8691 100644
--- a/cooker/Makefile
+++ b/cooker/Makefile
@@ -32,11 +32,13 @@ CFLAGS += -DSEITAN_AUDIT_ARCH=AUDIT_ARCH_$(AUDIT_ARCH)
SRCS := call.c calls.c emit.c gluten.c filter.c main.c match.c \
parse.c parson.c \
$(COMMON)/util.c \
- calls/net.c calls/ioctl.c calls/process.c calls/fs.c calls/io.c
+ calls/net.c calls/ioctl.c calls/process.c calls/fs.c calls/io.c \
+ seccomp_profile.c
HEADERS := call.h calls.h cooker.h emit.h filter.h gluten.h match.h \
parse.h parson.h \
$(COMMON)/gluten.h $(COMMON)/util.h \
- calls/net.h calls/ioctl.h calls/process.h calls/fs.h calls/io.h
+ calls/net.h calls/ioctl.h calls/process.h calls/fs.h calls/io.h \
+ seccomp_profile.h
$(BIN): $(SRCS) $(HEADERS)
$(CC) $(CFLAGS) -o $(BIN) $(SRCS)
diff --git a/cooker/emit.c b/cooker/emit.c
index 28afd29..ce325f1 100644
--- a/cooker/emit.c
+++ b/cooker/emit.c
@@ -14,6 +14,7 @@
#include "filter.h"
#include "util.h"
#include "emit.h"
+#include "seccomp_profile.h"
static const char *type_str[] = {
"UNDEF", "NONE",
@@ -549,8 +550,8 @@ static void gluten_link(struct gluten_ctx *g, enum jump_type type,
}
}
-void emit_bpf_arg(int index, enum type type, union value v, union value mask,
- enum op_cmp_type cmp)
+static void emit_bpf_filter_arg(int index, enum type type, union value v,
+ union value mask, enum op_cmp_type cmp)
{
struct bpf_field bpf;
@@ -575,6 +576,15 @@ void emit_bpf_arg(int index, enum type type, union value v, union value mask,
filter_add_check(&bpf);
}
+void emit_bpf_arg(int index, enum type type, union value v, union value mask,
+ enum op_cmp_type cmp, enum scmp_mode mode)
+{
+ if (mode == SCMP_FILTER)
+ emit_bpf_filter_arg(index, type, v, mask, cmp);
+ else
+ scmp_profile_add_check(index, v, mask, cmp);
+}
+
void link_block(struct gluten_ctx *g)
{
debug(" Linking block...");
diff --git a/cooker/emit.h b/cooker/emit.h
index 7413eec..835aae7 100644
--- a/cooker/emit.h
+++ b/cooker/emit.h
@@ -46,7 +46,7 @@ struct gluten_offset emit_data_or(struct gluten_ctx *g,
struct gluten_offset offset,
enum type type, union value *value);
void emit_bpf_arg(int index, enum type type, union value v, union value mask,
- enum op_cmp_type cmp);
+ enum op_cmp_type cmp, enum scmp_mode mode);
void link_block(struct gluten_ctx *g);
void link_match(struct gluten_ctx *g);
void link_matches(struct gluten_ctx *g);
diff --git a/cooker/main.c b/cooker/main.c
index 85c4746..5c099ff 100644
--- a/cooker/main.c
+++ b/cooker/main.c
@@ -17,20 +17,23 @@
#include "gluten.h"
#include "parse.h"
#include "filter.h"
+#include "seccomp_profile.h"
/* Cooker options */
static struct option options[] = {
{ "input", required_argument, NULL, 'i' },
{ "gluten", required_argument, NULL, 'g' },
{ "filter", required_argument, NULL, 'f' },
- { "scmp-profile", required_argument, NULL, 'p' },
+ { "scmp-out-prof", required_argument, NULL, 'p' },
+ { "scmp-orig-prof", required_argument, NULL, 's' }, //??? is required
};
struct arguments {
char *input_file;
char *gluten_file;
char *filter_file;
- char *scmp_profile_file;
+ char *scmp_prof_file;
+ char *orig_scmp_prof_file;
};
static void usage()
@@ -38,10 +41,11 @@ static void usage()
printf("seitan-cooker: generate the BPF filters or seccomp profile and the action byte code for seitan\n"
"Example: setain-cooker -i <input file> -g <gluten_file> -f <filter_file>\n"
"Usage:\n"
- "\t-i, --input:\tJSON input file\n"
- "\t-g, --gluten:\tBytecode file for seitan action\n"
- "\t-f, --filter:\tBPF filter file (cannot be used together with scmp-profile)\n"
- "\t-p, --scmp-profile:\tSeccomp profile file (cannot be used together with filter)\n");
+ "\t-i, --input:\t\tJSON input file\n"
+ "\t-g, --gluten:\t\tBytecode file for seitan action\n"
+ "\t-f, --filter:\t\tBPF filter file (cannot be used together with scmp-profile)\n"
+ "\t-p, --scmp-prof:\tSeccomp profile file (cannot be used together with filter)\n"
+ "\t-s, --scmp-orig-prof:\tOriginal seccomp profile (ignored if used with filter)\n");
exit(EXIT_FAILURE);
}
@@ -51,7 +55,7 @@ static void parse(int argc, char **argv, struct arguments *arguments)
int oc;
if (arguments == NULL)
usage();
- while ((oc = getopt_long(argc, argv, ":i:g:f:p:", options,
+ while ((oc = getopt_long(argc, argv, ":i:g:f:p:s:", options,
&option_index)) != -1) {
switch (oc) {
case 'i':
@@ -64,7 +68,10 @@ static void parse(int argc, char **argv, struct arguments *arguments)
arguments->filter_file = optarg;
break;
case 'p':
- arguments->scmp_profile_file = optarg;
+ arguments->scmp_prof_file = optarg;
+ break;
+ case 's':
+ arguments->orig_scmp_prof_file = optarg;
break;
default:
usage();
@@ -75,12 +82,12 @@ static void parse(int argc, char **argv, struct arguments *arguments)
usage();
}
if (arguments->filter_file != NULL &&
- arguments->scmp_profile_file != NULL) {
+ arguments->scmp_prof_file != NULL) {
err("the filter and scmp-profile options cannot be used together");
usage();
}
if (arguments->filter_file == NULL &&
- arguments->scmp_profile_file == NULL) {
+ arguments->scmp_prof_file == NULL) {
err("select one of the options between filter and scmp-profile");
usage();
}
@@ -104,12 +111,22 @@ int main(int argc, char **argv)
parse(argc, argv, &arguments);
+ if (arguments.filter_file != NULL) {
+ g.mode = SCMP_FILTER;
+ } else {
+ g.mode = SCMP_PROFILE;
+ scmp_profile_init(arguments.orig_scmp_prof_file);
+ }
+
gluten_init(&g);
parse_file(&g, arguments.input_file);
gluten_write(&g, arguments.gluten_file);
- filter_write(arguments.filter_file);
+ if (arguments.filter_file != NULL)
+ filter_write(arguments.filter_file);
+ else
+ scmp_profile_write(arguments.scmp_prof_file);
return 0;
}
diff --git a/cooker/match.c b/cooker/match.c
index c83f9fe..eeedead 100644
--- a/cooker/match.c
+++ b/cooker/match.c
@@ -18,7 +18,7 @@
#include "util.h"
#include "calls/net.h"
-
+#include "seccomp_profile.h"
/**
* arg_load() - Allocate and build bytecode for one syscall argument
* @g: gluten context
@@ -182,7 +182,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
emit_cmp(g, cmp, masked, cmp_offset,
gluten_size[f->type], jump);
- emit_bpf_arg(index, f->type, cmpterm, set, cmp);
+ emit_bpf_arg(index, f->type, cmpterm, set, cmp, g->mode);
break;
}
@@ -213,7 +213,7 @@ xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
emit_cmp(g, cmp, data_offset, const_offset,
gluten_size[f->type], jump);
- emit_bpf_arg(index, f->type, v, mask, cmp);
+ emit_bpf_arg(index, f->type, v, mask, cmp, g->mode);
break;
case GNU_DEV_MAJOR:
@@ -379,9 +379,17 @@ void handle_matches(struct gluten_ctx *g, JSON_Value *value)
debug(" Found description for %s", name);
emit_nr(g, emit_data(g, U64, 0, &v));
- filter_notify(call->number);
+ if (g->mode == SCMP_FILTER)
+ filter_notify(call->number);
+ else
+ scmp_profile_notify(call->name);
+
parse_match(g, args, call->args);
- filter_flush_args(call->number);
+
+ if (g->mode == SCMP_FILTER)
+ filter_flush_args(call->number);
+ else
+ scmp_profile_flush_args();
break;
}
diff --git a/cooker/seccomp_profile.c b/cooker/seccomp_profile.c
new file mode 100644
index 0000000..e75fda2
--- /dev/null
+++ b/cooker/seccomp_profile.c
@@ -0,0 +1,305 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+/* seitan - Syscall Expressive Interpreter, Transformer and Notifier
+ *
+ * cooker/emit.c - Generate gluten (bytecode) instructions and read-only data
+ *
+ * Copyright 2023 Red Hat GmbH
+ * Author: Alice Frosi <afrosi@redhat.com>
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "seccomp_profile.h"
+
+static struct seccomp scmp_profile;
+static unsigned int counter;
+static unsigned int count_args;
+static JSON_Object *root_obj;
+static JSON_Value *root;
+static bool ignore_syscall;
+
+const char *scmp_act_str[] = {
+ "SCMP_ACT_KILL_THREAD", "SCMP_ACT_TRAP", "SCMP_ACT_ERRNO",
+ "SCMP_ACT_TRACE", "SCMP_ACT_ALLOW", "SCMP_ACT_LOG",
+ "SCMP_ACT_NOTIFY",
+};
+
+const char *scmp_op_str[] = {
+ "",
+ "SCMP_CMP_NE",
+ "SCMP_CMP_LT",
+ "SCMP_CMP_LE",
+ "SCMP_CMP_EQ",
+ "SCMP_CMP_GE",
+ "SCMP_CMP_GT",
+ "SCMP_CMP_MASKED_EQ",
+};
+
+const char *arch_str[] = {
+ "SCMP_ARCH_NATIVE", "SCMP_ARCH_X86", "SCMP_ARCH_X86_64",
+ "SCMP_ARCH_X32", "SCMP_ARCH_ARM", "SCMP_ARCH_AARCH64",
+ "SCMP_ARCH_MIPS", "SCMP_ARCH_MIPS64", "SCMP_ARCH_MIPS64N32",
+ "SCMP_ARCH_MIPSEL", "SCMP_ARCH_MIPSEL64", "SCMP_ARCH_MIPSEL64N32",
+ "SCMP_ARCH_PPC", "SCMP_ARCH_PPC64", "SCMP_ARCH_PPC64LE",
+ "SCMP_ARCH_S390", "SCMP_ARCH_S390X", "SCMP_ARCH_PARISC",
+ "SCMP_ARCH_PARISC64", "SCMP_ARCH_RISCV64",
+};
+
+const char *scmp_filter_str[] = {
+ "SECCOMP_FILTER_FLAG_TSYNC",
+ "SECCOMP_FILTER_FLAG_LOG",
+ "SECCOMP_FILTER_FLAG_SPEC_ALLOW",
+ "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV",
+};
+
+// TODO: decide defaults for when the original profile isn't definied
+static void set_defaults_scmp_profile()
+{
+ scmp_profile.default_action = ACT_ERRNO;
+ die("Not implemented yet");
+}
+
+static void parse_orig_scmp_profile(char *path)
+{
+ debug("Use %s as base for the generated seccomp profile", path);
+ root = json_parse_file(path);
+ if (root == NULL)
+ die(" failed parsing JSON seccomp profile: %s", path);
+}
+
+/**
+ * is_scmp_notify_set - Verify if one of the syscall entries has the SCMP_NOTIFY
+ * action enabled
+ *
+ */
+static bool is_scmp_notify_set(JSON_Array *syscalls)
+{
+ const char *action;
+ JSON_Object *obj;
+ unsigned int i;
+
+ for (i = 0; i < json_array_get_count(syscalls); i++) {
+ if (((obj = json_array_get_object(syscalls, i)) == NULL) ||
+ ((action = json_object_get_string(obj, "action")) == NULL))
+ continue;
+ if (strcmp(action, scmp_act_str[ACT_NOTIFY]) == 0)
+ return true;
+ }
+ return false;
+}
+
+void scmp_profile_init(char *path)
+{
+ JSON_Array *syscalls;
+ counter = 0;
+ count_args = 0;
+
+ if (path == NULL) {
+ root = json_value_init_object();
+ debug("Set defaults for the seccomp profile");
+ set_defaults_scmp_profile();
+ } else {
+ parse_orig_scmp_profile(path);
+ }
+ if ((root_obj = json_value_get_object(root)) == NULL)
+ die(" failed serialize JSON");
+
+ if ((syscalls = json_object_get_array(root_obj, "syscalls")) == NULL)
+ return;
+ if (is_scmp_notify_set(syscalls))
+ die(" the use of multiple seccomp notifiers isn't supported");
+}
+
+static bool is_syscall_present(const char *name)
+{
+ if (name == NULL)
+ return false;
+ for (unsigned int i = 0; i < counter; i++)
+ if (strcmp(scmp_profile.syscalls[i].names, name) == 0)
+ return true;
+
+ return false;
+}
+
+void scmp_profile_notify(const char *name)
+{
+ ignore_syscall = false;
+ if (is_syscall_present(name)) {
+ ignore_syscall = true;
+ return;
+ }
+ debug(" #%u add syscall %s to seccomp profile", counter, name);
+ strcpy(scmp_profile.syscalls[counter].names, name);
+ scmp_profile.syscalls[counter].action = ACT_NOTIFY;
+}
+
+void scmp_profile_add_check(int index, union value v, union value mask,
+ enum op_cmp_type cmp)
+{
+ char *name = scmp_profile.syscalls[counter].names;
+ struct scmp_arg *arg;
+
+ if (count_args > 5)
+ die(" too many arguments for the syscall entry %d:%s", counter,
+ name);
+ debug(" #%u add arg to syscall %s to seccomp profile", count_args);
+ arg = &scmp_profile.syscalls[counter].args[count_args];
+ arg->index = index;
+ arg->value = v.v_num;
+ arg->set = true;
+ if (mask.v_num) {
+ arg->valueTwo = mask.v_num;
+ arg->op = OP_MASKEDEQUAL;
+ return;
+ }
+
+ // TODO: check if also the other cmp operations are inverted in cooker
+ switch (cmp) {
+ case CMP_NE:
+ arg->op = OP_EQUALTO;
+ break;
+ case CMP_EQ:
+ arg->op = OP_NOTEQUAL;
+ break;
+ case CMP_LE:
+ arg->op = OP_LESSEQUAL;
+ break;
+ case CMP_LT:
+ arg->op = OP_LESSTHAN;
+ break;
+ case CMP_GE:
+ arg->op = OP_GREATEREQUAL;
+ break;
+ case CMP_GT:
+ arg->op = OP_GREATERTHAN;
+ break;
+ default:
+ die(" operation not recognized");
+ break;
+ }
+}
+
+void scmp_profile_flush_args()
+{
+ if (ignore_syscall)
+ return;
+ debug(" flush args for syscall %s",
+ scmp_profile.syscalls[counter].names);
+ counter++;
+ count_args = 0;
+}
+
+static void json_append_syscall(JSON_Array *syscalls, struct syscall *syscall)
+{
+ JSON_Value *val = json_value_init_object();
+ JSON_Object *obj = json_value_get_object(val);
+ JSON_Value *arg = json_value_init_object();
+ JSON_Object *arg_obj = json_value_get_object(arg);
+ JSON_Array *names_array;
+ JSON_Array *args_array;
+
+ json_object_set_value(obj, "names", json_value_init_array());
+ json_object_set_value(obj, "args", json_value_init_array());
+ names_array = json_object_get_array(obj, "names");
+ ;
+ args_array = json_object_get_array(obj, "args");
+ ;
+ check_JSON_status(json_object_set_string(obj, "action",
+ scmp_act_str[ACT_NOTIFY]));
+ check_JSON_status(
+ json_array_append_string(names_array, &syscall->names[0]));
+ for (unsigned int i = 0; i < 6; i++) {
+ if (!syscall->args[i].set)
+ continue;
+ check_JSON_status(json_object_set_number(
+ arg_obj, "index", syscall->args[i].index));
+ check_JSON_status(json_object_set_number(
+ arg_obj, "value", syscall->args[i].value));
+ check_JSON_status(json_object_set_number(
+ arg_obj, "valueTwo", syscall->args[i].valueTwo));
+ check_JSON_status(json_object_set_string(
+ arg_obj, "op", scmp_op_str[syscall->args[i].op]));
+ check_JSON_status(json_array_append_value(args_array, arg));
+ debug(" added args for syscall %s %d: ", syscall->names, i,
+ syscall->args[i].value, syscall->args[i].valueTwo,
+ scmp_op_str[syscall->args[i].op]);
+ }
+ json_array_append_value(syscalls, val);
+}
+
+/**
+ * remove_existing_syscall() - Remove the syscall entry name from the list where
+ * the syscall is listed as allowed and without parameters.
+ * Eg. if in the original seccomp profile with the 'connect' syscall:
+ * "syscalls": [
+ * {
+ * "names": [ ..
+ * "connect",
+ * ..
+ * "action": "SCMP_ACT_ALLOW",
+ * "args": [],
+ * }
+ *
+ */
+static void remove_existing_syscall(JSON_Array *syscalls, char *name)
+{
+ const char *curr_syscall, *action;
+ JSON_Array *names, *args;
+ unsigned int i, k;
+ JSON_Object *obj;
+
+ for (i = 0; i < json_array_get_count(syscalls); i++) {
+ if (((obj = json_array_get_object(syscalls, i)) == NULL) ||
+ ((names = json_object_get_array(obj, "names")) == NULL) ||
+ ((args = json_object_get_array(obj, "args")) == NULL) ||
+ ((action = json_object_get_string(obj, "action")) == NULL))
+ continue;
+ if ((strcmp(action, scmp_act_str[ACT_ALLOW]) != 0) ||
+ (json_array_get_count(args) > 0))
+ continue;
+ for (k = 0; k < json_array_get_count(names); k++) {
+ curr_syscall = json_array_get_string(names, k);
+ if (curr_syscall == NULL)
+ die(" empty syscall name");
+ if (strcmp(curr_syscall, name) == 0) {
+ debug(" remove %s as duplicate at %d",
+ curr_syscall, k);
+ json_array_remove(names, k);
+ }
+ }
+ }
+}
+
+static void json_serialize_syscalls()
+{
+ JSON_Array *syscalls;
+ unsigned int i;
+
+ if ((syscalls = json_object_get_array(root_obj, "syscalls")) == NULL) {
+ json_object_set_value(root_obj, "syscalls",
+ json_value_init_array());
+ syscalls = json_object_get_array(root_obj, "syscalls");
+ }
+
+ for (i = 0; i < counter; i++) {
+ remove_existing_syscall(syscalls,
+ &scmp_profile.syscalls[i].names[0]);
+ // Create syscall entry for the notify
+ json_append_syscall(syscalls, &scmp_profile.syscalls[i]);
+ }
+}
+
+void scmp_profile_write(const char *file)
+{
+ debug("Write seccomp profile to %s", file);
+ json_serialize_syscalls();
+ json_serialize_to_file_pretty(root, file);
+
+ json_value_free(root);
+
+ return;
+}
diff --git a/cooker/seccomp_profile.h b/cooker/seccomp_profile.h
new file mode 100644
index 0000000..75e81dd
--- /dev/null
+++ b/cooker/seccomp_profile.h
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+* Copyright 2023 Red Hat GmbH
+* Author: Alice Frosi <afrosi@redhat.com>
+*/
+
+#ifndef SCMP_PROFILE_H_
+#define SCMP_PROFILE_H_
+
+#include <linux/limits.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "parson.h"
+#include "util.h"
+#include "cooker.h"
+#include "gluten.h"
+
+#define STRING_MAX 2000
+#define COMMENT_MAX 1000
+/* TODO define it in a common place */
+#define SYSCALL_MAX 512
+#define MAX_SUB_ARCHES 3
+#define check_JSON_status(status) \
+ do { \
+ if (status == JSONFailure) \
+ die("failing parsing JSON value"); \
+ } while (0)
+/*
+* Definition for the OCI Seccomp Specification:
+* https://github.com/opencontainers/runtime-spec/blob/main/config-linux.md#seccomp
+*/
+extern const char *scmp_act_str[];
+
+enum scmp_act_type {
+ ACT_KILLTHREAD,
+ ACT_TRAP,
+ ACT_ERRNO,
+ ACT_TRACE,
+ ACT_ALLOW,
+ ACT_LOG,
+ ACT_NOTIFY,
+};
+
+// Define operators for syscall arguments in Seccomp
+extern const char *scmp_op_str[];
+
+enum scmp_op_type {
+ OP_NO_CHECK,
+ OP_NOTEQUAL,
+ OP_LESSTHAN,
+ OP_LESSEQUAL,
+ OP_EQUALTO,
+ OP_GREATEREQUAL,
+ OP_GREATERTHAN,
+ OP_MASKEDEQUAL,
+};
+
+// Arg used for matching specific syscall arguments in Seccomp
+struct scmp_arg {
+ bool set;
+ uint32_t index;
+ uint64_t value;
+ uint64_t valueTwo;
+ enum scmp_op_type op;
+};
+
+extern const char *arch_str[];
+
+enum arch_type {
+ ARCH_NATIVE = 0,
+ ARCH_X86,
+ ARCH_X86_64,
+ ARCH_X32,
+ ARCH_ARM,
+ ARCH_AARCH64,
+ ARCH_MIPS,
+ ARCH_MIPS64,
+ ARCH_MIPS64N2,
+ ARCH_MIPSEL,
+ ARCH_MIPSEL6,
+ ARCH_MIPSEL6N32,
+ ARCH_PPC,
+ ARCH_PPC64,
+ ARCH_PPC64LE,
+ ARCH_S390,
+ ARCH_S390X,
+ ARCH_PARISC,
+ ARCH_PARISC6,
+ ARCH_RISCV64,
+ ARCH_MAX = ARCH_RISCV64,
+};
+
+// Architecture is used to represent a specific architecture
+// and its sub-architectures
+struct architecture {
+ enum arch_type arch;
+ enum arch_type subArches[MAX_SUB_ARCHES];
+};
+
+enum caps_type {
+ CAP_CHOWN = 0,
+ CAP_DAC_OVERRIDE = 1,
+ CAP_DAC_READ_SEARCH = 2,
+ CAP_FOWNER = 3,
+ CAP_FSETID = 4,
+ CAP_KILL = 5,
+ CAP_SETGID = 6,
+ CAP_SETUID = 7,
+ CAP_SETPCAP = 8,
+ CAP_LINUX_IMMUTABLE = 9,
+ CAP_NET_BIND_SERVICE = 10,
+ CAP_NET_BROADCAST = 11,
+ CAP_NET_ADMIN = 12,
+ CAP_NET_RAW = 13,
+ CAP_IPC_LOCK = 14,
+ CAP_IPC_OWNER = 15,
+ CAP_SYS_MODULE = 16,
+ CAP_SYS_RAWIO = 17,
+ CAP_SYS_CHROOT = 18,
+ CAP_SYS_PTRACE = 19,
+ CAP_SYS_PACCT = 20,
+ CAP_SYS_ADMIN = 21,
+ CAP_SYS_BOOT = 22,
+ CAP_SYS_NICE = 23,
+ CAP_SYS_RESOURCE = 24,
+ CAP_SYS_TIME = 25,
+ CAP_SYS_TTY_CONFIG = 26,
+ CAP_MKNOD = 27,
+ CAP_LEASE = 28,
+ CAP_AUDIT_WRITE = 29,
+ CAP_AUDIT_CONTROL = 30,
+ CAP_SETFCAP = 31,
+ CAP_MAC_OVERRIDE = 32,
+ CAP_MAC_ADMIN = 33,
+ CAP_SYSLOG = 34,
+ CAP_WAKE_ALARM = 35,
+ CAP_BLOCK_SUSPEND = 36,
+ CAP_AUDIT_READ = 37,
+ CAP_PERFMON = 38,
+ CAP_BPF = 39,
+ CAP_CHECKPOINT_RESTORE = 40,
+ CAP_LAST_CAP = 41,
+ CAPS_MAX = CAP_LAST_CAP,
+};
+
+// Filter is used to conditionally apply Seccomp rules
+struct scmp_filter {
+ enum caps_type caps[CAPS_MAX];
+ enum arch_type arches[ARCH_MAX];
+};
+
+extern const char *scmp_filter_str[];
+
+enum scmp_filter_type {
+ SCMP_FILT_FLAG_TSYNC,
+ SCMP_FILT_FLAG_LOG,
+ SCMP_FILT_FLAG_SPEC_ALLOW,
+ SCMP_FILT_FLAG_WAIT_KILLABLE_RECV,
+ SCMP_FILT_FLAG_MAX = SCMP_FILT_FLAG_WAIT_KILLABLE_RECV,
+};
+
+// Syscall is used to match a group of syscalls in Seccomp
+struct syscall {
+ /* here we use a single syscall per entry*/
+ char names[STRING_MAX];
+ enum scmp_act_type action;
+ struct scmp_arg args[6];
+ char comment[COMMENT_MAX];
+ enum scmp_filter_type includes;
+ enum scmp_filter_type excludes;
+ char err[STRING_MAX];
+};
+
+// Seccomp represents the config for a seccomp profile for syscall restriction.
+struct seccomp {
+ enum scmp_act_type default_action;
+
+ char defaultErrno[STRING_MAX];
+
+ // Architectures is kept to maintain backward compatibility with the old
+ // seccomp profile.
+ enum arch_type architectures[ARCH_MAX];
+ struct architecture archMap[ARCH_MAX];
+ struct syscall syscalls[SYSCALL_MAX];
+ enum scmp_filter_type flags[SCMP_FILT_FLAG_MAX];
+ char listenerPath[PATH_MAX];
+ char listenerMetadata[PATH_MAX];
+};
+
+void scmp_profile_init();
+void scmp_profile_notify(const char *name);
+void scmp_profile_add_check(int index, union value v, union value mask,
+ enum op_cmp_type cmp);
+void scmp_profile_write(const char *file);
+void scmp_profile_flush_args();
+#endif