spank-olm

WIP Do not look
git clone git://archive.git.mtrnord.blog/MTRNord/spank-olm.git
Log | Files | Refs | README | LICENSE

commit 51d5c9b214674b244f90baa88b45c537c05cd2ee
parent 4eff43f8d167afbd4e25ca0d0cc78bc143f17096
Author: MTRNord <mtrnord1@gmail.com>
Date:   Tue,  6 Aug 2024 20:01:16 +0200

Initial fuzzing prep

Diffstat:
A.clusterfuzzlite/Dockerfile | 16++++++++++++++++
A.clusterfuzzlite/build.sh | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
A.clusterfuzzlite/project.yaml | 8++++++++
A.github/workflows/cflite_batch.yml | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A.github/workflows/cflite_pr.yml | 48++++++++++++++++++++++++++++++++++++++++++++++++
Afuzz/meson.build | 45+++++++++++++++++++++++++++++++++++++++++++++
Afuzz/olm_decryption_fuzzer.cpp | 6++++++
Afuzz/test_fuzz.sh | 17+++++++++++++++++
Ainclude/slap-olm.hpp | 2++
Dmain.cpp | 6------
Mmeson.build | 32++++++++++++++++++++++++++++----
Ameson_options.txt | 12++++++++++++
Asrc/slap-olm.cpp | 2++
13 files changed, 295 insertions(+), 10 deletions(-)

diff --git a/.clusterfuzzlite/Dockerfile b/.clusterfuzzlite/Dockerfile @@ -0,0 +1,15 @@ +FROM gcr.io/oss-fuzz-base/base-builder:v1 +RUN apt-get update && apt-get install -y \ + automake \ + autopoint \ + cmake \ + git \ + python3-pip \ + pkg-config +RUN pip3 install meson ninja + +RUN git clone --depth 1 https://github.com/randombit/botan.git +COPY . $SRC/spank-olm + +WORKDIR $SRC/spank-olm +COPY ./.clusterfuzzlite/build.sh $SRC/ +\ No newline at end of file diff --git a/.clusterfuzzlite/build.sh b/.clusterfuzzlite/build.sh @@ -0,0 +1,52 @@ +#!/bin/bash -eu + +export PKG_CONFIG="pkg-config --static" +export PKG_CONFIG_PATH="$WORK/lib/pkgconfig" +export CPPFLAGS="-I$WORK/include" +export LDFLAGS="-L$WORK/lib" + +# Run as many parallel jobs as there are available CPU cores +export MAKEFLAGS="-j$(nproc)" + +# botan +pushd ../botan +./configure.py --prefix="${WORK}" +make +make install +cp build/botan-3.pc "${PKG_CONFIG_PATH}" +popd + +# spank-olm +meson setup build --prefix="${WORK}" --libdir=lib --prefer-static --default-library=static --buildtype=debugoptimized \ + -Dfuzzing_engine=oss-fuzz -Dfuzzer_ldflags="$LIB_FUZZING_ENGINE" \ + -Dcpp_link_args="$LDFLAGS -Wl,-rpath=\$ORIGIN" +meson install -C build --tag devel + +# Copy fuzz executables to $OUT +find build/fuzz -maxdepth 1 -executable -type f -exec cp -v '{}' "${OUT}" \; + +# All shared libraries needed during fuzz target execution should be inside the $OUT/lib directory +mkdir -p "${OUT}" +cp ${WORK}/lib/*.so "${OUT}/lib" + +# TODO: This is from libvips and needs adjusting: + +## Merge the seed corpus in a single directory, exclude files larger than 4k +#mkdir -p fuzz/corpus +#find \ +# $SRC/afl-testcases/{gif*,jpeg*,png,tiff,webp}/full/images \ +# fuzz/*_fuzzer_corpus \ +# test/test-suite/images \ +# -type f -size -4k \ +# -exec bash -c 'hash=($(sha1sum {})); mv {} fuzz/corpus/$hash' \; +#zip -jrq $OUT/seed_corpus.zip fuzz/corpus +# +## Link corpus +#for fuzzer in fuzz/*_fuzzer.cc; do +# target=$(basename "$fuzzer" .cc) +# ln -sf "seed_corpus.zip" "$OUT/${target}_seed_corpus.zip" +#done +# +## Copy options and dictionary files to $OUT +#find fuzz -name '*_fuzzer.dict' -exec cp -v '{}' $OUT \; +#find fuzz -name '*_fuzzer.options' -exec cp -v '{}' $OUT \; +\ No newline at end of file diff --git a/.clusterfuzzlite/project.yaml b/.clusterfuzzlite/project.yaml @@ -0,0 +1,7 @@ +homepage: "https://github.com/MTRNord/spank-olm" +language: c++ +primary_contact: "git@nordgedanken.dev" +main_repo: 'https://github.com/MTRNord/spank-olm' + +fuzzing_engines: + - libfuzzer +\ No newline at end of file diff --git a/.github/workflows/cflite_batch.yml b/.github/workflows/cflite_batch.yml @@ -0,0 +1,58 @@ +name: ClusterFuzzLite batch fuzzing +on: + schedule: + - cron: '0 0 * * *' # Every 6th hour. Change this to whatever is suitable. +permissions: read-all +jobs: + BatchFuzzing: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sanitizer: + - address + - undefined + - memory + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: c++ + sanitizer: ${{ matrix.sanitizer }} + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 3600 + mode: 'batch' + sanitizer: ${{ matrix.sanitizer }} + output-sarif: true + # Optional but recommended: For storing certain artifacts from fuzzing. + # See later section on "Git repo for storage". + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + Coverage: + runs-on: ubuntu-latest + steps: + - name: Build Fuzzers + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: c++ + sanitizer: coverage + - name: Run Fuzzers + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 600 + mode: 'coverage' + sanitizer: 'coverage' + # Optional but recommended. + # See later section on "Git repo for storage". + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". diff --git a/.github/workflows/cflite_pr.yml b/.github/workflows/cflite_pr.yml @@ -0,0 +1,48 @@ +name: ClusterFuzzLite PR fuzzing +on: + pull_request: + paths: + - '**' +permissions: read-all +jobs: + PR: + runs-on: ubuntu-latest + concurrency: + group: ${{ github.workflow }}-${{ matrix.sanitizer }}-${{ github.ref }} + cancel-in-progress: true + strategy: + fail-fast: false + matrix: + sanitizer: + - address + - undefined + - memory + steps: + - name: Build Fuzzers (${{ matrix.sanitizer }}) + id: build + uses: google/clusterfuzzlite/actions/build_fuzzers@v1 + with: + language: c++ + github-token: ${{ secrets.GITHUB_TOKEN }} + sanitizer: ${{ matrix.sanitizer }} + # Optional but recommended: used to only run fuzzers that are affected + # by the PR. + # See later section on "Git repo for storage". + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". + - name: Run Fuzzers (${{ matrix.sanitizer }}) + id: run + uses: google/clusterfuzzlite/actions/run_fuzzers@v1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + fuzz-seconds: 600 + mode: 'code-change' + sanitizer: ${{ matrix.sanitizer }} + output-sarif: true + # Optional but recommended: used to download the corpus produced by + # batch fuzzing. + # See later section on "Git repo for storage". + # storage-repo: https://${{ secrets.PERSONAL_ACCESS_TOKEN }}@github.com/OWNER/STORAGE-REPO-NAME.git + # storage-repo-branch: main # Optional. Defaults to "main" + # storage-repo-branch-coverage: gh-pages # Optional. Defaults to "gh-pages". diff --git a/fuzz/meson.build b/fuzz/meson.build @@ -0,0 +1,44 @@ +fuzz_deps = spank_olm_deps +fuzz_ldflags = [] + +if get_option('fuzzer_ldflags') != '' + fuzz_ldflags += [get_option('fuzzer_ldflags')] +endif + +if fuzzing_engine == 'libfuzzer' + fuzz_ldflags += ['-fsanitize=fuzzer'] +endif + +fuzz_progs = [ + 'olm_decryption_fuzzer' +] + +fuzz_execs = [] +foreach fuzz_prog : fuzz_progs + fuzz_execs += executable(fuzz_prog, + fuzz_prog + '.cpp', + dependencies: [spank_olm_dep, fuzz_deps], + link_args: fuzz_ldflags + ) +endforeach + +# If the fuzzing engine is not OSS-Fuzz, build the unit tests to be run on CI +if fuzzing_engine != 'oss-fuzz' + test_fuzz = configure_file( + input: 'test_fuzz.sh', + output: 'test_fuzz.sh', + copy: true, + ) + + test( + 'fuzz', + test_fuzz, + workdir: meson.current_build_dir(), + depends: [ + fuzz_execs, + ], + # Increase the timeout as running the tests with sanitizers + # enabled could be slower than the default 30 seconds. + timeout: 60, + ) +endif +\ No newline at end of file diff --git a/fuzz/olm_decryption_fuzzer.cpp b/fuzz/olm_decryption_fuzzer.cpp @@ -0,0 +1,5 @@ +#include <cstdint> +#include <cstddef> +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + return 0; +} +\ No newline at end of file diff --git a/fuzz/test_fuzz.sh b/fuzz/test_fuzz.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +ret=0 + +for fuzzer in *_fuzzer; do + exit_code=0 + "./${fuzzer}" || exit_code=$? + if [ $exit_code -ne 0 ]; then + echo FAIL "${fuzzer}" + ret=1 + fi +done + +exit $ret +\ No newline at end of file diff --git a/include/slap-olm.hpp b/include/slap-olm.hpp @@ -0,0 +1 @@ +#pragma once +\ No newline at end of file diff --git a/main.cpp b/main.cpp @@ -1,6 +0,0 @@ -#include <iostream> - -int main() { - std::cout << "Hello, World!" << std::endl; - return 0; -} diff --git a/meson.build b/meson.build @@ -3,10 +3,34 @@ project('spank-olm', 'cpp', default_options : ['warning_level=3', 'cpp_std=c++23', 'b_lto=true', - 'b_thinlto_cache=true']) + 'b_thinlto_cache=true', + 'warning_level=3',]) -spank_olm = executable('spank_olm', 'main.cpp', install : true) +# libFuzzer related things +fuzzing_engine = get_option('fuzzing_engine') +if fuzzing_engine == 'libfuzzer' + if not cc.has_argument('-fsanitize=fuzzer') + error('fuzzing_engine libfuzzer requires "-fsanitize=fuzzer"') + endif + fuzzer_args = ['-fsanitize=fuzzer-no-link', '-fsanitize=fuzzer'] + add_project_arguments(cc.first_supported_argument(fuzzer_args), language : ['cpp', 'c']) +endif + +# Cmake doesnt work with meson, so we need to require pkg-config +botan_dep = dependency('botan-3', version : '>=3.6.0', required : true, method : 'pkg-config') + +spank_olm_deps = [botan_dep] + +incdir = include_directories('include') +spank_olm = library('spank_olm', 'src/slap-olm.cpp', install : true, dependencies : spank_olm_deps, include_directories : incdir) + +spank_olm_dep = declare_dependency( + link_with: spank_olm, + dependencies: spank_olm_deps, +) snitch_dep = dependency('snitch') -test('test', executable('spank-olm-test','tests/test.cpp',dependencies:snitch_dep)) -\ No newline at end of file +test('test', executable('spank-olm-test','tests/test.cpp',dependencies:snitch_dep, link_with : spank_olm)) + +subdir('fuzz') +\ No newline at end of file diff --git a/meson_options.txt b/meson_options.txt @@ -0,0 +1,11 @@ +# fuzzing options + +option('fuzzing_engine', + type: 'combo', + choices : ['none', 'libfuzzer', 'oss-fuzz'], + value: 'none', + description: 'Select the fuzzing engine') + +option('fuzzer_ldflags', + type: 'string', + description: 'Extra LDFLAGS used during linking of fuzzing binaries') +\ No newline at end of file diff --git a/src/slap-olm.cpp b/src/slap-olm.cpp @@ -0,0 +1 @@ +#include "slap-olm.hpp" +\ No newline at end of file