Various frida/ashmem fixes (#116)

* Fix incorrect encoding of and imm: use a register for now

* Fix assumption regarding length of ashmem clients list

* Make harness less chatty

* Fix refcounting in the ashmem server

* Always work around the frida allocate-near bug, not just when doing asan.

* Add support for ashmem on devices which have a boot secret, but don't use it

* Formatting
This commit is contained in:
s1341 2021-05-21 14:34:35 +03:00 committed by GitHub
parent bfbaa7ae83
commit 533a93ddd6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 49 deletions

View File

@ -87,7 +87,7 @@ extern "C" int afl_libfuzzer_init() {
static char * allocation = NULL;
__attribute__((noinline))
void func3( char * alloc) {
printf("func3\n");
//printf("func3\n");
if (random() == 0) {
alloc[0x1ff] = 0xde;
printf("alloc[0x200]: %d\n", alloc[0x200]);
@ -96,12 +96,12 @@ void func3( char * alloc) {
__attribute__((noinline))
void func2() {
allocation = (char*)malloc(0xff);
printf("func2\n");
//printf("func2\n");
func3(allocation);
}
__attribute__((noinline))
void func1() {
printf("func1\n");
//printf("func1\n");
func2();
}
// Entry point for LibFuzzer.

View File

@ -17,7 +17,7 @@ use serde::{Deserialize, Serialize};
use std::{
cell::RefCell,
io::{Read, Write},
rc::Rc,
rc::{Rc, Weak},
sync::{Arc, Condvar, Mutex},
};
@ -167,8 +167,8 @@ impl ShMemProvider for ServedShMemProvider {
fn release_map(&mut self, map: &mut Self::Mem) {
let (refcount, _) = self
.send_receive(AshmemRequest::Deregister(map.server_fd))
.expect("Could not communicate to AshMem server!");
if refcount == 0 {
.expect("Could not communicate with AshMem server!");
if refcount == 1 {
unsafe {
ManuallyDrop::drop(&mut map.inner);
}
@ -211,7 +211,7 @@ impl AshmemClient {
pub struct AshmemService {
provider: AshmemShMemProvider,
clients: HashMap<RawFd, AshmemClient>,
all_maps: HashMap<i32, Rc<RefCell<AshmemShMem>>>,
all_maps: HashMap<i32, Weak<RefCell<AshmemShMem>>>,
}
#[derive(Debug)]
@ -252,9 +252,14 @@ impl AshmemService {
};
Ok(AshmemResponse::Id(client_id))
}
AshmemRequest::NewMap(map_size) => Ok(AshmemResponse::Mapping(Rc::new(RefCell::new(
self.provider.new_map(map_size)?,
)))),
AshmemRequest::NewMap(map_size) => {
let new_map = self.provider.new_map(map_size)?;
let description = new_map.description();
let new_rc = Rc::new(RefCell::new(new_map));
self.all_maps
.insert(description.id.to_int(), Rc::downgrade(&new_rc));
Ok(AshmemResponse::Mapping(new_rc))
}
AshmemRequest::ExistingMap(description) => {
let client = self.clients.get_mut(&client_id).unwrap();
if client.maps.contains_key(&description.id.to_int()) {
@ -269,25 +274,27 @@ impl AshmemService {
.unwrap()
.clone(),
))
} else if self.all_maps.contains_key(&description.id.to_int()) {
} else {
Ok(AshmemResponse::Mapping(
self.all_maps
.get_mut(&description.id.to_int())
.unwrap()
.clone(),
.clone()
.upgrade()
.unwrap(),
))
} else {
let new_rc =
Rc::new(RefCell::new(self.provider.from_description(description)?));
self.all_maps
.insert(description.id.to_int(), new_rc.clone());
Ok(AshmemResponse::Mapping(new_rc))
}
}
AshmemRequest::Deregister(map_id) => {
let client = self.clients.get_mut(&client_id).unwrap();
let map = client.maps.entry(map_id).or_default().pop().unwrap();
Ok(AshmemResponse::RefCount(Rc::strong_count(&map) as u32))
let maps = client.maps.entry(map_id).or_default();
if maps.is_empty() {
Ok(AshmemResponse::RefCount(0u32))
} else {
Ok(AshmemResponse::RefCount(
Rc::strong_count(&maps.pop().unwrap()) as u32,
))
}
}
};
//println!("send ashmem client: {}, response: {:?}", client_id, &response);

View File

@ -656,7 +656,13 @@ pub mod unix_shmem {
if let Ok(boot_id) =
std::fs::read_to_string("/proc/sys/kernel/random/boot_id")
{
format!("{}{}", "/dev/ashmem", boot_id).trim().to_string()
let path_str =
format!("{}{}", "/dev/ashmem", boot_id).trim().to_string();
if std::path::Path::new(&path_str).exists() {
path_str
} else {
"/dev/ashmem".to_string()
}
} else {
"/dev/ashmem".to_string()
},

View File

@ -745,30 +745,6 @@ impl AsanRuntime {
/// instance after this function has been called, as the generated blobs would become
/// invalid!
pub fn init(&mut self, modules_to_instrument: &[PathBuf]) {
// workaround frida's frida-gum-allocate-near bug:
unsafe {
for _ in 0..512 {
mmap(
std::ptr::null_mut(),
128 * 1024,
ProtFlags::PROT_NONE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
0,
)
.expect("Failed to map dummy regions for frida workaround");
mmap(
std::ptr::null_mut(),
4 * 1024 * 1024,
ProtFlags::PROT_NONE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE,
-1,
0,
)
.expect("Failed to map dummy regions for frida workaround");
}
}
unsafe {
ASAN_ERRORS = Some(AsanErrors::new());
}
@ -1443,7 +1419,7 @@ impl AsanRuntime {
}
#[allow(clippy::unused_self)]
fn generate_shadow_check_exact_blob(&mut self, val: u32) -> Box<[u8]> {
fn generate_shadow_check_exact_blob(&mut self, val: u64) -> Box<[u8]> {
let shadow_bit = Allocator::get().shadow_bit as u32;
macro_rules! shadow_check_exact {
($ops:ident, $val:expr) => {dynasm!($ops
@ -1460,9 +1436,11 @@ impl AsanRuntime {
; lsr x1, x1, #16
; lsr x1, x1, x0
; .dword -717536768 // 0xd53b4200 //mrs x0, NZCV
; and x1, x1, #$val as u64
; cmp x1, #$val
; b.eq >done
; stp x2, x3, [sp, #-0x10]!
; mov x2, $val
; ands x1, x1, x2
; ldp x2, x3, [sp], 0x10
; b.ne >done
; adr x1, >done
; nop // will be replaced by b to report

View File

@ -36,6 +36,8 @@ use num_traits::cast::FromPrimitive;
use rangemap::RangeMap;
use std::{path::PathBuf, rc::Rc};
use nix::sys::mman::{mmap, MapFlags, ProtFlags};
use crate::{asan_rt::AsanRuntime, FridaOptions};
/// An helper that feeds [`FridaInProcessExecutor`] with user-supplied instrumentation
@ -216,6 +218,30 @@ impl<'a> FridaInstrumentationHelper<'a> {
_harness_module_name: &str,
modules_to_instrument: &'a [PathBuf],
) -> Self {
// workaround frida's frida-gum-allocate-near bug:
unsafe {
for _ in 0..512 {
mmap(
std::ptr::null_mut(),
128 * 1024,
ProtFlags::PROT_NONE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE | MapFlags::MAP_NORESERVE,
-1,
0,
)
.expect("Failed to map dummy regions for frida workaround");
mmap(
std::ptr::null_mut(),
4 * 1024 * 1024,
ProtFlags::PROT_NONE,
MapFlags::MAP_ANONYMOUS | MapFlags::MAP_PRIVATE | MapFlags::MAP_NORESERVE,
-1,
0,
)
.expect("Failed to map dummy regions for frida workaround");
}
}
let mut helper = Self {
map: [0u8; MAP_SIZE],
previous_pc: [0u64; 1],