Skip to content

Commit

Permalink
Merge pull request kubearmor#1017 from daemon1024/refactor-bpf
Browse files Browse the repository at this point in the history
bpf,enforcer: remove conditional compilation and add alternate bpflsm availability check
  • Loading branch information
nyrahul authored Aug 1, 2023
2 parents 3f84854 + 0190aa3 commit f1b41d0
Show file tree
Hide file tree
Showing 21 changed files with 385 additions and 241 deletions.
11 changes: 0 additions & 11 deletions Dockerfile.init
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2021 Authors of KubeArmor

### build syscall checker

FROM golang:1.20-alpine3.17 as init-builder
WORKDIR /usr/src/KubeArmor
COPY ./KubeArmor/BPF/tests/main.go main.go
COPY ./KubeArmor/BPF/tests/go.mod go.mod
COPY ./KubeArmor/BPF/tests/go.sum go.sum

RUN CGO_ENABLED=0 go build -o syscheck main.go

### Make compiler image
FROM alpine:3.17 as kubearmor-init

Expand All @@ -23,5 +13,4 @@ RUN apk --no-cache add bash git clang llvm make gcc bpftool@edge

COPY ./KubeArmor/BPF /KubeArmor/BPF/
COPY ./KubeArmor/build/compile.sh /KubeArmor/compile.sh
COPY --from=init-builder /usr/src/KubeArmor/syscheck /KubeArmor/BPF/tests/syscheck
ENTRYPOINT ["/KubeArmor/compile.sh"]
22 changes: 7 additions & 15 deletions KubeArmor/BPF/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include Makefile.vars

.PHONY: all
all: kernel_headers libbpf syscall_test system_monitor.bpf.o system_monitor.container.bpf.o system_monitor.host.bpf.o
all: kernel_headers libbpf system_monitor.bpf.o system_monitor.container.bpf.o system_monitor.host.bpf.o

.PHONY: kernel_headers
kernel_headers:
Expand Down Expand Up @@ -29,35 +29,27 @@ ifeq (,$(wildcard $(LIBBPF)/src/libbpf.a))
$(Q)make -C $(LIBBPF)/src
endif

.PHONY: syscall_test
syscall_test: tests/Makefile
$(Q)make -C tests KRNDIR="$(KRNDIR)"

# below we use long chain of commands, clang | opt | llvm-dis | llc,
# to generate final object file. 'clang' compiles the source into IR
# with native target, e.g., x64, arm64, etc. 'opt' does bpf CORE IR builtin
# processing (llvm12) and IR optimizations. 'llvm-dis' converts
# 'opt' output to IR, and finally 'llc' generates bpf byte code.
# Ref https://elixir.bootlin.com/linux/v5.19.5/source/samples/bpf/Makefile#L439

system_monitor.bpf.o: $(SYSMONITOR) $(VMLINUX_H) syscall_test
system_monitor.bpf.o: $(SYSMONITOR) $(VMLINUX_H)
@echo "Compiling eBPF bytecode: $(GREEN)$@$(NC) ..."
@echo "Using Compiler flags: $(CFlags)"
$(Q)$(CL) $(KF) -DMONITOR_HOST_AND_CONTAINER $(CFlags) -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@
$(Q)$(CL) $(KF) -DMONITOR_HOST_AND_CONTAINER -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@

system_monitor.container.bpf.o: $(SYSMONITOR) $(VMLINUX_H) syscall_test
system_monitor.container.bpf.o: $(SYSMONITOR) $(VMLINUX_H)
@echo "Compiling eBPF bytecode: $(GREEN)$@$(NC) ..."
@echo "Using Compiler flags: $(CFlags)"
$(Q)$(CL) $(KF) -DMONITOR_CONTAINER $(CFlags) -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@
$(Q)$(CL) $(KF) -DMONITOR_CONTAINER -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@

system_monitor.host.bpf.o: $(SYSMONITOR) $(VMLINUX_H) syscall_test
system_monitor.host.bpf.o: $(SYSMONITOR) $(VMLINUX_H)
@echo "Compiling eBPF bytecode: $(GREEN)$@$(NC) ..."
@echo "Using Compiler flags: $(CFlags)"
$(Q)$(CL) $(KF) -DMONITOR_HOST $(CFlags) -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@
$(Q)$(CL) $(KF) -DMONITOR_HOST -Xclang -disable-llvm-passes -c $< -o - | opt -O2 -mtriple=bpf-pc-linux | llvm-dis | llc -march=bpf -mcpu=probe -filetype=obj -o $@

.PHONY: clean
clean:
@make -C tests clean
$(Q)rm -rf *.o $(VMLINUX)/vmlinux.h

.PHONY: clean-all
Expand Down
2 changes: 0 additions & 2 deletions KubeArmor/BPF/Makefile.vars
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,3 @@ RED=\033[0;31m
GREEN=\033[0;32m
CYAN=\033[0;36m
NC=\033[0m

CFlags = $(shell tr '\n' ' ' < cflags.lst )
36 changes: 36 additions & 0 deletions KubeArmor/BPF/probe.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// +build ignore
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright 2023 Authors of KubeArmor */

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

char LICENSE[] SEC("license") = "Dual BSD/GPL";

typedef struct {
bool exec;
} event;

struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} events SEC(".maps");

// Force emitting struct event into the ELF.
const event *unused __attribute__((unused));

SEC("lsm/mmap_file")
int test_memfd() {
event *task_info;

task_info = bpf_ringbuf_reserve(&events, sizeof(event), 0);
if (!task_info) {
return 0;
}

task_info->exec = true;

bpf_ringbuf_submit(task_info, 0);

return 0;
}
2 changes: 0 additions & 2 deletions KubeArmor/BPF/system_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1019,7 +1019,6 @@ static __always_inline int security_path_task_arg(struct pt_regs *ctx)
return 0;
}

#if defined(SECURITY_PATH)
SEC("kprobe/security_path_mknod")
int kprobe__security_path_mknod(struct pt_regs *ctx)
{
Expand All @@ -1043,7 +1042,6 @@ int kprobe__security_path_rmdir(struct pt_regs *ctx)
return 0;
return security_path__dir_path_args(ctx);
}
#endif

SEC("kprobe/security_ptrace_access_check")
int kprobe__security_ptrace_access_check(struct pt_regs *ctx)
Expand Down
41 changes: 0 additions & 41 deletions KubeArmor/BPF/tests/Makefile

This file was deleted.

20 changes: 0 additions & 20 deletions KubeArmor/BPF/tests/checks/security_path_unlink.c

This file was deleted.

37 changes: 0 additions & 37 deletions KubeArmor/BPF/tests/checksyscall.sh

This file was deleted.

8 changes: 0 additions & 8 deletions KubeArmor/BPF/tests/go.mod

This file was deleted.

4 changes: 0 additions & 4 deletions KubeArmor/BPF/tests/go.sum

This file was deleted.

58 changes: 0 additions & 58 deletions KubeArmor/BPF/tests/main.go

This file was deleted.

2 changes: 1 addition & 1 deletion KubeArmor/build/compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ else
make
fi

cp *.bpf.o ignore.lst /opt/kubearmor/BPF/
cp *.bpf.o /opt/kubearmor/BPF/
37 changes: 26 additions & 11 deletions KubeArmor/enforcer/runtimeEnforcer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"path/filepath"
"strings"

probe "github.com/kubearmor/KubeArmor/KubeArmor/utils/bpflsmprobe"

kl "github.com/kubearmor/KubeArmor/KubeArmor/common"
cfg "github.com/kubearmor/KubeArmor/KubeArmor/config"
be "github.com/kubearmor/KubeArmor/KubeArmor/enforcer/bpflsm"
Expand Down Expand Up @@ -126,31 +128,44 @@ func NewRuntimeEnforcer(node tp.Node, pinpath string, logger *fd.Feeder) *Runtim
re := &RuntimeEnforcer{}
re.Logger = logger

lsms := []string{}

lsmFile := []byte{}
lsmPath := "/sys/kernel/security/lsm"

if !kl.IsK8sLocal() {
// mount securityfs
if err := kl.RunCommandAndWaitWithErr("mount", []string{"-t", "securityfs", "securityfs", "/sys/kernel/security"}); err != nil {
if _, err := os.Stat(filepath.Clean("/sys/kernel/security")); err != nil {
re.Logger.Errf("Failed to read /sys/kernel/security (%s)", err.Error())
return nil
re.Logger.Warnf("Failed to read /sys/kernel/security (%s)", err.Error())
goto probeBPFLSM
}
}
}

lsm := []byte{}
lsmPath := "/sys/kernel/security/lsm"

if _, err := os.Stat(filepath.Clean(lsmPath)); err == nil {
lsm, err = os.ReadFile(lsmPath)
lsmFile, err = os.ReadFile(lsmPath)
if err != nil {
re.Logger.Errf("Failed to read /sys/kernel/security/lsm (%s)", err.Error())
return nil
re.Logger.Warnf("Failed to read /sys/kernel/security/lsm (%s)", err.Error())
goto probeBPFLSM
}
}

lsms = strings.Split(string(lsmFile), ",")

probeBPFLSM:
if !kl.ContainsElement(lsms, "bpf") {
err := probe.CheckBPFLSMSupport()
if err == nil {
lsms = append(lsms, "bpf")
} else {
re.Logger.Warnf("BPF LSM not supported %s", err.Error())
}
}

lsms := string(lsm)
re.Logger.Printf("Supported LSMs: %s", lsms)
re.Logger.Printf("Supported LSMs: %s", strings.Join(lsms, ","))

return selectLsm(re, cfg.GlobalCfg.LsmOrder, availablelsms, strings.Split(lsms, ","), node, pinpath, logger)
return selectLsm(re, cfg.GlobalCfg.LsmOrder, availablelsms, lsms, node, pinpath, logger)
}

// RegisterContainer registers container identifiers to BPFEnforcer Map
Expand Down
Loading

0 comments on commit f1b41d0

Please sign in to comment.