Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IMA hashes in LSM events #2818

Merged
merged 7 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/v1/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions api/v1/tetragon/codegen/eventchecker/eventchecker.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

287 changes: 149 additions & 138 deletions api/v1/tetragon/tetragon.pb.go

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions api/v1/tetragon/tetragon.proto
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,8 @@ message ProcessLsm {
KprobeAction action = 8;
// Tags of the Tracing Policy to categorize the event.
repeated string tags = 9;
// IMA file hash. Format algorithm:value.
string ima_hash = 11;
kkourt marked this conversation as resolved.
Show resolved Hide resolved
}

message KernelModule {
Expand Down
25 changes: 19 additions & 6 deletions bpf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ PROCESS = bpf_execve_event.o bpf_execve_event_v53.o bpf_fork.o bpf_exit.o bpf_ge
bpf_multi_kprobe_v53.o bpf_multi_retkprobe_v53.o \
bpf_generic_tracepoint.o bpf_generic_tracepoint_v53.o \
bpf_generic_uprobe.o bpf_generic_uprobe_v53.o \
bpf_generic_lsm.o bpf_generic_lsm_v511.o \
bpf_generic_lsm_core.o bpf_generic_lsm_output.o \
bpf_generic_lsm_core_v511.o bpf_generic_lsm_output_v511.o \
bpf_generic_lsm_ima_file_v511.o bpf_generic_lsm_ima_bprm_v511.o \
bpf_execve_event_v61.o \
bpf_generic_kprobe_v61.o bpf_generic_retkprobe_v61.o \
bpf_generic_tracepoint_v61.o \
Expand All @@ -27,7 +29,8 @@ PROCESS = bpf_execve_event.o bpf_execve_event_v53.o bpf_fork.o bpf_exit.o bpf_ge
bpf_generic_tracepoint_v511.o \
bpf_multi_kprobe_v511.o bpf_multi_retkprobe_v511.o \
bpf_generic_uprobe_v511.o \
bpf_generic_lsm_v61.o \
bpf_generic_lsm_core_v61.o bpf_generic_lsm_output_v61.o \
bpf_generic_lsm_ima_file_v61.o bpf_generic_lsm_ima_bprm_v61.o \
bpf_loader.o \
bpf_cgroup.o \
bpf_enforcer.o bpf_multi_enforcer.o bpf_fmodret_enforcer.o \
Expand Down Expand Up @@ -72,7 +75,10 @@ deps/bpf_multi_retkprobe_$$(VAR).d: process/bpf_generic_retkprobe.c
deps/bpf_generic_tracepoint_$$(VAR).d: process/bpf_generic_tracepoint.c
deps/bpf_generic_uprobe_$$(VAR).d: process/bpf_generic_uprobe.c
deps/bpf_multi_uprobe_$$(VAR).d: process/bpf_generic_uprobe.c
deps/bpf_generic_lsm_$$(VAR).d: process/bpf_generic_lsm.c
deps/bpf_generic_lsm_core_$$(VAR).d: process/bpf_generic_lsm_core.c
deps/bpf_generic_lsm_output_$$(VAR).d: process/bpf_generic_lsm_output.c
deps/bpf_generic_lsm_ima_bprm_$$(VAR).d: process/bpf_generic_lsm_ima_bprm.c
deps/bpf_generic_lsm_ima_file_$$(VAR).d: process/bpf_generic_lsm_ima_file.c
endef

# Generic build targets for each sub-dir
Expand Down Expand Up @@ -150,11 +156,18 @@ objs/%_v511.ll:
$(DEPSDIR)%_v511.d:
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -D__LARGE_MAP_KEYS -MM -MP -MT $(patsubst $(DEPSDIR)%.d, $(OBJSDIR)%.ll, $@) $< > $@

objs/bpf_generic_lsm.ll: process/bpf_generic_lsm.c
objs/bpf_generic_lsm_core.ll: process/bpf_generic_lsm_core.c
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -c $< -o $@

$(DEPSDIR)/bpf_generic_lsm.d:
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)bpf_generic_lsm.d, $(OBJSDIR)bpf_generic_lsm.ll, $@) $< > $@
$(DEPSDIR)/bpf_generic_lsm_core.d:
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)bpf_generic_lsm_core.d, $(OBJSDIR)bpf_generic_lsm_core.ll, $@) $< > $@

objs/bpf_generic_lsm_output.ll: process/bpf_generic_lsm_output.c
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -c $< -o $@

$(DEPSDIR)/bpf_generic_lsm_output.d:
$(CLANG) $(CLANG_FLAGS) -D__LARGE_BPF_PROG -MM -MP -MT $(patsubst $(DEPSDIR)bpf_generic_lsm_output.d, $(OBJSDIR)bpf_generic_lsm_output.ll, $@) $< > $@


# BPFTESTDIR
objs/%.ll: $(BPFTESTDIR)%.c
Expand Down
4 changes: 4 additions & 0 deletions bpf/include/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,10 @@ static void BPF_FUNC(dynptr_data, const struct bpf_dynptr *ptr, uint32_t offset,

static long BPF_FUNC(sock_ops_cb_flags_set, struct bpf_sock_ops *bpf_sock, int argval);

/* LSM */
static long BPF_FUNC(ima_file_hash, struct file *file, void *dst, uint32_t size);
static long BPF_FUNC(ima_inode_hash, struct inode *inode, void *dst, uint32_t size);

/** LLVM built-ins, mem*() routines work for constant size */

#ifndef lock_xadd
Expand Down
1 change: 1 addition & 0 deletions bpf/lib/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define MSG_COMMON_FLAG_RETURN BIT(0)
#define MSG_COMMON_FLAG_KERNEL_STACKTRACE BIT(1)
#define MSG_COMMON_FLAG_USER_STACKTRACE BIT(2)
#define MSG_COMMON_FLAG_IMA_HASH BIT(3)

/* Msg Layout */
struct msg_common {
Expand Down
5 changes: 5 additions & 0 deletions bpf/lib/generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ struct msg_generic_kprobe {
__u32 tailcall_index_process; // recursion index for generic_process_event
__u32 tailcall_index_selector; // recursion index for filter_read_arg
int pass;
union {
struct {
bool post; // true if event needs to be posted
} lsm;
};
};

FUNC_INLINE size_t generic_kprobe_common_size(void)
Expand Down
3 changes: 2 additions & 1 deletion bpf/process/bpf_generic_kprobe.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,8 @@ generic_kprobe_filter_arg(void *ctx)
__attribute__((section("kprobe/4"), used)) int
generic_kprobe_actions(void *ctx)
{
return generic_actions(ctx, &maps);
generic_actions(ctx, &maps);
return 0;
anfedotoff marked this conversation as resolved.
Show resolved Hide resolved
}

__attribute__((section("kprobe/5"), used)) int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include "compiler.h"
#include "bpf_event.h"
#include "bpf_task.h"
#ifdef __LARGE_MAP_KEYS
#include "bpf_lsm_ima.h"
#endif
#include "retprobe_map.h"
#include "types/operations.h"
#include "types/basic.h"
Expand Down Expand Up @@ -89,7 +92,7 @@ FUNC_INLINE int try_override(void *ctx)
return (long)*error;
}

#define MAIN "lsm/generic_lsm"
#define MAIN "lsm/generic_lsm_core"

__attribute__((section((MAIN)), used)) int
generic_lsm_event(struct pt_regs *ctx)
Expand Down Expand Up @@ -144,16 +147,32 @@ generic_lsm_filter_arg(void *ctx)
__attribute__((section("lsm/4"), used)) int
generic_lsm_actions(void *ctx)
{
generic_actions(ctx, &maps);
bool postit = generic_actions(ctx, &maps);

// If NoPost action is set, check for Override action here
return try_override(ctx);
}
struct msg_generic_kprobe *e;
int zero = 0;

__attribute__((section("lsm/5"), used)) int
generic_lsm_output(void *ctx)
{
generic_output(ctx, (struct bpf_map_def *)&process_call_heap, MSG_OP_GENERIC_LSM);
e = map_lookup_elem(&process_call_heap, &zero);
if (!e)
return 0;

e->lsm.post = postit;
#ifdef __LARGE_MAP_KEYS
// Set dummy hash entry for ima program
if (e && e->common.flags & MSG_COMMON_FLAG_IMA_HASH && e->lsm.post) {
struct ima_hash hash;

__u64 pid_tgid = get_current_pid_tgid();

memset(&hash, 0, sizeof(struct ima_hash));
hash.state = 1;
map_update_elem(&ima_hash_map, &pid_tgid, &hash, BPF_ANY);
}
#endif

// If NoPost action is set, check for Override action here
if (!e->lsm.post)
return try_override(ctx);

return try_override(ctx);
return 0;
}
52 changes: 52 additions & 0 deletions bpf/process/bpf_generic_lsm_ima_bprm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright Authors of Cilium */

#include "vmlinux.h"
#include "api.h"

#define GENERIC_LSM

#include "compiler.h"
#include "bpf_event.h"
#include "bpf_task.h"
#include "bpf_lsm_ima.h"
#include "retprobe_map.h"
#include "types/basic.h"

char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL";

struct filter_map_value {
unsigned char buf[FILTER_SIZE];
};

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, struct filter_map_value);
} filter_map SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, struct event_config);
} config_map SEC(".maps");

__attribute__((section("lsm.s/generic_lsm_ima_bprm"), used)) int
BPF_PROG(ima_bprm, struct linux_binprm *bprm)
{
struct ima_hash hash;
__u64 pid_tgid = get_current_pid_tgid();
struct ima_hash *dummy = map_lookup_elem(&ima_hash_map, &pid_tgid);

if (dummy && dummy->state == 1) {
if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_ima_file_hash))
hash.algo = ima_file_hash(bprm->file, &hash.value, MAX_IMA_HASH_SIZE);
else
hash.algo = ima_inode_hash(bprm->file->f_inode, &hash.value, MAX_IMA_HASH_SIZE);
hash.state = 2;
map_update_elem(&ima_hash_map, &pid_tgid, &hash, BPF_ANY);
}
return 0;
}
52 changes: 52 additions & 0 deletions bpf/process/bpf_generic_lsm_ima_file.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/* Copyright Authors of Cilium */

#include "vmlinux.h"
#include "api.h"

#define GENERIC_LSM

#include "compiler.h"
#include "bpf_event.h"
#include "bpf_task.h"
#include "bpf_lsm_ima.h"
#include "retprobe_map.h"
#include "types/basic.h"

char _license[] __attribute__((section("license"), used)) = "Dual BSD/GPL";

struct filter_map_value {
unsigned char buf[FILTER_SIZE];
};

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, int);
__type(value, struct filter_map_value);
} filter_map SEC(".maps");

struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 1);
__type(key, __u32);
__type(value, struct event_config);
} config_map SEC(".maps");

__attribute__((section("lsm.s/generic_lsm_ima_file"), used)) int
BPF_PROG(ima_file, struct file *file)
{
struct ima_hash hash;
__u64 pid_tgid = get_current_pid_tgid();
struct ima_hash *dummy = map_lookup_elem(&ima_hash_map, &pid_tgid);

if (dummy && dummy->state == 1) {
if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_ima_file_hash))
hash.algo = ima_file_hash(file, &hash.value, MAX_IMA_HASH_SIZE);
else
hash.algo = ima_inode_hash(file->f_inode, &hash.value, MAX_IMA_HASH_SIZE);
hash.state = 2;
map_update_elem(&ima_hash_map, &pid_tgid, &hash, BPF_ANY);
}
return 0;
}
Loading
Loading