mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 12:48:07 +00:00
Add support for ASAN print_scariness (#359)
This commit is contained in:
@ -36,6 +36,9 @@ pub struct CrashReport {
|
|||||||
pub task_id: Uuid,
|
pub task_id: Uuid,
|
||||||
|
|
||||||
pub job_id: Uuid,
|
pub job_id: Uuid,
|
||||||
|
|
||||||
|
pub scariness_score: Option<u32>,
|
||||||
|
pub scariness_description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
@ -150,6 +153,8 @@ impl CrashReport {
|
|||||||
call_stack: asan_log.call_stack().to_vec(),
|
call_stack: asan_log.call_stack().to_vec(),
|
||||||
call_stack_sha256: asan_log.call_stack_sha256(),
|
call_stack_sha256: asan_log.call_stack_sha256(),
|
||||||
asan_log: Some(asan_log.text().to_string()),
|
asan_log: Some(asan_log.text().to_string()),
|
||||||
|
scariness_score: asan_log.scariness_score().into(),
|
||||||
|
scariness_description: asan_log.scariness_description().to_owned(),
|
||||||
task_id,
|
task_id,
|
||||||
job_id,
|
job_id,
|
||||||
}
|
}
|
||||||
|
@ -136,6 +136,8 @@ impl<'a> GenericReportProcessor<'a> {
|
|||||||
crash_site: crash.crash_site,
|
crash_site: crash.crash_site,
|
||||||
call_stack_sha256,
|
call_stack_sha256,
|
||||||
asan_log: None,
|
asan_log: None,
|
||||||
|
scariness_score: None,
|
||||||
|
scariness_description: None,
|
||||||
task_id,
|
task_id,
|
||||||
job_id,
|
job_id,
|
||||||
};
|
};
|
||||||
|
55
src/agent/onefuzz/data/libfuzzer-scariness-underflow.txt
Normal file
55
src/agent/onefuzz/data/libfuzzer-scariness-underflow.txt
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
=================================================================
|
||||||
|
==32266==ERROR: AddressSanitizer: stack-buffer-underflow on address 0x7ffd2173f200 at pc 0x0000004fd403 bp 0x7ffd2173f1f0 sp 0x7ffd2173f1e8
|
||||||
|
WRITE of size 4 at 0x7ffd2173f200 thread T0
|
||||||
|
SCARINESS: 51 (4-byte-write-stack-buffer-underflow)
|
||||||
|
#0 0x4fd402 in LLVMFuzzerTestOneInput /home/runner/work/onefuzz/onefuzz/src/integration-tests/libfuzzer/simple.c:28:69
|
||||||
|
#1 0x43b271 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43b271)
|
||||||
|
#2 0x43a9a5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43a9a5)
|
||||||
|
#3 0x43cf9b in fuzzer::Fuzzer::MutateAndTestOne() (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43cf9b)
|
||||||
|
#4 0x43dd15 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43dd15)
|
||||||
|
#5 0x42999b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x42999b)
|
||||||
|
#6 0x4557a2 in main (/tmp/xx/linux-libfuzzer/fuzz.exe+0x4557a2)
|
||||||
|
#7 0x7f878654d0b2 in __libc_start_main /build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:308:16
|
||||||
|
#8 0x41db59 in _start (/tmp/xx/linux-libfuzzer/fuzz.exe+0x41db59)
|
||||||
|
|
||||||
|
Address 0x7ffd2173f200 is located in stack of thread T0 at offset 0 in frame
|
||||||
|
#0 0x4fcccf in LLVMFuzzerTestOneInput /home/runner/work/onefuzz/onefuzz/src/integration-tests/libfuzzer/simple.c:8
|
||||||
|
|
||||||
|
This frame has 1 object(s):
|
||||||
|
[32, 36) 'cnt' (line 9)
|
||||||
|
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork
|
||||||
|
(longjmp and C++ exceptions *are* supported)
|
||||||
|
SUMMARY: AddressSanitizer: stack-buffer-underflow /home/runner/work/onefuzz/onefuzz/src/integration-tests/libfuzzer/simple.c:28:69 in LLVMFuzzerTestOneInput
|
||||||
|
Shadow bytes around the buggy address:
|
||||||
|
0x1000242dfdf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
=>0x1000242dfe40:[f1]f1 f1 f1 04 f3 f3 f3 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
0x1000242dfe90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
Shadow byte legend (one shadow byte represents 8 application bytes):
|
||||||
|
Addressable: 00
|
||||||
|
Partially addressable: 01 02 03 04 05 06 07
|
||||||
|
Heap left redzone: fa
|
||||||
|
Freed heap region: fd
|
||||||
|
Stack left redzone: f1
|
||||||
|
Stack mid redzone: f2
|
||||||
|
Stack right redzone: f3
|
||||||
|
Stack after return: f5
|
||||||
|
Stack use after scope: f8
|
||||||
|
Global redzone: f9
|
||||||
|
Global init order: f6
|
||||||
|
Poisoned by user: f7
|
||||||
|
Container overflow: fc
|
||||||
|
Array cookie: ac
|
||||||
|
Intra object redzone: bb
|
||||||
|
ASan internal: fe
|
||||||
|
Left alloca redzone: ca
|
||||||
|
Right alloca redzone: cb
|
||||||
|
Shadow gap: cc
|
||||||
|
==32266==ABORTING
|
16
src/agent/onefuzz/data/libfuzzer-scariness.txt
Normal file
16
src/agent/onefuzz/data/libfuzzer-scariness.txt
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
=================================================================
|
||||||
|
==28073==ERROR: AddressSanitizer: FPE on unknown address 0x0000004fd774 (pc 0x0000004fd774 bp 0x7ffd45d2c110 sp 0x7ffd45d2bf00 T0)
|
||||||
|
SCARINESS: 10 (signal)
|
||||||
|
#0 0x4fd773 in LLVMFuzzerTestOneInput /home/runner/work/onefuzz/onefuzz/src/integration-tests/libfuzzer/simple.c:58:32
|
||||||
|
#1 0x43b271 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43b271)
|
||||||
|
#2 0x43a9a5 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43a9a5)
|
||||||
|
#3 0x43cf9b in fuzzer::Fuzzer::MutateAndTestOne() (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43cf9b)
|
||||||
|
#4 0x43dd15 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x43dd15)
|
||||||
|
#5 0x42999b in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/tmp/xx/linux-libfuzzer/fuzz.exe+0x42999b)
|
||||||
|
#6 0x4557a2 in main (/tmp/xx/linux-libfuzzer/fuzz.exe+0x4557a2)
|
||||||
|
#7 0x7fc6b74190b2 in __libc_start_main /build/glibc-YYA7BZ/glibc-2.31/csu/../csu/libc-start.c:308:16
|
||||||
|
#8 0x41db59 in _start (/tmp/xx/linux-libfuzzer/fuzz.exe+0x41db59)
|
||||||
|
|
||||||
|
AddressSanitizer can not provide additional info.
|
||||||
|
SUMMARY: AddressSanitizer: FPE /home/runner/work/onefuzz/onefuzz/src/integration-tests/libfuzzer/simple.c:58:32 in LLVMFuzzerTestOneInput
|
||||||
|
==28073==ABORTING
|
@ -16,6 +16,8 @@ pub struct AsanLog {
|
|||||||
summary: String,
|
summary: String,
|
||||||
fault_type: String,
|
fault_type: String,
|
||||||
call_stack: Vec<String>,
|
call_stack: Vec<String>,
|
||||||
|
scariness_score: Option<u32>,
|
||||||
|
scariness_description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsanLog {
|
impl AsanLog {
|
||||||
@ -27,12 +29,19 @@ impl AsanLog {
|
|||||||
|
|
||||||
let call_stack = parse_call_stack(&text).unwrap_or_else(Vec::default);
|
let call_stack = parse_call_stack(&text).unwrap_or_else(Vec::default);
|
||||||
|
|
||||||
|
let (scariness_score, scariness_description) = match parse_scariness(&text) {
|
||||||
|
Some((x, y)) => (Some(x), Some(y)),
|
||||||
|
None => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
let log = Self {
|
let log = Self {
|
||||||
text,
|
text,
|
||||||
sanitizer,
|
sanitizer,
|
||||||
summary,
|
summary,
|
||||||
fault_type,
|
fault_type,
|
||||||
call_stack,
|
call_stack,
|
||||||
|
scariness_score,
|
||||||
|
scariness_description,
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(log)
|
Some(log)
|
||||||
@ -57,6 +66,24 @@ impl AsanLog {
|
|||||||
pub fn call_stack_sha256(&self) -> String {
|
pub fn call_stack_sha256(&self) -> String {
|
||||||
sha256::digest_iter(self.call_stack())
|
sha256::digest_iter(self.call_stack())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scariness_score(&self) -> Option<u32> {
|
||||||
|
self.scariness_score
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scariness_description(&self) -> &Option<String> {
|
||||||
|
&self.scariness_description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_scariness(text: &str) -> Option<(u32, String)> {
|
||||||
|
let pattern = r"(?m)^SCARINESS: (\d+) \(([^\)]+)\)\r?$";
|
||||||
|
let re = Regex::new(pattern).ok()?;
|
||||||
|
let captures = re.captures(text)?;
|
||||||
|
let index = u32::from_str_radix(captures.get(1)?.as_str(), 10).ok()?;
|
||||||
|
let value = captures.get(2)?.as_str().trim();
|
||||||
|
|
||||||
|
Some((index, value.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_asan_runtime_error(text: &str) -> Option<(String, String, String)> {
|
fn parse_asan_runtime_error(text: &str) -> Option<(String, String, String)> {
|
||||||
@ -197,70 +224,116 @@ mod tests {
|
|||||||
"AddressSanitizer",
|
"AddressSanitizer",
|
||||||
"heap-use-after-free",
|
"heap-use-after-free",
|
||||||
7,
|
7,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/libfuzzer-deadly-signal.txt",
|
"data/libfuzzer-deadly-signal.txt",
|
||||||
"libFuzzer",
|
"libFuzzer",
|
||||||
"deadly signal",
|
"deadly signal",
|
||||||
14,
|
14,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/libfuzzer-windows-llvm10-out-of-memory-malloc.txt",
|
"data/libfuzzer-windows-llvm10-out-of-memory-malloc.txt",
|
||||||
"libFuzzer",
|
"libFuzzer",
|
||||||
"out-of-memory",
|
"out-of-memory",
|
||||||
16,
|
16,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/libfuzzer-windows-llvm10-out-of-memory-rss.txt",
|
"data/libfuzzer-windows-llvm10-out-of-memory-rss.txt",
|
||||||
"libFuzzer",
|
"libFuzzer",
|
||||||
"out-of-memory",
|
"out-of-memory",
|
||||||
0,
|
0,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/libfuzzer-linux-llvm10-out-of-memory-malloc.txt",
|
"data/libfuzzer-linux-llvm10-out-of-memory-malloc.txt",
|
||||||
"libFuzzer",
|
"libFuzzer",
|
||||||
"out-of-memory",
|
"out-of-memory",
|
||||||
15,
|
15,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/libfuzzer-linux-llvm10-out-of-memory-rss.txt",
|
"data/libfuzzer-linux-llvm10-out-of-memory-rss.txt",
|
||||||
"libFuzzer",
|
"libFuzzer",
|
||||||
"out-of-memory",
|
"out-of-memory",
|
||||||
4,
|
4,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/tsan-linux-llvm10-data-race.txt",
|
"data/tsan-linux-llvm10-data-race.txt",
|
||||||
"ThreadSanitizer",
|
"ThreadSanitizer",
|
||||||
"data race",
|
"data race",
|
||||||
1,
|
1,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/clang-10-asan-breakpoint.txt",
|
"data/clang-10-asan-breakpoint.txt",
|
||||||
"AddressSanitizer",
|
"AddressSanitizer",
|
||||||
"breakpoint",
|
"breakpoint",
|
||||||
43,
|
43,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/asan-check-failure.txt",
|
"data/asan-check-failure.txt",
|
||||||
"AddressSanitizer",
|
"AddressSanitizer",
|
||||||
"CHECK failed",
|
"CHECK failed",
|
||||||
12,
|
12,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"data/asan-check-failure-missing-symbolizer.txt",
|
"data/asan-check-failure-missing-symbolizer.txt",
|
||||||
"AddressSanitizer",
|
"AddressSanitizer",
|
||||||
"CHECK failed",
|
"CHECK failed",
|
||||||
12,
|
12,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"data/libfuzzer-scariness.txt",
|
||||||
|
"AddressSanitizer",
|
||||||
|
"FPE",
|
||||||
|
9,
|
||||||
|
Some(10),
|
||||||
|
Some("signal".to_string()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"data/libfuzzer-scariness-underflow.txt",
|
||||||
|
"AddressSanitizer",
|
||||||
|
"stack-buffer-underflow",
|
||||||
|
9,
|
||||||
|
Some(51),
|
||||||
|
Some("4-byte-write-stack-buffer-underflow".to_string()),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for (log_path, sanitizer, fault_type, call_stack_len) in test_cases {
|
for (
|
||||||
|
log_path,
|
||||||
|
sanitizer,
|
||||||
|
fault_type,
|
||||||
|
call_stack_len,
|
||||||
|
scariness_score,
|
||||||
|
scariness_description,
|
||||||
|
) in test_cases
|
||||||
|
{
|
||||||
let data = std::fs::read_to_string(log_path)?;
|
let data = std::fs::read_to_string(log_path)?;
|
||||||
let log = AsanLog::parse(data).unwrap();
|
let log = AsanLog::parse(data).unwrap();
|
||||||
|
|
||||||
assert_eq!(log.sanitizer, sanitizer);
|
assert_eq!(log.sanitizer, sanitizer);
|
||||||
assert_eq!(log.fault_type, fault_type);
|
assert_eq!(log.fault_type, fault_type);
|
||||||
assert_eq!(log.call_stack.len(), call_stack_len);
|
assert_eq!(log.call_stack.len(), call_stack_len);
|
||||||
|
assert_eq!(log.scariness_score, scariness_score);
|
||||||
|
assert_eq!(log.scariness_description, scariness_description);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,8 @@ class Report(BaseModel):
|
|||||||
asan_log: Optional[str]
|
asan_log: Optional[str]
|
||||||
task_id: UUID
|
task_id: UUID
|
||||||
job_id: UUID
|
job_id: UUID
|
||||||
|
scariness_score: Optional[int]
|
||||||
|
scariness_description: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
class ADODuplicateTemplate(BaseModel):
|
class ADODuplicateTemplate(BaseModel):
|
||||||
|
Reference in New Issue
Block a user