Skip to content

Commit

Permalink
Support policies for multiple architectures
Browse files Browse the repository at this point in the history
  • Loading branch information
happyCoder92 committed Nov 4, 2021
1 parent fdc1d64 commit 1af0975
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 41 deletions.
18 changes: 18 additions & 0 deletions include/kafel.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ extern "C" {

typedef struct kafel_ctxt* kafel_ctxt_t;

enum kafel_target_arch {
KAFEL_TARGET_ARCH_ARM = 1 << 1,
KAFEL_TARGET_ARCH_AARCH64 = 1 << 2,
KAFEL_TARGET_ARCH_X86 = 1 << 3,
KAFEL_TARGET_ARCH_X86_64 = 1 << 4,
KAFEL_TARGET_ARCH_MIPS = 1 << 5,
KAFEL_TARGET_ARCH_MIPS64 = 1 << 6,
KAFEL_TARGET_ARCH_RISCV64 = 1 << 7,
KAFEL_TARGET_ARCHS_ALL = (1 << 8)-1,
};

/*
* Creates and initializes a kafel context
*/
Expand All @@ -55,9 +66,16 @@ void kafel_set_input_string(kafel_ctxt_t ctxt, const char* string);
/*
* Sets compilation target architecture for ctxt to target_arch
* target_arch must be a supported AUDIT_ARCH_* value (see <linux/audit.h>)
* Deprecated: use kafel_set_target_archs instead.
*/
void kafel_set_target_arch(kafel_ctxt_t ctxt, uint32_t target_arch);

/*
* Sets compilation target architectures for ctxt to target_archs.
* target_archs is a bitwise-or of desired KAFEL_ARCH_* values.
*/
void kafel_set_target_archs(kafel_ctxt_t ctxt, uint32_t target_archs);

/*
* Adds path to list of include search paths for ctxt
*/
Expand Down
81 changes: 67 additions & 14 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <sys/queue.h>

#include "common.h"
#include "kafel.h"
#include "range_rules.h"
#include "syscall.h"

Expand Down Expand Up @@ -683,6 +684,33 @@ static void reverse_instruction_buffer(struct codegen_ctxt *ctxt) {
}
}

static int compile_policy_for_archs(struct codegen_ctxt *ctxt,
struct kafel_ctxt *kafel_ctxt,
uint32_t target_archs) {
ASSERT(ctxt != NULL);
ASSERT(kafel_ctxt != NULL);

struct syscall_range_rules *rules = range_rules_create();
while (target_archs) {
uint32_t target_arch = target_archs & ~(target_archs-1);
target_archs &= ~(target_arch);
const struct syscall_list *syscall_list = syscalls_lookup(target_arch);
ASSERT(syscall_list != NULL);
mark_all_policies_unused(kafel_ctxt);
add_policy_rules(rules, kafel_ctxt->main_policy, syscall_list);
}
normalize_rules(rules, kafel_ctxt->default_action);
int begin = CURRENT_LOC;
int next = generate_rules(ctxt, rules);
range_rules_destroy(&rules);
if (next > begin) {
begin = next = ADD_INSTR(BPF_LOAD_SYSCALL);
} else {
next = -kafel_ctxt->default_action;
}
return next;
}

static int compile_policy_impl(struct codegen_ctxt *ctxt,
struct kafel_ctxt *kafel_ctxt,
struct sock_fprog *prog) {
Expand All @@ -698,33 +726,58 @@ static int compile_policy_impl(struct codegen_ctxt *ctxt,
kafel_ctxt->default_action = ACTION_KILL;
}

struct syscall_range_rules *rules = range_rules_create();
const struct syscall_list *syscall_list =
syscalls_lookup(kafel_ctxt->target_arch);
ASSERT(syscall_list != NULL);
mark_all_policies_unused(kafel_ctxt);
add_policy_rules(rules, kafel_ctxt->main_policy, syscall_list);
normalize_rules(rules, kafel_ctxt->default_action);
struct {
uint32_t audit_arch;
uint32_t target_archs;
} archs[32];
int archs_len = 0;

uint32_t target_archs = kafel_ctxt->target_archs;
if (target_archs == 0) {
target_archs = KAFEL_DEFAULT_TARGET_ARCH;
}
while (target_archs) {
uint32_t target_arch = target_archs & ~(target_archs-1);
target_archs &= ~(target_arch);
const struct syscall_list *syscall_list = syscalls_lookup(target_arch);
bool found = false;
for (int i = 0; i < archs_len; ++i) {
if (archs[i].audit_arch == syscall_list->audit_arch) {
archs[i].target_archs |= target_arch;
found = true;
break;
}
}
if (!found) {
archs[archs_len].audit_arch = syscall_list->audit_arch;
archs[archs_len].target_archs = target_arch;
++archs_len;
}
}

int begin = CURRENT_LOC;
int next = generate_rules(ctxt, rules);
range_rules_destroy(&rules);
if (next > begin) {
begin = next = ADD_INSTR(BPF_LOAD_SYSCALL);
} else {
next = -kafel_ctxt->default_action;
int next = -ACTION_KILL;

for (int i = 0; i < archs_len; ++i) {
int policy = compile_policy_for_archs(ctxt, kafel_ctxt, archs[i].target_archs);
if (policy != -ACTION_KILL) {
next = add_jump(ctxt, BPF_JEQ, archs[i].audit_arch, policy, next);
}
}
next = add_jump(ctxt, BPF_JEQ, kafel_ctxt->target_arch, next, -ACTION_KILL);

if (next > begin) {
begin = next = ADD_INSTR(BPF_LOAD_ARCH);
}
if (next < 0) {
resolve_location(ctxt, next);
}

if (ctxt->max_stack_ptr >= BPF_MEMWORDS) {
append_error(kafel_ctxt,
"Required stack size exceeds available BPF memory\n");
return -1;
}

if (ctxt->buffer.len > USHRT_MAX) {
append_error(
kafel_ctxt,
Expand Down
14 changes: 7 additions & 7 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,19 @@
#ifndef KAFEL_DEFAULT_TARGET_ARCH

#if defined(__x86_64__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_X86_64
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_X86_64
#elif defined(__aarch64__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_AARCH64
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_AARCH64
#elif defined(__arm__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_ARM
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_ARM
#elif defined(__mips64__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_MIPS64
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_MIPS64
#elif defined(__mips__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_MIPS
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_MIPS
#elif defined(__i386__)
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_I386
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_X86
#elif defined(__riscv) && __riscv_xlen == 64
#define KAFEL_DEFAULT_TARGET_ARCH AUDIT_ARCH_RISCV64
#define KAFEL_DEFAULT_TARGET_ARCH KAFEL_TARGET_ARCH_RISCV64
#else
#error "Unsupported architecture"
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ KAFEL_API kafel_ctxt_t kafel_ctxt_create(void) {
includes_ctxt_init(&ctxt->includes_ctxt);
TAILQ_INIT(&ctxt->policies);
TAILQ_INIT(&ctxt->constants);
ctxt->target_arch = KAFEL_DEFAULT_TARGET_ARCH;
return ctxt;
}

Expand Down Expand Up @@ -75,6 +74,7 @@ void kafel_ctxt_clean(kafel_ctxt_t ctxt) {

kafel_ctxt_reset(ctxt);
includes_ctxt_clean(&ctxt->includes_ctxt);
ctxt->target_archs = 0;
}

KAFEL_API void kafel_ctxt_destroy(kafel_ctxt_t* ctxt) {
Expand Down
2 changes: 1 addition & 1 deletion src/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ struct kafel_ctxt {
struct policieslist policies;
struct policy* main_policy;
int default_action;
uint32_t target_arch;
uint32_t target_archs;
struct {
enum {
INPUT_NONE,
Expand Down
57 changes: 51 additions & 6 deletions src/kafel.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,11 +105,33 @@ static int validate_references_in_expr(
return -1;
}

static int validate_references(kafel_ctxt_t ctxt) {
const struct syscall_list* syscall_list = syscalls_lookup(ctxt->target_arch);
static const char* kafel_arch_to_string(uint32_t arch) {
switch (arch) {
case KAFEL_TARGET_ARCH_X86_64:
return "x86-64";
case KAFEL_TARGET_ARCH_AARCH64:
return "AArch64";
case KAFEL_TARGET_ARCH_ARM:
return "ARM";
case KAFEL_TARGET_ARCH_X86:
return "X86";
case KAFEL_TARGET_ARCH_MIPS:
return "mips";
case KAFEL_TARGET_ARCH_MIPS64:
return "mips64";
case KAFEL_TARGET_ARCH_RISCV64:
return "riscv64";
default:
return "Unknown";
}
}

static int validate_references_for_arch(kafel_ctxt_t ctxt,
uint32_t target_arch) {
const struct syscall_list* syscall_list = syscalls_lookup(target_arch);
if (syscall_list == NULL) {
append_error(ctxt, "Cannot resolve syscall list for architecture %#x\n",
ctxt->target_arch);
append_error(ctxt, "Cannot resolve syscall list for architecture %s\n",
kafel_arch_to_string(target_arch));
return -1;
}
struct policy* policy;
Expand Down Expand Up @@ -145,6 +167,22 @@ static int validate_references(kafel_ctxt_t ctxt) {
return 0;
}

static int validate_references(kafel_ctxt_t ctxt) {
uint32_t target_archs = ctxt->target_archs;
if (target_archs == 0) {
target_archs = KAFEL_DEFAULT_TARGET_ARCH;
}
while (target_archs) {
uint32_t target_arch = target_archs & ~(target_archs-1);
target_archs &= ~target_arch;
int rv = validate_references_for_arch(ctxt, target_arch);
if (rv) {
return rv;
}
}
return 0;
}

KAFEL_API void kafel_set_input_file(kafel_ctxt_t ctxt, FILE* file) {
ASSERT(ctxt != NULL);
ASSERT(file != NULL);
Expand All @@ -162,9 +200,16 @@ KAFEL_API void kafel_set_input_string(kafel_ctxt_t ctxt, const char* string) {
}

KAFEL_API void kafel_set_target_arch(kafel_ctxt_t ctxt, uint32_t target_arch) {
ASSERT(ctxt != NULL);
uint32_t kafel_arch = kafel_arch_lookup_by_audit_arch(target_arch);
ASSERT(kafel_arch != 0);
kafel_set_target_archs(ctxt, kafel_arch);
}

ctxt->target_arch = target_arch;
KAFEL_API void kafel_set_target_archs(kafel_ctxt_t ctxt,
uint32_t target_archs) {
ASSERT(ctxt != NULL);
ASSERT(target_archs <= KAFEL_TARGET_ARCHS_ALL);
ctxt->target_archs = target_archs;
}

KAFEL_API void kafel_add_include_search_path(kafel_ctxt_t ctxt,
Expand Down
33 changes: 22 additions & 11 deletions src/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <string.h>

#include "common.h"
#include "kafel.h"

// Fix for Linux <3.12
#ifndef EM_ARM
Expand All @@ -35,8 +36,8 @@
extern const struct syscall_descriptor arch##_syscall_list[]; \
extern const size_t arch##_syscall_list_size;

#define SYSCALL_LIST(audit_arch, arch) \
{ audit_arch, arch##_syscall_list, &arch##_syscall_list_size }
#define SYSCALL_LIST(kafel_arch, audit_arch, arch) \
{ kafel_arch, audit_arch, arch##_syscall_list, &arch##_syscall_list_size }

SYSCALL_LIST_DECL(arm)
SYSCALL_LIST_DECL(aarch64)
Expand All @@ -48,32 +49,42 @@ SYSCALL_LIST_DECL(riscv64)

const struct syscall_list syscall_lists[] = {
#ifdef AUDIT_ARCH_ARM
SYSCALL_LIST(AUDIT_ARCH_ARM, arm),
SYSCALL_LIST(KAFEL_TARGET_ARCH_ARM, AUDIT_ARCH_ARM, arm),
#endif
#ifdef AUDIT_ARCH_AARCH64
SYSCALL_LIST(AUDIT_ARCH_AARCH64, aarch64),
SYSCALL_LIST(KAFEL_TARGET_ARCH_AARCH64, AUDIT_ARCH_AARCH64, aarch64),
#endif
#ifdef AUDIT_ARCH_X86_64
SYSCALL_LIST(AUDIT_ARCH_X86_64, amd64),
SYSCALL_LIST(KAFEL_TARGET_ARCH_X86_64, AUDIT_ARCH_X86_64, amd64),
#endif
#ifdef AUDIT_ARCH_MIPS
SYSCALL_LIST(AUDIT_ARCH_MIPS, mipso32),
SYSCALL_LIST(KAFEL_TARGET_ARCH_MIPS, AUDIT_ARCH_MIPS, mipso32),
#endif
#ifdef AUDIT_ARCH_MIPS64
SYSCALL_LIST(AUDIT_ARCH_MIPS64, mips64),
SYSCALL_LIST(KAFEL_TARGET_ARCH_MIPS64, AUDIT_ARCH_MIPS64, mips64),
#endif
#ifdef AUDIT_ARCH_I386
SYSCALL_LIST(AUDIT_ARCH_I386, i386),
SYSCALL_LIST(KAFEL_TARGET_ARCH_X86, AUDIT_ARCH_I386, i386),
#endif
#ifdef AUDIT_ARCH_RISCV64
SYSCALL_LIST(AUDIT_ARCH_RISCV64, riscv64),
SYSCALL_LIST(KAFEL_TARGET_ARCH_RISCV64, AUDIT_ARCH_RISCV64, riscv64),
#endif
};

const struct syscall_list* syscalls_lookup(uint32_t arch) {
uint32_t kafel_arch_lookup_by_audit_arch(uint32_t audit_arch) {
for (size_t i = 0; i < sizeof(syscall_lists) / sizeof(syscall_lists[0]);
++i) {
if (syscall_lists[i].arch == arch) {
if (syscall_lists[i].audit_arch == audit_arch) {
return syscall_lists[i].kafel_arch;
}
}
return 0;
}

const struct syscall_list* syscalls_lookup(uint32_t kafel_arch) {
for (size_t i = 0; i < sizeof(syscall_lists) / sizeof(syscall_lists[0]);
++i) {
if (syscall_lists[i].kafel_arch == kafel_arch) {
return &syscall_lists[i];
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,13 @@ struct syscall_descriptor {
};

struct syscall_list {
uint32_t arch;
uint32_t kafel_arch;
uint32_t audit_arch;
const struct syscall_descriptor* const syscalls;
const size_t* const size;
};

uint32_t kafel_arch_lookup_by_audit_arch(uint32_t audit_arch);
const struct syscall_list* syscalls_lookup(uint32_t arch);
const struct syscall_descriptor* syscall_lookup(const struct syscall_list* list,
const char* name);
Expand Down

0 comments on commit 1af0975

Please sign in to comment.