1*e51878c1SAndroid Build Coastguard Worker // Copyright 2021, The Android Open Source Project 2*e51878c1SAndroid Build Coastguard Worker // 3*e51878c1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*e51878c1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*e51878c1SAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*e51878c1SAndroid Build Coastguard Worker // 7*e51878c1SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0 8*e51878c1SAndroid Build Coastguard Worker // 9*e51878c1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*e51878c1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*e51878c1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*e51878c1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*e51878c1SAndroid Build Coastguard Worker // limitations under the License. 14*e51878c1SAndroid Build Coastguard Worker 15*e51878c1SAndroid Build Coastguard Worker #![allow(missing_docs)] 16*e51878c1SAndroid Build Coastguard Worker #![allow(unused_must_use)] 17*e51878c1SAndroid Build Coastguard Worker #![no_main] 18*e51878c1SAndroid Build Coastguard Worker 19*e51878c1SAndroid Build Coastguard Worker use libfuzzer_sys::arbitrary::Arbitrary; 20*e51878c1SAndroid Build Coastguard Worker use libfuzzer_sys::fuzz_target; 21*e51878c1SAndroid Build Coastguard Worker use rustutils::system_properties; 22*e51878c1SAndroid Build Coastguard Worker use std::cell::RefCell; 23*e51878c1SAndroid Build Coastguard Worker use std::sync::Arc; 24*e51878c1SAndroid Build Coastguard Worker use std::sync::atomic::{AtomicBool, Ordering}; 25*e51878c1SAndroid Build Coastguard Worker use std::{fmt, thread, time}; 26*e51878c1SAndroid Build Coastguard Worker 27*e51878c1SAndroid Build Coastguard Worker thread_local! { 28*e51878c1SAndroid Build Coastguard Worker static COUNTER: RefCell<u64> = const{RefCell::new(0)}; 29*e51878c1SAndroid Build Coastguard Worker } 30*e51878c1SAndroid Build Coastguard Worker 31*e51878c1SAndroid Build Coastguard Worker #[derive(Arbitrary, Clone, Debug)] 32*e51878c1SAndroid Build Coastguard Worker enum WritableProperty { 33*e51878c1SAndroid Build Coastguard Worker Fuzzer1, 34*e51878c1SAndroid Build Coastguard Worker Fuzzer2, 35*e51878c1SAndroid Build Coastguard Worker } 36*e51878c1SAndroid Build Coastguard Worker 37*e51878c1SAndroid Build Coastguard Worker #[derive(Arbitrary, Clone, Debug)] 38*e51878c1SAndroid Build Coastguard Worker enum Property { 39*e51878c1SAndroid Build Coastguard Worker KeystoreBootLevel, 40*e51878c1SAndroid Build Coastguard Worker Random { name: String }, 41*e51878c1SAndroid Build Coastguard Worker Unique, 42*e51878c1SAndroid Build Coastguard Worker Writable { prop: WritableProperty }, 43*e51878c1SAndroid Build Coastguard Worker } 44*e51878c1SAndroid Build Coastguard Worker 45*e51878c1SAndroid Build Coastguard Worker impl fmt::Display for Property { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result46*e51878c1SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 47*e51878c1SAndroid Build Coastguard Worker write!(f, "{}", match self { 48*e51878c1SAndroid Build Coastguard Worker Property::KeystoreBootLevel => "keystore.boot_level".to_string(), 49*e51878c1SAndroid Build Coastguard Worker Property::Random { name } => name.to_string(), 50*e51878c1SAndroid Build Coastguard Worker Property::Unique => COUNTER.with(|counter| { 51*e51878c1SAndroid Build Coastguard Worker let val = *counter.borrow(); 52*e51878c1SAndroid Build Coastguard Worker *counter.borrow_mut() += 1; 53*e51878c1SAndroid Build Coastguard Worker format!("unique.fuzz.prop.{}", val) 54*e51878c1SAndroid Build Coastguard Worker }), 55*e51878c1SAndroid Build Coastguard Worker Property::Writable { prop } => prop.to_string(), 56*e51878c1SAndroid Build Coastguard Worker }) 57*e51878c1SAndroid Build Coastguard Worker } 58*e51878c1SAndroid Build Coastguard Worker } 59*e51878c1SAndroid Build Coastguard Worker 60*e51878c1SAndroid Build Coastguard Worker impl fmt::Display for WritableProperty { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result61*e51878c1SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 62*e51878c1SAndroid Build Coastguard Worker write!(f, "{}", match self { 63*e51878c1SAndroid Build Coastguard Worker WritableProperty::Fuzzer1 => "unique.fuzz.prop".to_string(), 64*e51878c1SAndroid Build Coastguard Worker WritableProperty::Fuzzer2 => "unique.fuzz.two.prop".to_string(), 65*e51878c1SAndroid Build Coastguard Worker }) 66*e51878c1SAndroid Build Coastguard Worker } 67*e51878c1SAndroid Build Coastguard Worker } 68*e51878c1SAndroid Build Coastguard Worker 69*e51878c1SAndroid Build Coastguard Worker #[derive(Arbitrary, Debug)] 70*e51878c1SAndroid Build Coastguard Worker enum Command { 71*e51878c1SAndroid Build Coastguard Worker Read { prop: Property }, 72*e51878c1SAndroid Build Coastguard Worker Write { prop: WritableProperty, value: String }, 73*e51878c1SAndroid Build Coastguard Worker WatcherRead { prop: Property }, 74*e51878c1SAndroid Build Coastguard Worker WatcherWait { value: u8 }, 75*e51878c1SAndroid Build Coastguard Worker } 76*e51878c1SAndroid Build Coastguard Worker 77*e51878c1SAndroid Build Coastguard Worker fuzz_target!(|commands: Vec<Command>| { 78*e51878c1SAndroid Build Coastguard Worker for command in commands { 79*e51878c1SAndroid Build Coastguard Worker match command { 80*e51878c1SAndroid Build Coastguard Worker Command::Read { prop } => { 81*e51878c1SAndroid Build Coastguard Worker system_properties::read(&prop.to_string()); 82*e51878c1SAndroid Build Coastguard Worker } 83*e51878c1SAndroid Build Coastguard Worker Command::Write { prop, value } => { 84*e51878c1SAndroid Build Coastguard Worker system_properties::write(&prop.to_string(), &value); 85*e51878c1SAndroid Build Coastguard Worker } 86*e51878c1SAndroid Build Coastguard Worker Command::WatcherRead { prop } => { 87*e51878c1SAndroid Build Coastguard Worker if let Ok(mut watcher) = system_properties::PropertyWatcher::new(&prop.to_string()) { 88*e51878c1SAndroid Build Coastguard Worker watcher.read(|_n, v| Ok(v.to_string())); 89*e51878c1SAndroid Build Coastguard Worker } 90*e51878c1SAndroid Build Coastguard Worker } 91*e51878c1SAndroid Build Coastguard Worker Command::WatcherWait { value } => { 92*e51878c1SAndroid Build Coastguard Worker // We want to ensure that we choose a property that can be written, 93*e51878c1SAndroid Build Coastguard Worker // or else we'd just have to implement a timeout and do nothing, 94*e51878c1SAndroid Build Coastguard Worker // so we use a hardcoded valid property. 95*e51878c1SAndroid Build Coastguard Worker let prop_str = "keystore.boot_level"; 96*e51878c1SAndroid Build Coastguard Worker let waited = Arc::new(AtomicBool::new(false)); 97*e51878c1SAndroid Build Coastguard Worker let waited_clone = waited.clone(); 98*e51878c1SAndroid Build Coastguard Worker // Spawn a thread that will wait for a change to the property. 99*e51878c1SAndroid Build Coastguard Worker let waiter = thread::spawn(move || { 100*e51878c1SAndroid Build Coastguard Worker let result = match system_properties::PropertyWatcher::new(prop_str) { 101*e51878c1SAndroid Build Coastguard Worker Ok(mut watcher) => watcher.wait(None), 102*e51878c1SAndroid Build Coastguard Worker Err(e) => Err(e), 103*e51878c1SAndroid Build Coastguard Worker }; 104*e51878c1SAndroid Build Coastguard Worker waited_clone.store(true, Ordering::Relaxed); 105*e51878c1SAndroid Build Coastguard Worker result 106*e51878c1SAndroid Build Coastguard Worker }); 107*e51878c1SAndroid Build Coastguard Worker // Write the property in a loop (so we're sure to follow the wait call). 108*e51878c1SAndroid Build Coastguard Worker let mut cur_value = value; 109*e51878c1SAndroid Build Coastguard Worker while !waited.load(Ordering::Relaxed) { 110*e51878c1SAndroid Build Coastguard Worker thread::sleep(time::Duration::from_millis(1)); 111*e51878c1SAndroid Build Coastguard Worker system_properties::write(prop_str, &cur_value.to_string()); 112*e51878c1SAndroid Build Coastguard Worker cur_value = cur_value.wrapping_add(1); 113*e51878c1SAndroid Build Coastguard Worker } 114*e51878c1SAndroid Build Coastguard Worker waiter.join(); 115*e51878c1SAndroid Build Coastguard Worker } 116*e51878c1SAndroid Build Coastguard Worker } 117*e51878c1SAndroid Build Coastguard Worker } 118*e51878c1SAndroid Build Coastguard Worker }); 119