Skip to content

Commit b401746

Browse files
Initial fuzzer integration (#961)
Adds a set of fuzzers for various `linkerd` crates. The goal of this PR is to create an initial fuzzer infrastructure as well as fuzzers that can be integrated with OSS-Fuzz for continuous fuzzing. The way I set it up was to place the fuzzers for a given crate within the crate folder itself. I then put in a `fuzz_logic` module in the source code that is to be fuzzed, thus following the low of how the existing tests are written. The majority of additions in this PR are independent of the linkerd2-proxy source code, but there are a few changes. Signed-off-by: davkor <[email protected]>
1 parent 07e9249 commit b401746

File tree

24 files changed

+343
-2
lines changed

24 files changed

+343
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,4 @@ debug = false
6363
debug = false
6464

6565
[patch.crates-io]
66-
webpki = { git = "https://github.com/linkerd/webpki", branch = "cert-dns-names-0.21", rev = "b2c3bb3" }
66+
webpki = { git = "https://github.com/linkerd/webpki", branch = "cert-dns-names-0.21" }

linkerd/addr/fuzz/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

linkerd/addr/fuzz/Cargo.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "linkerd-addr-fuzz"
3+
version = "0.0.0"
4+
authors = ["Linkerd Developers <[email protected]>"]
5+
publish = false
6+
edition = "2018"
7+
8+
[package.metadata]
9+
cargo-fuzz = true
10+
11+
[dependencies]
12+
libfuzzer-sys = "0.4"
13+
14+
[dependencies.linkerd-addr]
15+
path = ".."
16+
17+
# Prevent this from interfering with workspaces
18+
[workspace]
19+
members = ["."]
20+
21+
[features]
22+
fuzzing = []
23+
24+
[[bin]]
25+
name = "fuzz_target_1"
26+
path = "fuzz_targets/fuzz_target_1.rs"
27+
required-features = ["fuzzing"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
4+
5+
fuzz_target!(|data: &[u8]| {
6+
if let Ok(s) = std::str::from_utf8(data) {
7+
linkerd_addr::fuzz_logic::fuzz_addr_1(s);
8+
}
9+
});

linkerd/addr/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,3 +258,22 @@ mod tests {
258258
}
259259
}
260260
}
261+
262+
#[cfg(fuzzing)]
263+
pub mod fuzz_logic {
264+
use super::*;
265+
266+
pub fn fuzz_addr_1(fuzz_data: &str) {
267+
if let Ok(addr) = Addr::from_str(fuzz_data) {
268+
addr.is_loopback();
269+
addr.to_http_authority();
270+
addr.is_loopback();
271+
addr.socket_addr();
272+
}
273+
274+
if let Ok(name_addr) = NameAddr::from_str_and_port(fuzz_data, 1234) {
275+
name_addr.port();
276+
name_addr.as_http_authority();
277+
}
278+
}
279+
}

linkerd/dns/fuzz/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
target
3+
corpus
4+
artifacts

linkerd/dns/fuzz/Cargo.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
[package]
3+
name = "linkerd-dns-fuzz"
4+
version = "0.0.0"
5+
authors = ["Linkerd Developers <[email protected]>"]
6+
publish = false
7+
edition = "2018"
8+
9+
[package.metadata]
10+
cargo-fuzz = true
11+
12+
[dependencies]
13+
libfuzzer-sys = "0.4"
14+
tokio = { version = "1", features = ["rt", "time", "io-util"] }
15+
16+
[dependencies.linkerd-dns]
17+
path = ".."
18+
19+
# Prevent this from interfering with workspaces
20+
[workspace]
21+
members = ["."]
22+
23+
[features]
24+
fuzzing = []
25+
26+
[[bin]]
27+
name = "fuzz_target_1"
28+
path = "fuzz_targets/fuzz_target_1.rs"
29+
test = false
30+
doc = false
31+
required-features = ["fuzzing"]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![no_main]
2+
use libfuzzer_sys::fuzz_target;
3+
4+
fuzz_target!(|data: &[u8]| {
5+
if let Ok(s) = std::str::from_utf8(data) {
6+
let rt = tokio::runtime::Runtime::new().unwrap();
7+
rt.block_on(linkerd_dns::fuzz_logic::fuzz_entry(s))
8+
}
9+
});

linkerd/dns/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,3 +246,25 @@ mod tests {
246246
assert!(Suffix::from_str("").is_err(), "suffix must not be empty");
247247
}
248248
}
249+
250+
#[cfg(fuzzing)]
251+
pub mod fuzz_logic {
252+
use super::*;
253+
use std::str::FromStr;
254+
pub struct FuzzConfig {}
255+
256+
// Empty config resolver that we can use.
257+
impl ConfigureResolver for FuzzConfig {
258+
fn configure_resolver(&self, _opts: &mut ResolverOpts) {}
259+
}
260+
261+
// Test the resolvers do not panic unexpectedly.
262+
pub async fn fuzz_entry(fuzz_data: &str) {
263+
if let Ok(name) = Name::from_str(fuzz_data) {
264+
let fcon = FuzzConfig {};
265+
let resolver = Resolver::from_system_config_with(&fcon).unwrap();
266+
let _w = resolver.resolve_a(&name).await;
267+
let _w2 = resolver.resolve_srv(&name).await;
268+
}
269+
}
270+
}

linkerd/proxy/http/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ tracing = "0.1.23"
3939
try-lock = "0.2"
4040
pin-project = "1"
4141

42+
[target.'cfg(fuzzing)'.dependencies]
43+
tokio-test = "0.4"
44+
4245
[dev-dependencies]
4346
tokio-test = "0.4"
4447
tracing-subscriber = "0.2.16"

0 commit comments

Comments
 (0)