summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2024-11-07 15:57:50 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2024-11-07 19:37:28 -0500
commit4849606fcb47ff42ed8f6c9f7c0f01bd24c21bc2 (patch)
treeacf4060a9ffa6b481e3dc5132a1df9c3e1b37572
parente1001febe8554361e0f2047ca5f813399c6e741a (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-xbuild-test-kernel6
-rw-r--r--lib/parse-test.sh4
-rw-r--r--src/bin/syzbot-get.rs92
-rw-r--r--tests/prelude.sh3
-rwxr-xr-xtests/syzbot-repro.ktest34
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 "$@"