Skip to main content

KubeArmor BPF LSM Integration

· 3 min read
Barun Acharya

KubeArmor BPF LSM Integration

High Level Module Changes

NowProposed
NowProposed

Module Design

Module Design

Map Design

Map Design

Outer Map details

struct outer_hash {
__uint(type, BPF_MAP_TYPE_HASH_OF_MAPS);
__uint(max_entries, X);
__uint(key_size, sizeof(struct outer_key)); // 2*u32
__uint(value_size, sizeof(u32)); // Inner Map File Descriptor
__uint(pinning, LIBBPF_PIN_BY_NAME); // Created in Userspace, Identified in Kernel Space using pinned name
};
  • Key
    • Identifier for Containers
struct outer_key {
u32 pid_ns;
u32 mnt_ns;
};

Inner Map details

&ebpf.MapSpec{
Type: ebpf.Hash,
KeySize: 4, // Hash Value of Entity
ValueSize: 8, // Decision Values
MaxEntries: 1024,
}
  • Value
struct data_t {
bool owner; // owner only flag
bool read; // read only flag
bool dir; // policy directory flag
bool recursive; // directory recursive flag
bool hint; // policy directory hint
};

Handling of Events

Handling of Events

Deeper Dive with Examples

  1. Example 1

  2. Example 2 But what if it's not a match Match We explore how directory matching works in the next example

  3. Example
    Notice How we split the directory policy to a sets of hints in the map. This helps in efficient matching of directory paths in Kernel Space. Map
    What if we try to access a file in a different directory.
    Route
    Presence of no hint helps break through the iteration hence optimizing the process.

Directory Matching

#pragma unroll
for (int i = 0; i < MAX_STRING_SIZE; i++) {
if (path[i] == '\0')
break;

if (path[i] == '/') {
__builtin_memset(&dir, 0, sizeof(dir));
bpf_probe_read_str(&dir, i + 2, path);

fp = jenkins_hash(dir, i + 1, 0);

struct data_t *val = bpf_map_lookup_elem(inner, &fp);
if (val) {
if (val->dir) {
matched = true;
goto decisionmaker;
}
if (val->hint == 0) { // If we match a non directory entity somehow
break;
}
} else {
break;
}
}
}

Hashing

Files and Source Names can be huge. Worst case both add to 8192 bytes. Which is a very large entity for key. So we hash that value to u32 key. We stored hashed values from userspace and lookup up hashed values from kernel space for decision making.

We plan to use a Jenkins hash algorithm modified for use in ebpf land and matching implementation in user land.

Based on Event Auditor Implementation

Inspirations

TODO/ToCheck

  1. List out LSM Hooks to be integrated with
  2. Explore Hashing
  3. Analyse Performance Impact
  4. ...

Miscellaneous Notes