Skip to content

Commit

Permalink
Mayhem support
Browse files Browse the repository at this point in the history
  • Loading branch information
mayhem-bot authored and ForAllSecure Mayhem Bot committed Aug 24, 2024
1 parent 23e35d7 commit ce751f4
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 0 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/fuzz_db-mayhem.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Mayhem
on:
push:
pull_request:
workflow_dispatch:
workflow_call:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
name: ${{ matrix.os }} shared=${{ matrix.shared }} ${{ matrix.build_type }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
shared: [false]
build_type: [Release]
include:
- os: ubuntu-latest
triplet: x64-linux
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: .
file: mayhem/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Start analysis
uses: forallsecure/mcode-action@v1
with:
mayhem-token: ${{ secrets.MAYHEM_TOKEN }}
args: --image ${{ steps.meta.outputs.tags }} --cmd /out/fuzz_db --target fuzz_db
--file mayhem/fuzz_db.mayhemfile
sarif-output: sarif
- name: Upload SARIF file(s)
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: sarif
30 changes: 30 additions & 0 deletions mayhem/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Copyright 2020 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################

FROM gcr.io/oss-fuzz-base/base-builder
RUN apt-get update && apt-get install -y make autoconf automake libtool gettext pkg-config build-essential
COPY . leveldb
RUN rm -rf leveldb/mayhem

WORKDIR $SRC/

# Copy in our files
COPY mayhem/build.sh $SRC/
COPY mayhem/*.cc $SRC/leveldb/
COPY mayhem/*.options $SRC/

ENV FUZZING_LANGUAGE=c++ SANITIZER=address
RUN compile
Empty file added mayhem/Dockerfile.dockerignore
Empty file.
35 changes: 35 additions & 0 deletions mayhem/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash -eu
# Copyright 2020 Google Inc.
# Copyright 2020 Luca Boccassi <[email protected]>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
################################################################################

cd $SRC/leveldb
mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release -DLEVELDB_BUILD_TESTS=0 \
-DLEVELDB_BUILD_BENCHMARKS=0 .. && cmake --build .

for fuzzer in fuzz_db; do
# Compile
$CXX $CXXFLAGS -c ../${fuzzer}.cc -o ${fuzzer}.o \
-DLEVELDB_PLATFORM_POSIX=1 -std=c++11 -Wall \
-I$SRC/leveldb/build/include -I$SRC/leveldb/ -I$SRC/leveldb/include

# Link
$CXX $LIB_FUZZING_ENGINE $CXXFLAGS ${fuzzer}.o -o $OUT/${fuzzer} libleveldb.a
done

# Copy options to out
cp $SRC/*options $OUT/
151 changes: 151 additions & 0 deletions mayhem/fuzz_db.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
/* Copyright 2020 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/


#include <cstdint>
#include <cstddef>
#include <filesystem>
#include <memory>
#include <string>

#include "leveldb/db.h"
#include "leveldb/iterator.h"
#include "leveldb/options.h"
#include "leveldb/status.h"

#include <fuzzer/FuzzedDataProvider.h>

namespace {

// Deletes the database directory when going out of scope.
class AutoDbDeleter {
public:
static constexpr char kDbPath[] = "/tmp/testdb";

AutoDbDeleter() = default;

AutoDbDeleter(const AutoDbDeleter&) = delete;
AutoDbDeleter& operator=(const AutoDbDeleter&) = delete;

~AutoDbDeleter() {
std::__fs::filesystem::remove_all(kDbPath);
}
};

// static
constexpr char AutoDbDeleter::kDbPath[];

// Returns nullptr (a falsey unique_ptr) if opening fails.
std::unique_ptr<leveldb::DB> OpenDB() {
leveldb::Options options;
options.create_if_missing = true;

leveldb::DB* db_ptr;
leveldb::Status status =
leveldb::DB::Open(options, AutoDbDeleter::kDbPath, &db_ptr);
if (!status.ok())
return nullptr;

return std::unique_ptr<leveldb::DB>(db_ptr);
}

enum class FuzzOp {
kPut = 0,
kGet = 1,
kDelete = 2,
kGetProperty = 3,
kIterate = 4,
kGetReleaseSnapshot = 5,
kReopenDb = 6,
kCompactRange = 7,
// Add new values here.

// When adding new values, update to the last value above.
kMaxValue = kCompactRange,
};

} // namespace

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Must occur before `db` so the deletion doesn't happen while the DB is open.
AutoDbDeleter db_deleter;

std::unique_ptr<leveldb::DB> db = OpenDB();
if (!db.get())
return 0;

// Perform a sequence of operations on the database.
FuzzedDataProvider fuzzed_data(data, size);
while (fuzzed_data.remaining_bytes() != 0) {
FuzzOp fuzz_op = fuzzed_data.ConsumeEnum<FuzzOp>();

switch (fuzz_op) {
case FuzzOp::kPut: {
std::string key = fuzzed_data.ConsumeRandomLengthString();
std::string value = fuzzed_data.ConsumeRandomLengthString();
db->Put(leveldb::WriteOptions(), key, value);
break;
}
case FuzzOp::kGet: {
std::string key = fuzzed_data.ConsumeRandomLengthString();
std::string value;
db->Get(leveldb::ReadOptions(), key, &value);
break;
}
case FuzzOp::kDelete: {
std::string key = fuzzed_data.ConsumeRandomLengthString();
db->Delete(leveldb::WriteOptions(), key);
break;
}
case FuzzOp::kGetProperty: {
std::string name = fuzzed_data.ConsumeRandomLengthString();
std::string value;
db->GetProperty(name, &value);
break;
}
case FuzzOp::kIterate: {
std::unique_ptr<leveldb::Iterator> it(
db->NewIterator(leveldb::ReadOptions()));
for (it->SeekToFirst(); it->Valid(); it->Next())
continue;
}
case FuzzOp::kGetReleaseSnapshot: {
leveldb::ReadOptions snapshot_options;
snapshot_options.snapshot = db->GetSnapshot();
std::unique_ptr<leveldb::Iterator> it(db->NewIterator(snapshot_options));
db->ReleaseSnapshot(snapshot_options.snapshot);
}
case FuzzOp::kReopenDb: {
// The database must be closed before attempting to reopen it. Otherwise,
// the open will fail due to exclusive locking.
db.reset();
db = OpenDB();
if (!db)
return 0; // Reopening the database failed.
break;
}
case FuzzOp::kCompactRange: {
std::string begin_key = fuzzed_data.ConsumeRandomLengthString();
std::string end_key = fuzzed_data.ConsumeRandomLengthString();
leveldb::Slice begin_slice(begin_key);
leveldb::Slice end_slice(end_key);
db->CompactRange(&begin_slice, &end_slice);
break;
}
}
}

return 0;
}
4 changes: 4 additions & 0 deletions mayhem/fuzz_db.mayhemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
project: PROJECT
target: fuzz_db
cmds:
- cmd: /out/fuzz_db
2 changes: 2 additions & 0 deletions mayhem/fuzz_db.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[libfuzzer]
detect_leaks=0

0 comments on commit ce751f4

Please sign in to comment.