diff --git a/bpf/include/api.h b/bpf/include/api.h index 9a83dbdd68e..4994824e9d4 100644 --- a/bpf/include/api.h +++ b/bpf/include/api.h @@ -267,6 +267,10 @@ static long BPF_FUNC(dynptr_read, void *dst, uint32_t len, const struct bpf_dynp static long BPF_FUNC(dynptr_write, const struct bpf_dynptr *dst, uint32_t offset, void *src, uint32_t len, uint64_t flags); static void BPF_FUNC(dynptr_data, const struct bpf_dynptr *ptr, uint32_t offset, uint32_t len); +/* 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 diff --git a/bpf/lib/common.h b/bpf/lib/common.h index acd23496346..48a9b5718a4 100644 --- a/bpf/lib/common.h +++ b/bpf/lib/common.h @@ -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 { diff --git a/bpf/process/bpf_generic_lsm.c b/bpf/process/bpf_generic_lsm.c index 69c53848e2c..f8dd3c0bdda 100644 --- a/bpf/process/bpf_generic_lsm.c +++ b/bpf/process/bpf_generic_lsm.c @@ -56,6 +56,20 @@ struct { __type(value, struct event_config); } config_map SEC(".maps"); +#ifdef __LARGE_MAP_KEYS +struct ima_hash { + int algo; + char hash[64]; +}; + +struct { + __uint(type, BPF_MAP_TYPE_LRU_HASH); + __uint(max_entries, 1024); + __type(key, struct msg_execve_key); + __type(value, struct ima_hash); +} ima_hash_map SEC(".maps"); +#endif + #ifdef __LARGE_BPF_PROG struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); @@ -154,6 +168,75 @@ __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); +#ifdef __LARGE_MAP_KEYS + struct msg_generic_kprobe *e; + int zero = 0; + + e = map_lookup_elem(&process_call_heap, &zero); + if (e && e->common.flags & MSG_COMMON_FLAG_IMA_HASH) + tail_call(ctx, &lsm_calls, TAIL_CALL_IMA_HASH); +#endif + return try_override(ctx); +} + +#ifdef __LARGE_MAP_KEYS +__attribute__((section("lsm.s/file_open"), used)) int +BPF_PROG(ima_file_open, struct file *file) +{ + struct ima_hash hash; + struct msg_generic_kprobe *e; + int zero = 0; + + e = map_lookup_elem(&process_call_heap, &zero); + if (!e) + return 0; +#ifdef __V61_BPF_PROG + hash.algo = ima_file_hash(file, &hash.hash, 64); +#else + hash.algo = ima_inode_hash(file->f_inode, &hash.hash, 64); +#endif + map_update_elem(&ima_hash_map, &e->current, &hash, BPF_ANY); + + return try_override(ctx); +} + +__attribute__((section("lsm.s/mmap_file"), used)) int +BPF_PROG(ima_mmap_file, struct file *file, unsigned long prot, unsigned long flags) +{ + struct ima_hash hash; + struct msg_generic_kprobe *e; + int zero = 0; + + e = map_lookup_elem(&process_call_heap, &zero); + if (!e) + return 0; +#ifdef __V61_BPF_PROG + hash.algo = ima_file_hash(file, &hash.hash, 64); +#else + hash.algo = ima_inode_hash(file->f_inode, &hash.hash, 64); +#endif + map_update_elem(&ima_hash_map, &e->current, &hash, BPF_ANY); return try_override(ctx); } + +__attribute__((section("lsm.s/bprm_check_security"), used)) int +BPF_PROG(ima_bprm_check_security, struct linux_binprm *bprm) +{ + struct ima_hash hash; + struct msg_generic_kprobe *e; + int zero = 0; + + e = map_lookup_elem(&process_call_heap, &zero); + if (!e) + return 0; +#ifdef __V61_BPF_PROG + hash.algo = ima_file_hash(bprm->file, &hash.hash, 64); +#else + hash.algo = ima_inode_hash(bprm->file->f_inode, &hash.hash, 64); +#endif + map_update_elem(&ima_hash_map, &e->current, &hash, BPF_ANY); + + return try_override(ctx); +} +#endif diff --git a/bpf/process/types/basic.h b/bpf/process/types/basic.h index 06de0defca1..292d878f560 100644 --- a/bpf/process/types/basic.h +++ b/bpf/process/types/basic.h @@ -120,6 +120,7 @@ enum { TAIL_CALL_ARGS = 3, TAIL_CALL_ACTIONS = 4, TAIL_CALL_SEND = 5, + TAIL_CALL_IMA_HASH = 6, }; struct generic_maps { @@ -2211,6 +2212,12 @@ do_action(void *ctx, __u32 i, struct selector_action *actions, e->common.flags |= MSG_COMMON_FLAG_USER_STACKTRACE; e->user_stack_id = get_stackid(ctx, &stack_trace_map, BPF_F_USER_STACK); } +#ifdef __LARGE_MAP_KEYS + __u32 ima_hash = actions->act[++i]; + + if (ima_hash) + e->common.flags |= MSG_COMMON_FLAG_IMA_HASH; +#endif break; } diff --git a/pkg/sensors/program/loader.go b/pkg/sensors/program/loader.go index b904f2b1334..dfe23216abc 100644 --- a/pkg/sensors/program/loader.go +++ b/pkg/sensors/program/loader.go @@ -423,6 +423,9 @@ func TracingAttach() AttachFunc { func LSMOpen(load *Program) OpenFunc { return func(coll *ebpf.CollectionSpec) error { + delete(coll.Programs, "ima_file_open") + delete(coll.Programs, "ima_mmap_file") + delete(coll.Programs, "ima_bprm_check_security") for _, prog := range coll.Programs { if prog.AttachType == ebpf.AttachLSMMac { prog.AttachTo = load.Attach diff --git a/pkg/sensors/tracing/lsm_test.go b/pkg/sensors/tracing/lsm_test.go index 5fee0397753..7b9cdee895a 100644 --- a/pkg/sensors/tracing/lsm_test.go +++ b/pkg/sensors/tracing/lsm_test.go @@ -67,6 +67,10 @@ func TestLSMObjectLoad(t *testing.T) { // generic_lsm_process_event*,generic_lsm_output tus.SensorMap{Name: "tcpmon_map", Progs: []uint{1, 2, 6}}, } + if kernels.MinKernelVersion("5.11") { + // all LSM programs + sensorMaps[1] = tus.SensorMap{Name: "lsm_calls", Progs: []uint{0, 1, 2, 3, 4, 5, 6}} + } configHook := ` apiVersion: cilium.io/v1alpha1