Skip to content

Commit 50e07a9

Browse files
committed
Rewrite in Rust
Finally, we are getting rid of C and libbpf here. This PR replaces all the eBPF programs with Rust programs written in Aya. The part of this PR is also: * fetching recent, relevant changes in aya-template * using LpmTrie maps for mount policies (TODO) * detecting new processes only with tracepoints, the task LSM program was removed Fixes: lockc-project#49 Fixes: lockc-project#134 Fixes: lockc-project#137 Fixes: lockc-project#138 Signed-off-by: Michal Rostecki <[email protected]>
1 parent abd4967 commit 50e07a9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+41873
-2299
lines changed

.cargo/config.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
11
[alias]
2-
xtask = "run --package xtask --"
3-
4-
[target.x86_64-unknown-linux-gnu]
5-
runner = "sudo -E"
2+
xtask = "run --package xtask --"

.github/workflows/rust.yml

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,28 +11,34 @@ jobs:
1111
runs-on: ubuntu-latest
1212
steps:
1313
- uses: actions/checkout@v2
14-
- uses: actions/setup-go@v2
14+
- name: Install rustc nightly
15+
uses: actions-rs/toolchain@v1
1516
with:
16-
go-version: "1.17"
17-
- name: Install dapper
18-
run: go install github.com/rancher/dapper@latest
17+
toolchain: nightly
18+
components: rustfmt, clippy, rust-src
19+
- name: Install bpf-linker
20+
run: cargo install bpf-linker
21+
- name: Build eBPF
22+
run: cargo xtask build-ebpf
1923
- name: Build
20-
run: dapper cargo build
24+
run: cargo build
2125
env:
2226
DOCKER_BUILDKIT: 1
2327
COMPOSE_DOCKER_CLI_BUILD: 1
2428
- name: Test
25-
run: dapper cargo test
29+
run: cargo test
2630
env:
2731
DOCKER_BUILDKIT: 1
2832
COMPOSE_DOCKER_CLI_BUILD: 1
2933
- name: Lint
30-
run: dapper cargo clippy -- -D warnings
34+
run: cargo clippy -- -D warnings
3135
env:
3236
DOCKER_BUILDKIT: 1
3337
COMPOSE_DOCKER_CLI_BUILD: 1
38+
- name: Install udeps
39+
run: cargo install udeps
3440
- name: Check unused dependencies
35-
run: dapper cargo +nightly udeps --all-targets
41+
run: cargo udeps --all-targets
3642
env:
3743
DOCKER_BUILDKIT: 1
3844
COMPOSE_DOCKER_CLI_BUILD: 1

.gitignore

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,13 @@
1+
### https://raw.github.com/github/gitignore/master/Rust.gitignore
2+
13
# Generated by Cargo
24
# will have compiled files and executables
3-
**/debug/
4-
**/target/
5+
debug/
6+
target/
57

68
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
79
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
810
Cargo.lock
911

1012
# These are backup files generated by rustfmt
1113
**/*.rs.bk
12-
13-
# BTF headers
14-
**/vmlinux.h
15-
16-
# Output (BPF)
17-
**/.output/
18-
19-
# Misc
20-
**/*~
21-
22-
# mdBook output
23-
**/docs/book/
24-
25-
# IDE
26-
.idea
27-
28-
# Dapper
29-
Dockerfile.dapper*

.vim/coc-settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rust-analyzer.linkedProjects": ["Cargo.toml", "lockc-ebpf/Cargo.toml"]
3+
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rust-analyzer.linkedProjects": ["Cargo.toml", "lockc-ebpf/Cargo.toml"]
3+
}

Cargo.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,2 @@
11
[workspace]
2-
members = [
3-
"lockc",
4-
"xtask",
5-
]
2+
members = ["lockc", "lockc-common", "xtask"]

README.md

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,28 @@
1-
![lockc](https://raw.githubusercontent.com/lockc-project/assets/main/logo-horizontal-lockc.png)
1+
# lockc
22

3-
[![Crate](https://img.shields.io/crates/v/lockc)](https://crates.io/crates/lockc)
4-
[![Book](https://img.shields.io/website?url=https%3A%2F%2Flockc-project.github.io%2Flockc%2F)](https://lockc-project.github.io/lockc/)
5-
[![Discord](https://img.shields.io/discord/874314181191565453?label=discord&logo=discord)](https://discord.gg/799cmsYB4q)
6-
[![Docs](https://docs.rs/lockc/badge.svg)](https://docs.rs/lockc/)
7-
[![Build Status](https://github.com/lockc-project/lockc/actions/workflows/rust.yml/badge.svg)](https://github.com/lockc-project/lockc/actions/workflows/rust.yml)
3+
## Prerequisites
84

9-
**lockc** is open source sofware for providing MAC (Mandatory Access Control)
10-
type of security audit for container workloads.
5+
1. Install a rust stable toolchain: `rustup install stable`
6+
1. Install a rust nightly toolchain: `rustup install nightly`
7+
1. Install bpf-linker: `cargo install bpf-linker`
118

12-
The main reason why **lockc** exists is that **containers do not contain**.
13-
Containers are not as secure and isolated as VMs. By default, they expose
14-
a lot of information about host OS and provide ways to "break out" from the
15-
container. **lockc** aims to provide more isolation to containers and make them
16-
more secure.
9+
## Build eBPF
1710

18-
The [Containers do not contain](https://lockc-project.github.io/book/containers-do-not-contain.html)
19-
documentation section explains what we mean by that phrase and what kind of
20-
behavior we want to restrict with **lockc**.
11+
```bash
12+
cargo xtask build-ebpf
13+
```
2114

22-
The main technology behind lockc is [eBPF](https://ebpf.io/) - to be more
23-
precise, its ability to attach to [LSM hooks](https://www.kernel.org/doc/html/latest/bpf/bpf_lsm.html)
15+
To perform a release build you can use the `--release` flag.
16+
You may also change the target architecture with the `--target` flag
2417

25-
Please note that currently lockc is an experimental project, not meant for
26-
production environment and without any official binaries or packages to use -
27-
currently the only way to use it is building from sources.
18+
## Build Userspace
2819

29-
See [the full documentation here](https://lockc-project.github.io/book/).
30-
And [the code documentation here](https://docs.rs/lockc/).
20+
```bash
21+
cargo build
22+
```
3123

32-
If you need help or want to talk with contributors, plese come chat with us
33-
on `#lockc` channel on the [Rust Cloud Native Discord server](https://discord.gg/799cmsYB4q).
24+
## Run
3425

35-
**lockc's** userspace part is licensed under [Apache License, version 2.0](https://github.com/lockc-project/lockc/blob/main/LICENSE).
36-
37-
eBPF programs inside [lockc/src/bpf directory](https://github.com/lockc-project/lockc/tree/main/lockc/src/bpf)
38-
are licensed under [GNU General Public License, version 2](https://github.com/lockc-project/lockc/blob/main/lockc/src/bpf/LICENSE).
26+
```bash
27+
cargo xtask run
28+
```

lockc-common/Cargo.toml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "lockc-common"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[features]
7+
default = []
8+
user = [ "aya", "thiserror" ]
9+
10+
[dependencies]
11+
aya = { version = "0.10", optional = true }
12+
thiserror = { version = "1.0", optional = true }
13+
14+
[lib]
15+
path = "src/lib.rs"

lockc-common/src/lib.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#![cfg_attr(not(feature = "user"), no_std)]
2+
3+
/// Max configurable PID limit (for x86_64, for the other architectures it's
4+
/// less or equal).
5+
// TODO(vadorovsky): I need to teach aya to be able to resize maps before they
6+
// are loaded into the kernel. So far aya doesn't differentiate between open()
7+
// and load(), it opens the ELF object and loads it immediately in one step.
8+
// I need to change it.
9+
// After that, we will be able to set the limit again up to the upper possible
10+
// limit. And resize according to the max PID limit in sysctl.
11+
// Before it's done - let's stick to the default value to not use too much RAM.
12+
// pub const PID_MAX_LIMIT: u32 = 4194304;
13+
pub const PID_MAX_LIMIT: u32 = 32768;
14+
15+
pub const MOUNT_TYPE_LEN: usize = 5;
16+
17+
pub const PATH_LEN: usize = 64;
18+
19+
const CONTAINER_ID_LEN: usize = 64;
20+
21+
#[cfg_attr(feature = "user", derive(Debug))]
22+
#[derive(Copy, Clone)]
23+
#[repr(C)]
24+
pub enum ContainerPolicyLevel {
25+
NotFound = -1,
26+
27+
Lockc,
28+
29+
// Policy levels.
30+
Restricted,
31+
Baseline,
32+
Privileged,
33+
}
34+
35+
#[derive(Copy, Clone)]
36+
#[repr(C)]
37+
pub struct ContainerID {
38+
pub id: [u8; CONTAINER_ID_LEN],
39+
}
40+
41+
#[cfg(feature = "user")]
42+
#[derive(thiserror::Error, Debug)]
43+
pub enum NewContainerIDError {
44+
#[error(transparent)]
45+
NulError(#[from] std::ffi::NulError),
46+
47+
#[error("could not convert Vec<u8> to CString")]
48+
VecU8CStringConv,
49+
}
50+
51+
#[cfg(feature = "user")]
52+
impl ContainerID {
53+
/// Creates a new container_id instance and converts the given Rust string
54+
/// into C fixed size char array.
55+
pub fn new(id: &str) -> Result<Self, NewContainerIDError> {
56+
let mut id_b = std::ffi::CString::new(id)?.into_bytes_with_nul();
57+
id_b.resize(CONTAINER_ID_LEN, 0);
58+
Ok(ContainerID {
59+
id: id_b
60+
.try_into()
61+
.map_err(|_| NewContainerIDError::VecU8CStringConv)?,
62+
})
63+
}
64+
}
65+
66+
#[derive(Copy, Clone)]
67+
#[repr(C)]
68+
pub struct Container {
69+
pub policy_level: ContainerPolicyLevel,
70+
}
71+
72+
#[derive(Copy, Clone)]
73+
#[repr(C)]
74+
pub struct Process {
75+
pub container_id: ContainerID,
76+
}
77+
78+
#[derive(Copy, Clone)]
79+
#[repr(C)]
80+
pub struct MountType {
81+
pub mount_type: [u8; MOUNT_TYPE_LEN],
82+
}
83+
84+
#[derive(Copy, Clone)]
85+
#[repr(C)]
86+
pub struct ContainerPath {
87+
pub path: [u8; PATH_LEN],
88+
}
89+
90+
#[cfg(feature = "user")]
91+
mod user {
92+
use super::*;
93+
94+
unsafe impl aya::Pod for ContainerID {}
95+
unsafe impl aya::Pod for Container {}
96+
unsafe impl aya::Pod for Process {}
97+
}

lockc-ebpf/.cargo/config.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[build]
2+
target-dir = "../target"
3+
target = "bpfel-unknown-none"
4+
5+
[unstable]
6+
build-std = ["core"]

lockc-ebpf/.vim/coc-settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"rust-analyzer.cargo.target": "bpfel-unknown-none",
3+
"rust-analyzer.checkOnSave.allTargets": false
4+
}

lockc-ebpf/.vscode/settings.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"rust-analyzer.cargo.target": "bpfel-unknown-none",
3+
"rust-analyzer.checkOnSave.allTargets": false,
4+
}

lockc-ebpf/Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "lockc-ebpf"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
aya-bpf = { git = "https://github.com/aya-rs/aya", branch = "main" }
8+
aya-log-ebpf = { git = "https://github.com/aya-rs/aya-log", branch = "main" }
9+
lockc-common = { path = "../lockc-common" }
10+
11+
[[bin]]
12+
name = "lockc"
13+
path = "src/main.rs"
14+
15+
[profile.dev]
16+
opt-level = 3
17+
debug = false
18+
debug-assertions = false
19+
overflow-checks = false
20+
lto = true
21+
panic = "abort"
22+
incremental = false
23+
codegen-units = 1
24+
rpath = false
25+
26+
[profile.release]
27+
lto = true
28+
panic = "abort"
29+
codegen-units = 1
30+
31+
[workspace]
32+
members = []

lockc-ebpf/rust-toolchain.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[toolchain]
2+
channel="nightly"

0 commit comments

Comments
 (0)