Add support for ASAN print_scariness (#359)

This commit is contained in:
bmc-msft
2020-12-02 11:33:22 -05:00
committed by GitHub
parent e6b55ab95a
commit 054989f232
6 changed files with 154 additions and 1 deletions

View File

@ -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,
} }

View File

@ -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,
}; };

View 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

View 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

View File

@ -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(())
} }

View File

@ -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):