Skip to content

Commit 33b0f96

Browse files
committed
bpf: Fix map pinning
Aya relies on the `pinning` field in BPF map definitions. libbpf doesn't provide that field, so instead of using their bpf_map_def struct, here we define our bpf_elf_map struct which has it. Our structure is similar to those available in Cilium[0] and some selftests in the kernel tree[1]. [0] https://github.com/cilium/cilium/blob/v1.11.1/bpf/include/bpf/loader.h#L19-L29 [1] https://elixir.bootlin.com/linux/v5.16.8/source/samples/bpf/tc_l2_redirect_kern.c#L23 Fixes: #169 Signed-off-by: Michal Rostecki <mrostecki@opensuse.org>
1 parent c36efa8 commit 33b0f96

File tree

4 files changed

+65
-14
lines changed

4 files changed

+65
-14
lines changed

lockc/src/bin/lockcd.rs

-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,6 @@ async fn ebpf(
5656
.join("bpf")
5757
.join("lockc");
5858

59-
std::fs::create_dir_all(&path_base)?;
60-
6159
let mut bpf = load_bpf(&path_base)?;
6260

6361
init_allowed_paths(&mut bpf)?;

lockc/src/bpf/maps.h

+38-8
Original file line numberDiff line numberDiff line change
@@ -4,27 +4,51 @@
44
#include "map_structs.h"
55
#include <bpf/bpf_helpers.h>
66

7+
#define PIN_BY_NAME 1
8+
9+
// NOTE(vadorovsky): The bpf_map_def struct from libbpf doesn't contain the
10+
// `pinning` field. Aya uses it (for pinning maps, obviously). This kind of
11+
// structure is used also in Cilium and even in few selftests in the kernel
12+
// tree[1].
13+
//
14+
// [0] https://github.com/cilium/cilium/blob/v1.11.1/bpf/include/bpf/loader.h#L19-L29
15+
// [1] https://elixir.bootlin.com/linux/v5.16.8/source/samples/bpf/tc_l2_redirect_kern.c#L23
16+
/*
17+
* bpf_elf_map - description of BPF map attributes. Saved in the ELF object.
18+
*/
19+
struct bpf_elf_map {
20+
u32 type;
21+
u32 key_size;
22+
u32 value_size;
23+
u32 max_entries;
24+
u32 flags;
25+
u32 id;
26+
u32 pinning;
27+
};
28+
729
/*
830
* containers - BPF map containing the info about a policy which should be
931
* enforced on the given container.
1032
*/
11-
struct bpf_map_def SEC("maps/containers") containers = {
33+
struct bpf_elf_map SEC("maps/containers") containers = {
1234
.type = BPF_MAP_TYPE_HASH,
1335
.max_entries = PID_MAX_LIMIT,
1436
.key_size = sizeof(struct container_id),
1537
.value_size = sizeof(struct container),
38+
.pinning = PIN_BY_NAME,
1639
};
1740

1841
/*
1942
* processes - BPF map which maps the PID to a container it belongs to. The
2043
* value of this map, which represents the container, is a key of `containers`
2144
* BPF map, so it can be used immediately for lookups in `containers` map.
2245
*/
23-
struct bpf_map_def SEC("maps/processes") processes = {
46+
struct bpf_elf_map SEC("maps/processes") processes = {
2447
.type = BPF_MAP_TYPE_HASH,
2548
.max_entries = PID_MAX_LIMIT,
2649
.key_size = sizeof(pid_t),
2750
.value_size = sizeof(struct process),
51+
.pinning = PIN_BY_NAME,
2852
};
2953

3054
/*
@@ -33,11 +57,12 @@ struct bpf_map_def SEC("maps/processes") processes = {
3357
* paths used by default by container runtimes, not paths mounted with the -v
3458
* option.
3559
*/
36-
struct bpf_map_def SEC("maps/ap_mnt_restr") ap_mnt_restr = {
60+
struct bpf_elf_map SEC("maps/ap_mnt_restr") ap_mnt_restr = {
3761
.type = BPF_MAP_TYPE_HASH,
3862
.max_entries = PATH_MAX_LIMIT,
3963
.key_size = sizeof(u32),
4064
.value_size = sizeof(struct accessed_path),
65+
.pinning = PIN_BY_NAME,
4166
};
4267

4368
/*
@@ -46,55 +71,60 @@ struct bpf_map_def SEC("maps/ap_mnt_restr") ap_mnt_restr = {
4671
* used by default by container runtimes and paths we allow to mount with -v
4772
* option.
4873
*/
49-
struct bpf_map_def SEC("maps/ap_mnt_base") ap_mnt_base = {
74+
struct bpf_elf_map SEC("maps/ap_mnt_base") ap_mnt_base = {
5075
.type = BPF_MAP_TYPE_HASH,
5176
.max_entries = PATH_MAX_LIMIT,
5277
.key_size = sizeof(u32),
5378
.value_size = sizeof(struct accessed_path),
79+
.pinning = PIN_BY_NAME,
5480
};
5581

5682
/*
5783
* ap_acc_restr - BPF map which contains the path prefixes allowed to access
5884
* (open, create, delete, move etc.) inside filesystems of restricted
5985
* containers.
6086
*/
61-
struct bpf_map_def SEC("maps/ap_acc_restr") ap_acc_restr = {
87+
struct bpf_elf_map SEC("maps/ap_acc_restr") ap_acc_restr = {
6288
.type = BPF_MAP_TYPE_HASH,
6389
.max_entries = PATH_MAX_LIMIT,
6490
.key_size = sizeof(u32),
6591
.value_size = sizeof(struct accessed_path),
92+
.pinning = PIN_BY_NAME,
6693
};
6794

6895
/*
6996
* ap_acc_base - BPF map which contains the path prefixes allowed to access
7097
* (open, create, delete, move etc.) inside filesystems of baseline containers.
7198
*/
72-
struct bpf_map_def SEC("maps/ap_acc_base") ap_acc_base = {
99+
struct bpf_elf_map SEC("maps/ap_acc_base") ap_acc_base = {
73100
.type = BPF_MAP_TYPE_HASH,
74101
.max_entries = PATH_MAX_LIMIT,
75102
.key_size = sizeof(u32),
76103
.value_size = sizeof(struct accessed_path),
104+
.pinning = PIN_BY_NAME,
77105
};
78106

79107
/*
80108
* dp_acc_restr - BPF map which contains the path prefixes denied to access
81109
* (open, create, delete, move etc.) inside filesystems of restricted
82110
* containers.
83111
*/
84-
struct bpf_map_def SEC("maps/dp_acc_restr") dp_acc_restr = {
112+
struct bpf_elf_map SEC("maps/dp_acc_restr") dp_acc_restr = {
85113
.type = BPF_MAP_TYPE_HASH,
86114
.max_entries = PATH_MAX_LIMIT,
87115
.key_size = sizeof(u32),
88116
.value_size = sizeof(struct accessed_path),
117+
.pinning = PIN_BY_NAME,
89118
};
90119

91120
/*
92121
* dp_acc_base - BPF map which contains the path prefixes denied to access
93122
* (open, create, delete, move etc.) inside filesystems of baseline containers.
94123
*/
95-
struct bpf_map_def SEC("maps/dp_acc_base") dp_acc_base = {
124+
struct bpf_elf_map SEC("maps/dp_acc_base") dp_acc_base = {
96125
.type = BPF_MAP_TYPE_HASH,
97126
.max_entries = PATH_MAX_LIMIT,
98127
.key_size = sizeof(u32),
99128
.value_size = sizeof(struct accessed_path),
129+
.pinning = PIN_BY_NAME,
100130
};

lockc/src/load.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::path::Path;
1+
use std::{io, path::Path};
22

33
use aya::{
44
include_bytes_aligned,
@@ -7,9 +7,20 @@ use aya::{
77
};
88
use thiserror::Error;
99

10+
#[derive(Error, Debug)]
11+
pub enum LoadError {
12+
#[error(transparent)]
13+
IO(#[from] io::Error),
14+
15+
#[error(transparent)]
16+
Bpf(#[from] BpfError),
17+
}
18+
1019
/// Loads BPF programs from the object file built with clang.
11-
pub fn load_bpf<P: AsRef<Path>>(path_base_r: P) -> Result<Bpf, BpfError> {
20+
pub fn load_bpf<P: AsRef<Path>>(path_base_r: P) -> Result<Bpf, LoadError> {
1221
let path_base = path_base_r.as_ref();
22+
std::fs::create_dir_all(&path_base)?;
23+
1324
let data = include_bytes_aligned!(concat!(env!("OUT_DIR"), "/lockc.bpf.o"));
1425
let bpf = BpfLoader::new().map_pin_path(path_base).load(data)?;
1526

lockc/src/maps.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -143,19 +143,31 @@ pub fn add_process(bpf: &mut Bpf, container_id: String, pid: i32) -> Result<(),
143143

144144
#[cfg(test)]
145145
mod tests {
146+
use tempfile::{Builder, TempDir};
147+
146148
use crate::{bpfstructs::container_policy_level_POLICY_LEVEL_BASELINE, load::load_bpf};
147149

148150
use super::*;
149151

152+
fn tmp_path_base() -> TempDir {
153+
Builder::new()
154+
.prefix("lockc-temp")
155+
.rand_bytes(5)
156+
.tempdir_in("/sys/fs/bpf")
157+
.expect("Creating temporary dir in BPFFS failed")
158+
}
159+
150160
#[test]
151161
fn test_init_allowed_paths() {
152-
let mut bpf = load_bpf("/sys/fs/bpf/lockc-test").expect("Loading BPF failed");
162+
let path_base = tmp_path_base();
163+
let mut bpf = load_bpf(path_base).expect("Loading BPF failed");
153164
init_allowed_paths(&mut bpf).expect("Initializing allowed paths failed");
154165
}
155166

156167
#[test]
157168
fn test_add_container() {
158-
let mut bpf = load_bpf("/sys/fs/bpf/lockc-test").expect("Loading BPF failed");
169+
let path_base = tmp_path_base();
170+
let mut bpf = load_bpf(path_base).expect("Loading BPF failed");
159171
add_container(
160172
&mut bpf,
161173
"5833851e673d45fab4d12105bf61c3f4892b2bbf9c12d811db509a4f22475ec9".to_string(),

0 commit comments

Comments
 (0)