1 + ![Deepfence Logo](images/readme/deepfence-logo.png) 2 + 3 + [![GitHub license](https://img.shields.io/github/license/deepfence/ebpfguard)](https://github.com/deepfence/ebpfguard/blob/master/LICENSE) 4 + [![GitHub stars](https://img.shields.io/github/stars/deepfence/ebpfguard)](https://github.com/deepfence/ebpfguard/stargazers) 1 5 [![Workflow Status](https://github.com/deepfence/ebpfguard/workflows/build-test/badge.svg)](https://github.com/deepfence/ebpfguard/actions?query=workflow) 6 + [![GitHub issues](https://img.shields.io/github/issues/deepfence/ebpfguard)](https://github.com/deepfence/ebpfguard/issues) 7 + [![Slack](https://img.shields.io/badge/[email protected] ?logo=slack)](https://join.slack.com/t/deepfence-community/shared_invite/zt-podmzle9-5X~qYx8wMaLt9bGWwkSdgQ) 8 + <h3 align="center"> 9 + <a 10 + href="https://runacap.com/ross-index/annual-2022/" 11 + target="_blank" 12 + rel="noopener" 13 + > 14 + <img 15 + style="width: 260px; height: 56px" 16 + src="https://runacap.com/wp-content/uploads/2023/02/Annual_ROSS_badge_black_2022.svg" 17 + alt="ROSS Index - Fastest Growing Open-Source Startups | Runa Capital" 18 + width="260" 19 + height="56" 20 + /> 21 + </a> 22 + </h3> 2 23 3 - # ebpfguard 24 + # Ebpfguard 4 25 5 26 **Ebpfguard** is a library for managing Linux security policies. It is based on 6 27 [LSM hooks](https://www.kernel.org/doc/html/latest/admin-guide/LSM/index.html), skipped 4 lines 11 32 the need to use them directly. 12 33 13 34 ## Prerequisites 35 + 36 + ### kernel capabilities 14 37 15 38 First, you need to have a Linux kernel: 16 39 * with BTF support skipped 16 lines 33 56 34 57 If the output doesn't contain `bpf`, you need to enable BPF LSM by adding 35 58 `lsm=[...],bpf` to your kernel config parameters. That can be achieved by 36 - executing the [following script](https://raw.githubusercontent.com/vadorovsky/enable-bpf-lsm/main/enable-bpf-lsm.py). 59 + executing the [enable-bpf-lsm.py](https://github.com/deepfence/ebpfguard/blob/main/enable-bpf-lsm.py.py) script. 37 60 38 - Then you need the Rust stable and nightly toolchains installed on your system, 39 - as well as bpf-linker. You can install these by following these 40 - [instructions](https://aya-rs.dev/book/start/development/). 61 + This script will print modified contents of `/etc/default/grub` file to stdout. 62 + Either pipe it back directly to `/etc/default/grub` or save it somewhere 63 + and compare contents before swapping to a new version. 41 64 42 - ## LSM hooks 43 - 44 - LSM hooks supported by Ebpfguard are: 65 + Whole command with direct pipe: 45 66 46 - * [`bprm_check_security`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L62) 47 - * [`file_open`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L620) 48 - * [`sb_mount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L128) 49 - * [`sb_remount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L147) 50 - * [`sb_umount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L159) 51 - * [`socket_bind`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L904) 52 - * [`socket_connect`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L912) 53 - * [`task_fix_setuid`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L709) 67 + ```bash 68 + $ ./enable-bpf.lsm.py | sudo tee /etc/default/grub 1>/dev/null 69 + ``` 54 70 55 - ## Examples 71 + This file is used by grub2 to assemble final `grub.cfg`. To trigger reconfiguration 72 + use grub's mkconfig command with `-o <path to grub.cfg>` switch. 56 73 57 - ### Defining single policies 74 + Both command name and path to `grub.cfg` are distribution dependent. 58 75 59 - #### `file_open` 76 + On ubuntu: 60 77 61 - The [file_open](https://github.com/deepfence/ebpfguard/tree/main/examples/file_open) 62 - example shows how to define a policy for `file_open` LSM hook as Rust code. 63 - It denies the given binary (or all processes, if none defined) from opening 64 - the given directory. 78 + ``` 79 + $ sudo grub-mkconfig -o /boot/grub/grub.cfg 80 + ``` 65 81 66 - To try it out, let's create a directory and a file inside it: 82 + On fedora: 67 83 68 - ```bash 69 - $ mkdir /tmp/test 70 - $ echo "foo" > /tmp/test/test 84 + ``` 85 + $ sudo grub2-mkconfig -o /boot/grub2/grub.cfg 71 86 ``` 72 87 73 - Then run our example policy program with: 88 + After that's done reboot your system. 89 + 90 + ### rust toolchain and packages 74 91 75 - ```bash 76 - $ RUST_LOG=info cargo xtask run --example file_open -- --path-to-deny /tmp/test 77 - ``` 92 + You need the Rust stable and nightly toolchains installed on your system, bpf-linker and bpftool binary. 78 93 79 - When trying to access that directory and file, you should see that these 80 - operations are denied: 94 + Install nightly toolchain: 81 95 82 - ```bash 83 - $ ls /tmp/test/ 84 - ls: cannot open directory '/tmp/test/': Operation not permitted 85 - $ cat /tmp/test/test 86 - cat: /tmp/test/test: Operation not permitted 96 + ``` 97 + $ rustup toolchain install nightly --component rust-src 87 98 ``` 88 99 89 - The policy application should show logs like: 100 + Optionally add miri: 90 101 91 - ```bash 92 - [2023-04-22T20:51:01Z INFO file_open] file_open: pid=3001 subject=980333 path=9632 93 - [2023-04-22T20:51:03Z INFO file_open] file_open: pid=3010 subject=980298 path=9633 94 102 ``` 95 - #### mount 96 - 97 - The [mount](https://github.com/deepfence/ebpfguard/tree/main/examples/file_open) 98 - example shows how to define a policy for `sb_mount`, `sb_remount` and 99 - `sb_umount` LSM hooks as Rust code. It denies the mount operations for all 100 - processes except for the optionally given one. 103 + $ rustup component add miri --toolchain nightly 104 + ``` 101 105 102 - To try it out, let's create two directories: 106 + Finally install bpf-linker: 103 107 104 - ```bash 105 - $ mkdir /tmp/test1 106 - $ mkdir /tmp/test2 108 + ``` 109 + $ cargo install bpf-linker 107 110 ``` 108 111 109 - Then run our example policy program, first without providing any binary to 110 - allow mount for (so it's denied for all processes): 112 + This bpf-linker installation method works on linux x86_64 systems. 113 + For others refer to [aya-rs documentation](https://aya-rs.dev/book/start/development/). 111 114 112 - ```bash 113 - $ RUST_LOG=info cargo xtask run --example mount 114 - ``` 115 + To install bpftool either use distro provided package or build it from [source](https://github.com/libbpf/bpftool). 115 116 116 - Let's try to bind mount the first directory to the second one. It should 117 - fail with the following error: 117 + On ubuntu it is a part of linux-tools: 118 118 119 - ```bash 120 - sudo mount --bind /tmp/test1 /tmp/test2 121 - mount: /tmp/test2: permission denied. 122 - dmesg(1) may have more information after failed mount system call. 119 + ``` 120 + $ sudo apt install linux-tools-$(uname -r) 123 121 ``` 124 122 125 - And the policy program should show a log like: 123 + ## Development 124 + 125 + All commands should be executed from repository/workspace root folder unless noted otherwise. 126 126 127 - ```bash 128 - [2023-04-23T21:02:58Z INFO mount] sb_mount: pid=17363 subject=678150 129 - ``` 127 + ### Compilation 130 128 131 - Now let's try to allow mount operations for the mount binary: 129 + First compile ebpf bytecode with the following command. It will be embedded 130 + in userspace binary using aya. 132 131 133 - ```bash 134 - $ RUST_LOG=info cargo xtask run --example mount -- --allow /usr/bin/mount 132 + ``` 133 + $ cargo xtask build-ebpf 135 134 ``` 136 135 137 - And try to bind mount the first directory to the second one again. It should 138 - succeed this time: 136 + Then userspace code. 139 137 140 - ```bash 141 - $ sudo mount --bind /tmp/test1 /tmp/test2 142 - $ mount | grep test 143 - tmpfs on /tmp/test2 type tmpfs (rw,nosuid,nodev,seclabel,nr_inodes=1048576,inode64) 138 + ``` 139 + $ cargo build 144 140 ``` 145 141 146 - #### `task_fix_setuid` 142 + ### Tests 147 143 148 - The [task_fix_setuid](https://github.com/deepfence/ebpfguard/tree/main/examples/task_fix_setuid) 149 - example shows how to define a policy for `task_fix_setuid` LSM hook as Rust 150 - code. It denies the `setuid` operation for all processes except for the 151 - optionally given one. 144 + Commands in this subsection mirror state of CI pipeline. 152 145 153 - To try it out, run our example policy program, first without providing any 154 - binary to allow `setuid` for (so it's denied for all processes): 146 + Regular tests 155 147 156 - ```bash 157 - $ RUST_LOG=info cargo xtask run --example task_fix_setuid 148 + ``` 149 + $ cargo test 158 150 ``` 159 151 160 - Then try to use `sudo`. It should fail with the following error: 152 + Formatting gateway. Drop check subflag to autoformat. 161 153 162 - ```bash 163 - sudo -i 164 - sudo: PERM_ROOT: setresuid(0, -1, -1): Operation not permitted 165 - sudo: error initializing audit plugin sudoers_audit 154 + ``` 155 + $ cargo fmt --all -- --check 166 156 ``` 167 157 168 - And the policy program should show log like: 158 + Clippy lints. 169 159 170 - ```bash 171 - [2023-04-23T15:15:00Z INFO task_fix_setuid] file_open: pid=25604 subject=674642 old_uid=1000 old_gid=1000 new_uid=0 new_gid=1000 160 + ``` 161 + $ cargo clippy --workspace -- --deny warnings 172 162 ``` 173 163 174 - Now, let's try to allow `setuid` for a specific binary. Let's use `sudo`: 164 + Miri verification. 175 165 176 - ```bash 177 - $ RUST_LOG=info cargo xtask run --example task_fix_setuid -- --allow /usr/bin/sudo 166 + ``` 167 + $ cargo +nightly miri test --all-targets 178 168 ``` 179 169 180 - Then try to use `sudo` again. It should work this time: 170 + Note that miri verification requires nightly toolchain as well as miri component. To add them execute: 181 171 182 - ```bash 183 - $ sudo -i 184 - # whoami 185 - root 172 + ``` 173 + $ rustup toolchain install nightly --component rust-src 174 + $ rustup component add miri --toolchain nightly 186 175 ``` 187 176 188 - ### Daemon with CLI and YAML engine 177 + ## LSM hooks 189 178 190 - Run the daemon with: 179 + LSM hooks supported by Ebpfguard are: 191 180 192 - ```bash 193 - $ RUST_LOG=info cargo xtask run --example daemon 194 - ``` 181 + * [`bprm_check_security`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L62) 182 + * [`file_open`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L620) 183 + * [`sb_mount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L128) 184 + * [`sb_remount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L147) 185 + * [`sb_umount`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L159) 186 + * [`socket_bind`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L904) 187 + * [`socket_connect`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L912) 188 + * [`task_fix_setuid`](https://elixir.bootlin.com/linux/v6.2.12/source/include/linux/lsm_hooks.h#L709) 195 189 196 - Then manage the policies using the CLI: 190 + ## Examples 197 191 198 - ```bash 199 - $ cargo xtask run --example cli -- --help 200 - ``` 192 + For usage examples check [EXAMPLES.md](EXAMPLES.md). 201 193 202 - You can apply policies from the 203 - [example YAML file](https://github.com/deepfence/ebpfguard/blob/main/examples/cli/policy.yaml): 194 + ## Get in touch 204 195 205 - ```bash 206 - $ cargo xtask run --example cli -- policy add --path examples/cli/policy.yaml 207 - ``` 196 + Thank you for using Ebpfguard. Please feel welcome to participate in the [Deepfence community](COMMUNITY.md). 197 + 198 + * [Deepfence Community Website](https://community.deepfence.io) 199 + * [<img src="https://img.shields.io/badge/[email protected] ?logo=slack">](https://join.slack.com/t/deepfence-community/shared_invite/zt-podmzle9-5X~qYx8wMaLt9bGWwkSdgQ) Got a question, need some help? Find the Deepfence team on Slack 200 + * [![GitHub issues](https://img.shields.io/github/issues/deepfence/ebpfguard)](https://github.com/deepfence/ebpfguard/issues) Got a feature request or found a bug? Raise an issue 201 + <!-- * [![Documentation](https://img.shields.io/badge/documentation-read-green)](https://community.deepfence.io/docs/ebpfguard/) Read the documentation in the [Deepfence Ebpfguard Documentation](https://community.deepfence.io/docs/ebpfguard/) --> 202 + <!-- * [productsecurity at deepfence dot io](SECURITY.md): Found a security issue? Share it in confidence --> 203 + * Find out more at [deepfence.io](https://deepfence.io/) 208 204 209 205 ## License 210 206 skipped 2 lines 213 209 214 210 eBPF programs inside ebpfguard-ebpf directory are licensed under 215 211 [GNU General Public License, version 2](https://github.com/deepfence/ebpfguard/blob/main/ebpfguard-ebpf/LICENSE). 212 +