Skip to content

Commit

Permalink
Add code
Browse files Browse the repository at this point in the history
  • Loading branch information
Changochen committed May 10, 2023
1 parent 80cdae7 commit 8d5356e
Show file tree
Hide file tree
Showing 53 changed files with 11,859 additions and 1 deletion.
24 changes: 24 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: build

on:
push:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-22.04
#runs-on: ${{ matrix.os }}

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3

- name: Install Prerequisites
run: sh ./install.sh

- name: add path
run: echo "$HOME/.cargo/bin" >> $GITHUB_PATH

- name: Run test
run: cargo test
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
Cargo.lock
.cur_input*
57 changes: 57 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
[package]
name = "mufuzz"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tonic = { version = "0.8.0", features = ["transport"] }
prost = "0.11.0"
lazy_static = "1.4.0"
clap = { version = "3.2.17", features = ["derive"] }

tokio = { version = "1.20.1", features = ["macros", "rt-multi-thread"] }
#tokio = { version = "1.17.0", features = ["macros", "rt-multi-thread", "full", "tracing"] }
tokio-stream = { version = "0.1.9", features = ["net"] }
libc = "0.2.132"
nix = { version = "0.25.0", optional = true }
core_affinity = { version = "0.5", git = "https://github.com/s1341/core_affinity_rs", rev = "6648a7a", optional = true }
serde = { version = "1.0.136", default-features = false, features = [
"alloc",
"derive",
] } # serialization lib
#quote = "1.0"
#syn = "1.0"
async-trait = "0.1.57"
futures = "0.3.23"
rand = "0.8.5"
tower = "0.4.13"
http = "0.2.8"
serde_json = "1.0.83"
itertools = "0.10.3"
rand_distr = "0.4.3"
async-channel = "1.7.1"
rayon = "1.5.3"
dashmap = "5.3.4"
#crossbeam = "0.8.1"
psutil = "3.2.2"
bitflags = "2.2.1"

#[lib]
#proc-macro = true

[build-dependencies]
tonic-build = "0.8.0"

[dev-dependencies]
serial_test = "0.9.0"
criterion = "0.3.6"

[features]
default = ["std", "fork"]
std = ["core_affinity", "nix"] # print, env, launcher ... support
fork = []

[profile.release]
debug = true
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,30 @@
# mufuzz
# mufuzz, a parallel fuzzing framework

TODO: Add reference

## Build
1. Install `cargo` and `protoc`
```
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
wget https://github.com/protocolbuffers/protobuf/releases/download/v21.5/protoc-21.5-linux-x86_64.zip && \
sudo unzip protoc-21.5-linux-x86_64.zip -d /usr/local
```
2. `cargo build --release`


## Run
Basic run (for example, run on 20 cores):
```
taskset -c 0-19 cargo run --release -- -c "your/command @@" -i input_corpus --core 20
```

Check the usage:
```
cargo run --release -- -help
```

## Note
1. The code is still under cleanup. Some features are still missing (such as saving the corpus/crashes to disk).
2. Assign exclusive cores to `mufuzz` for better performance.
3. Part of the forkserver code is borrowed from [LibAFL](https://github.com/AFLplusplus/LibAFL), a great project for building fuzzers.
4. After you exit the fuzzer, you might need to run `ipcrm -a` to remove the share memory.
15 changes: 15 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use std::fs;

fn main() -> Result<(), Box<dyn std::error::Error>> {
// Build all proto in proto/.
let paths = fs::read_dir("./proto").unwrap();
for path in paths {
let path = path.unwrap().path();
let path = path.to_str().unwrap();

if path.ends_with("proto") {
tonic_build::compile_protos(path)?;
}
}
Ok(())
}
4 changes: 4 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y

wget https://github.com/protocolbuffers/protobuf/releases/download/v21.5/protoc-21.5-linux-x86_64.zip && \
sudo unzip protoc-21.5-linux-x86_64.zip -d /usr/local
10 changes: 10 additions & 0 deletions proto/execution.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";

package microfuzz.execution;

import "msg_type.proto";

service Executor {
rpc ExecuteTestCases(msg_type.TestCases) returns (msg_type.Empty);
rpc GetFeedbacks(msg_type.Number) returns (msg_type.Feedbacks);
}
14 changes: 14 additions & 0 deletions proto/feedback.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
syntax = "proto3";

package microfuzz.feedback;

import "msg_type.proto";

service FeedbackCollector {
rpc CheckFeedbacks(msg_type.Feedbacks) returns (msg_type.Empty);
rpc GetInterestingTestCases(msg_type.Number) returns (msg_type.TestCases);
rpc GetMutationFeedbacks(msg_type.Number) returns (msg_type.Feedbacks);
rpc GetTestCaseFeedbacks(msg_type.Number) returns (msg_type.Feedbacks);

rpc RetrieveMonitorData(msg_type.Empty) returns (msg_type.MonitorData);
}
15 changes: 15 additions & 0 deletions proto/hello_world.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
syntax = "proto3";

package helloworld;

service Greeter {
rpc SayHello(HelloRequest) returns (HelloReply);
}

message HelloRequest {
string name = 1;
}

message HelloReply {
string message = 1;
}
10 changes: 10 additions & 0 deletions proto/monitor.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
syntax = "proto3";

package microfuzz.monitor;

import "msg_type.proto";

service Monitor {
rpc RegisterService(msg_type.ServiceInfo) returns (msg_type.RegistrationStatus);
rpc GetServices(msg_type.Empty) returns (msg_type.ServiceList);
}
90 changes: 90 additions & 0 deletions proto/msg_type.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
syntax = "proto3";

package microfuzz.msg_type;

message Number {
uint32 num = 1;
}

message TestCases {
repeated TestCase test_cases = 1;
}

message TestCase {
bytes content = 2;
uint32 pid = 3;
}

message Feedbacks {
repeated Feedback feedbacks = 1;
}

message NewBit {
uint32 index = 1;
uint32 value = 2;
}

message NewCoverage {
repeated NewBit new_bits = 1;
}

message Counter {
uint32 counter = 1;
}

message FakeFeedback {
string fake = 1;
}

enum ExecutionStatus {
OK = 0;
TIMEOUT = 1;
CRASH = 2;
INTERESTING = 3;
}

message MutationInfo {
uint32 pid = 1;
uint32 mutator_id = 2;
}

message FeedbackData {
oneof feedback_data {
NewCoverage new_coverage = 4;
Counter counter = 5;
FakeFeedback fake_feedback= 6;
}
}

message Feedback {
TestCase test_case = 1;
ExecutionStatus status = 2;
MutationInfo mutation_info = 3;
FeedbackData data = 4;
}

message Empty {}

message RegistrationStatus {
bool success = 1;
}

enum ServiceType {
MUTATOR = 0;
EXECUTOR = 1;
QUEUEMANAGER = 2;
FEEDBACKCOLLECTOR = 3;
}

message ServiceInfo {
ServiceType service_type = 1;
string socket_addr = 2;
}

message ServiceList {
repeated ServiceInfo services = 1;
}

message MonitorData {
repeated string data = 1;
}
12 changes: 12 additions & 0 deletions proto/mutation.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
syntax = "proto3";

package microfuzz.mutation;

import "msg_type.proto";

service Mutator {
// Post interesting testcases for mutation.
rpc MutateTestCases(msg_type.TestCases) returns (msg_type.Number);
rpc GetMutatedTestCases(msg_type.Number) returns (msg_type.TestCases);
rpc PostMutationFeedbacks(msg_type.Feedbacks) returns (msg_type.Empty);
}
14 changes: 14 additions & 0 deletions proto/queue_management.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
syntax = "proto3";

package microfuzz.queue_management;

import "msg_type.proto";

service QueueManager {
// Get new test cases that we want to test/evaluate in executor.
rpc GetInterestingTestCases(msg_type.Number) returns (msg_type.TestCases);
// Receive the summary of execution feedback.
rpc PostInterestingTestCases(msg_type.TestCases) returns (msg_type.Empty);

rpc PostTestCaseFeedbacks(msg_type.Feedbacks) returns (msg_type.Empty);
}
Loading

0 comments on commit 8d5356e

Please sign in to comment.