xref: /aosp_15_r20/system/librustutils/system_properties_fuzzer.rs (revision e51878c104ea269309bae357ae559a9fff179380)
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