diff options
author | Kent Overstreet <kent.overstreet@linux.dev> | 2024-11-07 15:57:50 -0500 |
---|---|---|
committer | Kent Overstreet <kent.overstreet@linux.dev> | 2024-11-07 19:37:28 -0500 |
commit | 4849606fcb47ff42ed8f6c9f7c0f01bd24c21bc2 (patch) | |
tree | acf4060a9ffa6b481e3dc5132a1df9c3e1b37572 | |
parent | e1001febe8554361e0f2047ca5f813399c6e741a (diff) |
syzbot-repro.ktest: Run syzbot reproducers in a single command
Example usage, to reproduce locally the bug https://syzkaller.appspot.com/bug?extid=f074d2e31d8d35a6a38c
build-test-kernel run -I ~/ktest/tests/syzbot-repro.ktest f074d2e31d8d35a6a38c
or, with an optionl crash index:
build-test-kernel run -I ~/ktest/tests/syzbot-repro.ktest f074d2e31d8d35a6a38c 3
The syzbot-get tool needs to first be built and installed, run
cargo install --path "path to ktest"
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rwxr-xr-x | build-test-kernel | 6 | ||||
-rw-r--r-- | lib/parse-test.sh | 4 | ||||
-rw-r--r-- | src/bin/syzbot-get.rs | 92 | ||||
-rw-r--r-- | tests/prelude.sh | 3 | ||||
-rwxr-xr-x | tests/syzbot-repro.ktest | 34 |
5 files changed, 137 insertions, 2 deletions
diff --git a/build-test-kernel b/build-test-kernel index 61b88cd..72fbacb 100755 --- a/build-test-kernel +++ b/build-test-kernel @@ -198,7 +198,11 @@ build_kernel() mv "$kconfig" "$kconfig".bak fi - new_config + if [[ -z $ktest_kconfig_base ]]; then + new_config + else + cp "$ktest_kconfig_base" "$kconfig" + fi log_verbose "kernel_config_require: ${ktest_kernel_config_require[@]} ${ktest_kernel_config_require_soft[@]}" diff --git a/lib/parse-test.sh b/lib/parse-test.sh index 42a476e..291211a 100644 --- a/lib/parse-test.sh +++ b/lib/parse-test.sh @@ -2,7 +2,9 @@ parse_test_deps() { export ktest_crashdump - eval $("$ktest_test" deps) + export ktest_out + + eval $( "$ktest_test" deps $ktest_testargs ) parse_arch "$ktest_arch" diff --git a/src/bin/syzbot-get.rs b/src/bin/syzbot-get.rs new file mode 100644 index 0000000..9ecafa0 --- /dev/null +++ b/src/bin/syzbot-get.rs @@ -0,0 +1,92 @@ +use std::path::PathBuf; +use clap::Parser; +use serde_derive::Deserialize; + +#[derive(Parser)] +#[command(author, version, about, long_about = None)] +struct Args { + #[arg(short, long)] + id: String, + #[arg(short, long)] + idx: Option<usize>, + #[arg(short, long)] + output: PathBuf, + #[arg(short, long)] + verbose: bool, +} + +#[allow(dead_code)] +#[derive(Deserialize, Debug)] +struct SyzCrash { + title: String, + #[serde(rename = "syz-reproducer")] + syz_reproducer: Option<String>, + #[serde(rename = "c-reproducer")] + c_reproducer: Option<String>, + #[serde(rename = "kernel-config")] + kernel_config: String, + #[serde(rename = "kernel-source-git")] + kernel_source_git: String, + #[serde(rename = "kernel-source-commit")] + kernel_source_commit: String, + #[serde(rename = "syzkaller-git")] + syzkaller_git: String, + #[serde(rename = "syzkaller-commit")] + syzkaller_commit: String, + #[serde(rename = "crash-report-link")] + crash_report_link: String, +} + +#[allow(dead_code)] +#[derive(Deserialize, Debug)] +struct SyzBug { + version: usize, + title: String, + id: String, + #[serde(default)] + discussions: Vec<String>, + crashes: Vec<SyzCrash>, +} + +fn get_syz_url(url: &String) -> String { + let url = format!("https://syzkaller.appspot.com{}", url); + reqwest::blocking::get(url).unwrap().text().unwrap() +} + +fn fetch_syz_url(args: &Args, url: &String, fname: &String) { + let fname = args.output.join(fname); + if !fname.exists() { + if args.verbose { eprintln!("fetching {} => {:?}", &url, &fname); } + + std::fs::write(fname, get_syz_url(url)).ok(); + } else { + if args.verbose { eprintln!("have {} => {:?}", &url, &fname); } + } +} + +fn fetch_syz_crash(args: &Args, crash: &SyzCrash, idx: usize) { + fetch_syz_url(&args, &crash.kernel_config, &format!("{}.{}.kconfig", args.id, idx)); + + if let Some(r) = &crash.c_reproducer.as_ref() { + fetch_syz_url(&args, r, &format!("{}.{}.repro.c", args.id, idx)); + } +} + +fn main() { + let args = Args::parse(); + + let bug_json = get_syz_url(&format!("/bug?json=1&extid={}", args.id)); + let bug: SyzBug = serde_json::from_str(&bug_json).unwrap(); + + if args.verbose { eprintln!("{:?}", &bug); } + + std::fs::create_dir_all(&args.output).ok(); + + if let Some(idx) = args.idx { + fetch_syz_crash(&args, &bug.crashes[idx], idx); + } else { + for (idx, crash) in bug.crashes.iter().enumerate() { + fetch_syz_crash(&args, &crash, idx); + } + } +} diff --git a/tests/prelude.sh b/tests/prelude.sh index b1bc878..93ede2b 100644 --- a/tests/prelude.sh +++ b/tests/prelude.sh @@ -35,7 +35,9 @@ if [[ ! -v ktest_cpus ]]; then ktest_qemu_append=() ktest_compiler=gcc ktest_allow_taint=false + ktest_tests_unknown=false + ktest_kconfig_base= BUILD_ON_HOST="" fi @@ -355,6 +357,7 @@ main() echo "ktest_qemu_append=(${ktest_qemu_append[@]})" echo "ktest_allow_taint=$ktest_allow_taint" echo "ktest_tests_unknown=$ktest_tests_unknown" + echo "ktest_kconfig_base=$ktest_kconfig_base" ;; init) create_ktest_user diff --git a/tests/syzbot-repro.ktest b/tests/syzbot-repro.ktest new file mode 100755 index 0000000..fa9b131 --- /dev/null +++ b/tests/syzbot-repro.ktest @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# +# Run syzbot reproducers: +# +# Example usage, to reproduce locally the bug https://syzkaller.appspot.com/bug?extid=f074d2e31d8d35a6a38c +# build-test-kernel run -I ~/ktest/tests/syzbot-repro.ktest f074d2e31d8d35a6a38c +# or, with an optionl crash index: +# build-test-kernel run -I ~/ktest/tests/syzbot-repro.ktest f074d2e31d8d35a6a38c 3 +# +# The syzbot-get tool first needs to be built and installed, run +# cargo install --path "path to ktest" + +. $(dirname $(readlink -e "${BASH_SOURCE[0]}"))/test-libs.sh + +ktest_tests_unknown=true + +if [[ $1 == "deps" ]]; then + syz_id=$2 + crash_idx=${3:-"0"} + + syzbot-get --output "$ktest_out/syzbot" --id $syz_id --idx $crash_idx + ktest_kconfig_base="$ktest_out/syzbot/$syz_id.$crash_idx.kconfig" +fi + +run_test() +{ + syz_id=$1 + crash_idx=${2:-"0"} + + gcc -O2 -Wall -o /tmp/syz-repro "$ktest_out/syzbot/$syz_id.$crash_idx.repro.c" + /tmp/syz-repro +} + +main "$@" |