Skip to content

Commit

Permalink
enforcer: setup bpf lsm enforcer
Browse files Browse the repository at this point in the history
- Detect BPF on the host system
- Setup eBPF objects for BPF LSM program
- Boilerplate BPFLSM Program

Signed-off-by: daemon1024 <[email protected]>
  • Loading branch information
daemon1024 committed Jul 9, 2022
1 parent b7a0176 commit 590d420
Show file tree
Hide file tree
Showing 10 changed files with 452 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ contribution/vagrant/*.log

# protobuf
protobuf/go.sum

#header
vmlinux.h
58 changes: 58 additions & 0 deletions KubeArmor/BPF/enforcer.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// +build ignore

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

char LICENSE[] SEC("license") = "Dual BSD/GPL";
#define EPERM 1

struct outer_key {
u32 pid_ns;
u32 mnt_ns;
};

struct outer_hash {
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
__uint(max_entries, 1024);
__uint(key_size, sizeof(struct outer_key));
__uint(value_size, sizeof(u32));
__uint(pinning, LIBBPF_PIN_BY_NAME);
};

struct outer_hash kubearmor_containers SEC(".maps");

static __always_inline u32 get_task_pid_ns_id(struct task_struct *task) {
return BPF_CORE_READ(task, nsproxy, pid_ns_for_children, ns).inum;
}

static __always_inline u32 get_task_mnt_ns_id(struct task_struct *task) {
return BPF_CORE_READ(task, nsproxy, mnt_ns, ns).inum;
}

static struct file *get_task_file(struct task_struct *task) {
return BPF_CORE_READ(task, mm, exe_file);
}

SEC("lsm/bprm_check_security")
int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) {
struct task_struct *t = (struct task_struct *)bpf_get_current_task();

struct outer_key okey = {.pid_ns = get_task_pid_ns_id(t),
.mnt_ns = get_task_mnt_ns_id(t)};

if (okey.pid_ns == PROC_PID_INIT_INO) {
return 0;
}

u32 *inner = bpf_map_lookup_elem(&kubearmor_containers, &okey);

if (!inner) {
return 0;
}

bpf_printk("monitoring %u,%u", okey.pid_ns, okey.mnt_ns);

return ret;
}
115 changes: 115 additions & 0 deletions KubeArmor/enforcer/bpflsm/enforcer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2022 Authors of KubeArmor

package bpflsm

import (
"sync"

"github.com/cilium/ebpf"
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/rlimit"
fd "github.com/kubearmor/KubeArmor/KubeArmor/feeder"
tp "github.com/kubearmor/KubeArmor/KubeArmor/types"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc clang enforcer ../../BPF/enforcer.bpf.c -- -I/usr/include/bpf -O2 -g

type BPFEnforcer struct {
Logger *fd.Feeder

InnerMapSpec *ebpf.MapSpec
BPFContainerMap *ebpf.Map

// ContainerID -> NsKey + rules
ContainerMap map[string]ContainerKV
ContainerMapLock *sync.RWMutex

obj enforcerObjects

Probes map[string]link.Link
}

func NewBPFEnforcer(node tp.Node, logger *fd.Feeder) *BPFEnforcer {

be := &BPFEnforcer{}

be.Logger = logger

var err error

if err := rlimit.RemoveMemlock(); err != nil {
be.Logger.Errf("Error removing rlimit %v", err)
return nil
}

be.InnerMapSpec = &ebpf.MapSpec{
Type: ebpf.Hash,
KeySize: 4,
ValueSize: 8,
MaxEntries: 1024,
}

be.BPFContainerMap, err = ebpf.NewMapWithOptions(&ebpf.MapSpec{
Type: ebpf.HashOfMaps,
KeySize: 8,
ValueSize: 4,
MaxEntries: 1024,
Pinning: ebpf.PinByName,
InnerMap: be.InnerMapSpec,
Name: "kubearmor_containers",
}, ebpf.MapOptions{
PinPath: "/sys/fs/bpf",
})
if err != nil {
be.Logger.Errf("error creating kubearmor_containers map: %s", err)
return nil
}

if err := loadEnforcerObjects(&be.obj, &ebpf.CollectionOptions{
Maps: ebpf.MapOptions{
PinPath: "/sys/fs/bpf",
},
}); err != nil {
be.Logger.Errf("error loading BPF LSM objects: %v", err)
return nil
}

be.Probes = make(map[string]link.Link)
be.ContainerMap = make(map[string]ContainerKV)
be.ContainerMapLock = new(sync.RWMutex)

be.Probes[be.obj.EnforceProc.String()], err = link.AttachLSM(link.LSMOptions{Program: be.obj.EnforceProc})
if err != nil {
be.Logger.Errf("opening kprobe %s: %s", be.obj.EnforceProc.String(), err)
return nil
}

return be
}

func (be *BPFEnforcer) DestroyBPFEnforcer() error {
if be == nil {
return nil
}

if err := be.obj.Close(); err != nil {
return err
}

if be.BPFContainerMap != nil {
if err := be.BPFContainerMap.Unpin(); err != nil {
return err
}
if err := be.BPFContainerMap.Close(); err != nil {
return err
}
}

for _, link := range be.Probes {
if err := link.Close(); err != nil {
return err
}
}
return nil
}
119 changes: 119 additions & 0 deletions KubeArmor/enforcer/bpflsm/enforcer_bpfeb.go

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

Binary file added KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o
Binary file not shown.
Loading

0 comments on commit 590d420

Please sign in to comment.