Skip to content

Commit

Permalink
Merge pull request #20 from blooo-io/ci/LDG-592-cicd-enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
n4l5u0r authored Nov 30, 2024
2 parents 4180b18 + e032fb2 commit e0518aa
Show file tree
Hide file tree
Showing 681 changed files with 1,029 additions and 118 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ SortIncludes: false
SpaceAfterCStyleCast: true
AllowShortCaseLabelsOnASingleLine: false
AllowAllArgumentsOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: None
BinPackArguments: false
BinPackParameters: false
---

14 changes: 14 additions & 0 deletions .clusterfuzzlite/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-lite:latest AS LITE_BUILDER

# Base image with clang toolchain
FROM gcr.io/oss-fuzz-base/base-builder:v1

# Copy the project's source code.
COPY . $SRC/app-plugin-paraswap
COPY --from=LITE_BUILDER /opt/nanox-secure-sdk $SRC/app-plugin-paraswap/BOLOS_SDK

# Working directory for build.sh
WORKDIR $SRC/app-plugin-paraswap

# Copy build.sh into $SRC dir.
COPY ./.clusterfuzzlite/build.sh $SRC/
9 changes: 9 additions & 0 deletions .clusterfuzzlite/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash -eu

# build fuzzers

pushd fuzzing
cmake -DBOLOS_SDK=../BOLOS_SDK -Bbuild -H.
make -C build
mv ./build/fuzz "${OUT}"
popd
1 change: 1 addition & 0 deletions .clusterfuzzlite/project.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
language: c
41 changes: 41 additions & 0 deletions .github/workflows/cflite_cron.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: ClusterFuzzLite cron tasks
on:
workflow_dispatch:
push:
branches:
- main # Use your actual default branch here.
schedule:
- cron: '0 13 * * 6' # At 01:00 PM, only on Saturday
permissions: read-all
jobs:
Fuzzing:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- mode: batch
sanitizer: address
- mode: batch
sanitizer: memory
- mode: prune
sanitizer: address
- mode: coverage
sanitizer: coverage
steps:
- name: Build Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
language: c # Change this to the language you are fuzzing.
sanitizer: ${{ matrix.sanitizer }}
- name: Run Fuzzers (${{ matrix.mode }} - ${{ matrix.sanitizer }})
id: run
uses: google/clusterfuzzlite/actions/run_fuzzers@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
fuzz-seconds: 300 # 5 minutes
mode: ${{ matrix.mode }}
sanitizer: ${{ matrix.sanitizer }}

43 changes: 43 additions & 0 deletions .github/workflows/cflite_pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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] # Override this with the sanitizers you want.
steps:
- name: Build Fuzzers (${{ matrix.sanitizer }})
id: build
uses: google/clusterfuzzlite/actions/build_fuzzers@v1
with:
language: c # Change this to the language you are fuzzing.
github-token: ${{ secrets.GITHUB_TOKEN }}
sanitizer: ${{ matrix.sanitizer }}
# Optional but recommended: used to only run fuzzers that are affected
# by the PR.
# 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: 300 # 5 minutes
mode: 'code-change'
sanitizer: ${{ matrix.sanitizer }}
output-sarif: true
# Optional but recommended: used to download the corpus produced by
# batch fuzzing.
# 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".
17 changes: 4 additions & 13 deletions .github/workflows/lint-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,7 @@ on:

jobs:
job_lint:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Clone
uses: actions/checkout@v3

- name: Lint
uses: DoozyX/[email protected]
with:
source: "./"
extensions: "h,c"
clangFormatVersion: 12.0.1
name: Check linting using the reusable workflow
uses: LedgerHQ/ledger-app-workflows/.github/workflows/reusable_lint.yml@v1
with:
source: "./src"
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ bin/
debug/
dep/
obj/
tests/elfs/
tests/elfs/*
build/

# Editors
Expand Down
121 changes: 121 additions & 0 deletions fuzzing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
cmake_minimum_required(VERSION 3.10)

if(${CMAKE_VERSION} VERSION_LESS 3.10)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()

# project information
project(Fuzzer
VERSION 1.0
DESCRIPTION "Contract parser of Paraswap plugin app"
LANGUAGES C)

# guard against bad build-type strings
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()

if (NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
message(FATAL_ERROR "Fuzzer needs to be built with Clang")
endif()

if (NOT DEFINED BOLOS_SDK)
message(FATAL_ERROR "BOLOS_SDK environment variable not found.")
endif()

# guard against in-source builds
if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt. ")
endif()

# specify C standard
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED True)

# compatible with ClusterFuzzLite
if (NOT DEFINED ENV{LIB_FUZZING_ENGINE})
set(COMPILATION_FLAGS_ "-fsanitize=fuzzer,address,undefined,signed-integer-overflow")
else()
set(COMPILATION_FLAGS_ "$ENV{LIB_FUZZING_ENGINE} $ENV{CFLAGS}")
endif()
string(REPLACE " " ";" COMPILATION_FLAGS ${COMPILATION_FLAGS_})

add_compile_options(-Wall -Wextra -g -pedantic)
# Just to limit compilation warnings of the plugin sources
add_compile_options(-Wno-implicit-function-declaration)
# Flag depending on the Build Type
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ggdb2 -O3")

set(SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../src")
set(ETH_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../ethereum-plugin-sdk")

add_compile_definitions(
APPNAME="Paraswap"
)

add_compile_definitions(
IO_HID_EP_LENGTH=64
HAVE_ECC
HAVE_ECC_WEIERSTRASS
HAVE_SECP_CURVES
HAVE_ECC_TWISTED_EDWARDS
HAVE_ED_CURVES
HAVE_ECDSA
HAVE_EDDSA
HAVE_HASH
HAVE_BLAKE2
HAVE_SHA224
HAVE_SHA256
HAVE_SHA3
HAVE_SHA512
)

include_directories(
${BOLOS_SDK}/include
${BOLOS_SDK}/lib_standard_app
${BOLOS_SDK}/lib_cxng/include
${BOLOS_SDK}/lib_cxng/src
${BOLOS_SDK}/target/nanox/include
${ETH_DIR}/src
${SRC_DIR}
)

# Take all source files from the application and the sdk
file(GLOB_RECURSE APPLICATION_SRC
# Take all plugin sources
${SRC_DIR}/*.c

# Take all sdk sources
${ETH_DIR}/src/*.c
)
# Filter out main.c from the SDK and the entire dbg folder
list(FILTER APPLICATION_SRC EXCLUDE REGEX "${ETH_DIR}/src/main|${SRC_DIR}/dbg/")

add_executable(fuzz
${APPLICATION_SRC}

# fuzzing specific files
fuzz_plugin.c
mocks.c

# sdk utils
${BOLOS_SDK}/src/ledger_assert.c
${BOLOS_SDK}/lib_standard_app/format.c

# cxng
${BOLOS_SDK}/lib_cxng/src/cx_hash.c
${BOLOS_SDK}/lib_cxng/src/cx_sha256.c
${BOLOS_SDK}/lib_cxng/src/cx_sha512.c
${BOLOS_SDK}/lib_cxng/src/cx_sha3.c
${BOLOS_SDK}/lib_cxng/src/cx_blake2b.c
${BOLOS_SDK}/lib_cxng/src/cx_utils.c
${BOLOS_SDK}/lib_cxng/src/cx_ram.c
)

target_compile_options(fuzz PUBLIC ${COMPILATION_FLAGS})
target_link_options(fuzz PUBLIC ${COMPILATION_FLAGS})

if (CMAKE_C_COMPILER_ID MATCHES "Clang")
add_compile_options(-gdwarf-4)
endif()
87 changes: 87 additions & 0 deletions fuzzing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Fuzzing on transaction parser

[//]: # (Comment)
[//]: # (This file when in the plugin-boilerplate repository is included in the Ethereum Plugin SDK Github page, keep that in mind when editing it.)

Fuzzing allows us to test how a program behaves when provided with invalid, unexpected, or random data as input.

In the case of `app-plugin-boilerplate` we want to test the code that is responsible for handling the contract data.
The fuzzer needs to implement `int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)`, which provides an array of random bytes that can be used to simulate a serialized transaction.
If the application crashes, or a [sanitizer](https://github.com/google/sanitizers) detects any kind of access violation, the fuzzing process is stopped, a report regarding the vulnerability is shown, and the input that triggered the bug is written to disk under the name `crash-*`. The vulnerable input file created can be passed as an argument to the fuzzer to triage the issue.

> **Note**: Usually we want to write a separate fuzz target for each functionality.
## Manual usage based on Ledger container

### Preparation

Before being able to use the fuzzing tests, the environment must be prepared with all submodules.
To install them, use the following command in the repository root directory:

```shell
git submodule update --init
```

The fuzzer can run from the docker `ledger-app-builder-legacy`. You can download it from the `ghcr.io` docker repository:

```shell
sudo docker pull ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest
```

You can then enter this development environment by executing the following command from the repository root directory:

```shell
sudo docker run --rm -ti --user "$(id -u):$(id -g)" -v "$(realpath .):/app" ghcr.io/ledgerhq/ledger-app-builder/ledger-app-builder-legacy:latest
```

### Compilation

Once in the container, go into the `fuzzing` folder to compile the fuzzer:

```shell
cd fuzzing

# cmake initialization
cmake -DBOLOS_SDK=/opt/nanox-secure-sdk -DCMAKE_C_COMPILER=/usr/bin/clang -Bbuild -H.

# Fuzzer compilation
make -C build
```

### Run

```shell
./build/fuzz
```

## Full usage based on `clusterfuzzlite` container

Exactly the same context as the CI, directly using the `clusterfuzzlite` environment.

More info can be found here:
<https://google.github.io/clusterfuzzlite/>

### Preparation

The principle is to build the container, and run it to perform the fuzzing.

> **Note**: The container contains a copy of the sources (they are not cloned), which means the `docker build` command must be re-executed after each code modification.
```shell
# Prepare directory tree
mkdir fuzzing/{corpus,out}
# Container generation
docker build -t app-plugin-boilerplate --file .clusterfuzzlite/Dockerfile .
```

### Compilation

```shell
docker run --rm --privileged -e FUZZING_LANGUAGE=c -v "$(realpath .)/fuzzing/out:/out" -ti app-plugin-boilerplate
```

### Run

```shell
docker run --rm --privileged -e FUZZING_ENGINE=libfuzzer -e RUN_FUZZER_MODE=interactive -v "$(realpath .)/fuzzing/corpus:/tmp/fuzz_corpus" -v "$(realpath .)/fuzzing/out:/out" -ti gcr.io/oss-fuzz-base/base-runner run_fuzzer fuzz
```
Loading

0 comments on commit e0518aa

Please sign in to comment.