Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite in Rust #199

Merged
merged 1 commit into from
May 14, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
[alias]
xtask = "run --package xtask --"

[target.x86_64-unknown-linux-gnu]
runner = "sudo -E"
xtask = "run --package xtask --"
22 changes: 14 additions & 8 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,34 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- name: Install rustc nightly
uses: actions-rs/toolchain@v1
with:
go-version: "1.17"
- name: Install dapper
run: go install github.com/rancher/dapper@latest
toolchain: nightly
components: rustfmt, clippy, rust-src
- name: Install bpf-linker
run: cargo install bpf-linker
- name: Build eBPF
run: cargo xtask build-ebpf
- name: Build
run: dapper cargo build
run: cargo build
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
- name: Test
run: dapper cargo test
run: cargo test
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
- name: Lint
run: dapper cargo clippy -- -D warnings
run: cargo clippy -- -D warnings
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
- name: Install udeps
run: cargo install cargo-udeps
- name: Check unused dependencies
run: dapper cargo +nightly udeps --all-targets
run: cargo udeps --all-targets
env:
DOCKER_BUILDKIT: 1
COMPOSE_DOCKER_CLI_BUILD: 1
24 changes: 4 additions & 20 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,29 +1,13 @@
### https://raw.github.com/github/gitignore/master/Rust.gitignore

# Generated by Cargo
# will have compiled files and executables
**/debug/
**/target/
debug/
target/

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

# These are backup files generated by rustfmt
**/*.rs.bk

# BTF headers
**/vmlinux.h

# Output (BPF)
**/.output/

# Misc
**/*~

# mdBook output
**/docs/book/

# IDE
.idea

# Dapper
Dockerfile.dapper*
3 changes: 3 additions & 0 deletions .vim/coc-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rust-analyzer.linkedProjects": ["Cargo.toml", "lockc-ebpf/Cargo.toml"]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rust-analyzer.linkedProjects": ["Cargo.toml", "lockc-ebpf/Cargo.toml"]
}
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[workspace]
members = [
"lockc",
"xtask",
]
members = ["lockc", "lockc-common", "xtask"]

[patch.crates-io]
aya = { git = "https://github.com/aya-rs/aya", branch = "main" }
48 changes: 19 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
![lockc](https://raw.githubusercontent.com/lockc-project/assets/main/logo-horizontal-lockc.png)
# lockc

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

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

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

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

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

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

See [the full documentation here](https://lockc-project.github.io/book/).
And [the code documentation here](https://docs.rs/lockc/).
```bash
cargo build
```

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

**lockc's** userspace part is licensed under [Apache License, version 2.0](https://github.com/lockc-project/lockc/blob/main/LICENSE).

eBPF programs inside [lockc/src/bpf directory](https://github.com/lockc-project/lockc/tree/main/lockc/src/bpf)
are licensed under [GNU General Public License, version 2](https://github.com/lockc-project/lockc/blob/main/lockc/src/bpf/LICENSE).
```bash
cargo xtask run
```
15 changes: 15 additions & 0 deletions lockc-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[package]
name = "lockc-common"
version = "0.1.0"
edition = "2021"

[features]
default = []
user = [ "aya", "thiserror" ]

[dependencies]
aya = { git = "https://github.com/aya-rs/aya", branch = "main", optional = true }
thiserror = { version = "1.0", optional = true }

[lib]
path = "src/lib.rs"
109 changes: 109 additions & 0 deletions lockc-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#![cfg_attr(not(feature = "user"), no_std)]

/// Max configurable PID limit (for x86_64, for the other architectures it's
/// less or equal).
// TODO(vadorovsky): I need to teach aya to be able to resize maps before they
// are loaded into the kernel. So far aya doesn't differentiate between open()
// and load(), it opens the ELF object and loads it immediately in one step.
// I need to change it.
// After that, we will be able to set the limit again up to the upper possible
// limit. And resize according to the max PID limit in sysctl.
// Before it's done - let's stick to the default value to not use too much RAM.
// pub const PID_MAX_LIMIT: u32 = 4194304;
pub const PID_MAX_LIMIT: u32 = 32768;

pub const MOUNT_TYPE_LEN: usize = 5;

pub const PATH_LEN: usize = 64;

const CONTAINER_ID_LEN: usize = 64;

#[cfg_attr(feature = "user", derive(Debug))]
#[derive(Copy, Clone)]
#[repr(C)]
pub enum ContainerPolicyLevel {
NotFound = -1,

Lockc,

// Policy levels.
Restricted,
Baseline,
Privileged,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ContainerID {
pub id: [u8; CONTAINER_ID_LEN],
}

impl ContainerID {
/// Convert container ID to a string.
///
/// # Safety
///
/// Container ID is a fixed-size array which has to be nul terminated.
/// Otherwise this conversion to string is going to fail.
pub unsafe fn as_str(&self) -> &str {
core::str::from_utf8_unchecked(&self.id)
}
}

#[cfg(feature = "user")]
#[derive(thiserror::Error, Debug)]
pub enum NewContainerIDError {
#[error(transparent)]
NulError(#[from] std::ffi::NulError),

#[error("could not convert Vec<u8> to CString")]
VecU8CStringConv,
}

#[cfg(feature = "user")]
impl ContainerID {
/// Creates a new container_id instance and converts the given Rust string
/// into C fixed size char array.
pub fn new(id: &str) -> Result<Self, NewContainerIDError> {
let mut id_b = std::ffi::CString::new(id)?.into_bytes_with_nul();
id_b.resize(CONTAINER_ID_LEN, 0);
Ok(ContainerID {
id: id_b
.try_into()
.map_err(|_| NewContainerIDError::VecU8CStringConv)?,
})
}
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct Container {
pub policy_level: ContainerPolicyLevel,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct Process {
pub container_id: ContainerID,
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct MountType {
pub mount_type: [u8; MOUNT_TYPE_LEN],
}

#[derive(Copy, Clone)]
#[repr(C)]
pub struct ContainerPath {
pub path: [u8; PATH_LEN],
}

#[cfg(feature = "user")]
mod user {
use super::*;

unsafe impl aya::Pod for ContainerID {}
unsafe impl aya::Pod for Container {}
unsafe impl aya::Pod for Process {}
}
6 changes: 6 additions & 0 deletions lockc-ebpf/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build]
target-dir = "../target"
target = "bpfel-unknown-none"

[unstable]
build-std = ["core"]
4 changes: 4 additions & 0 deletions lockc-ebpf/.vim/coc-settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.target": "bpfel-unknown-none",
"rust-analyzer.checkOnSave.allTargets": false
}
4 changes: 4 additions & 0 deletions lockc-ebpf/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.target": "bpfel-unknown-none",
"rust-analyzer.checkOnSave.allTargets": false,
}
33 changes: 33 additions & 0 deletions lockc-ebpf/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[package]
name = "lockc-ebpf"
version = "0.1.0"
edition = "2021"

[dependencies]
aya-bpf = { git = "https://github.com/aya-rs/aya", branch = "main" }
aya-log-ebpf = { git = "https://github.com/aya-rs/aya-log", branch = "main" }
lockc-common = { path = "../lockc-common" }
unroll = "0.1"

[[bin]]
name = "lockc"
path = "src/main.rs"

[profile.dev]
opt-level = 3
debug = false
debug-assertions = false
overflow-checks = false
lto = true
panic = "abort"
incremental = false
codegen-units = 1
rpath = false

[profile.release]
lto = true
panic = "abort"
codegen-units = 1

[workspace]
members = []
2 changes: 2 additions & 0 deletions lockc-ebpf/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[toolchain]
channel="nightly"
Loading