1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #![allow(missing_docs)]
18 #![no_main]
19 
20 mod read_utils;
21 
22 use crate::read_utils::READ_FUNCS;
23 use binder::binder_impl::{
24     Binder, BorrowedParcel, IBinderInternal, Parcel, Stability, TransactionCode,
25 };
26 use binder::{
27     declare_binder_interface, BinderFeatures, Interface, Parcelable, ParcelableHolder, SpIBinder,
28     StatusCode,
29 };
30 use binder_random_parcel_rs::create_random_parcel;
31 use libfuzzer_sys::{arbitrary::Arbitrary, fuzz_target};
32 
33 #[derive(Arbitrary, Debug)]
34 enum ReadOperation {
35     SetDataPosition { pos: i32 },
36     GetDataSize,
37     ReadParcelableHolder { is_vintf: bool },
38     ReadBasicTypes { instructions: Vec<usize> },
39 }
40 
41 #[derive(Arbitrary, Debug)]
42 enum Operation<'a> {
43     Transact { code: u32, flag: u32, data: &'a [u8] },
44     Append { start: i32, len: i32, data1: &'a [u8], data2: &'a [u8], append_all: bool },
45     Read { read_operations: Vec<ReadOperation>, data: &'a [u8] },
46 }
47 
48 /// Interface to fuzz transact with random parcel
49 pub trait BinderTransactTest: Interface {}
50 
51 declare_binder_interface! {
52     BinderTransactTest["Binder_Transact_Test"] {
53         native: BnBinderTransactTest(on_transact),
54         proxy: BpBinderTransactTest,
55     }
56 }
57 
58 impl BinderTransactTest for Binder<BnBinderTransactTest> {}
59 
60 impl BinderTransactTest for BpBinderTransactTest {}
61 
62 impl BinderTransactTest for () {}
63 
on_transact( _service: &dyn BinderTransactTest, _code: TransactionCode, _parcel: &BorrowedParcel<'_>, _reply: &mut BorrowedParcel<'_>, ) -> Result<(), StatusCode>64 fn on_transact(
65     _service: &dyn BinderTransactTest,
66     _code: TransactionCode,
67     _parcel: &BorrowedParcel<'_>,
68     _reply: &mut BorrowedParcel<'_>,
69 ) -> Result<(), StatusCode> {
70     Err(StatusCode::UNKNOWN_ERROR)
71 }
72 
do_transact(code: u32, data: &[u8], flag: u32)73 fn do_transact(code: u32, data: &[u8], flag: u32) {
74     let p: Parcel = create_random_parcel(data);
75     let spibinder: Option<SpIBinder> =
76         Some(BnBinderTransactTest::new_binder((), BinderFeatures::default()).as_binder());
77     let _reply = spibinder.submit_transact(code, p, flag);
78 }
79 
do_append_fuzz(start: i32, len: i32, data1: &[u8], data2: &[u8], append_all: bool)80 fn do_append_fuzz(start: i32, len: i32, data1: &[u8], data2: &[u8], append_all: bool) {
81     let mut p1 = create_random_parcel(data1);
82     let p2 = create_random_parcel(data2);
83 
84     // Fuzz both append methods
85     if append_all {
86         match p1.append_all_from(&p2) {
87             Ok(result) => result,
88             Err(e) => {
89                 println!("Error occurred while appending a parcel using append_all_from: {:?}", e)
90             }
91         }
92     } else {
93         match p1.append_from(&p2, start, len) {
94             Ok(result) => result,
95             Err(e) => {
96                 println!("Error occurred while appending a parcel using append_from: {:?}", e)
97             }
98         }
99     };
100 }
101 
do_read_fuzz(read_operations: Vec<ReadOperation>, data: &[u8])102 fn do_read_fuzz(read_operations: Vec<ReadOperation>, data: &[u8]) {
103     let parcel = create_random_parcel(data);
104 
105     for operation in read_operations {
106         match operation {
107             ReadOperation::SetDataPosition { pos } => {
108                 // Safety: Safe if pos is less than current size of the parcel.
109                 // It relies on C++ code for bound checks
110                 unsafe {
111                     match parcel.set_data_position(pos) {
112                         Ok(result) => result,
113                         Err(e) => println!("error occurred while setting data position: {:?}", e),
114                     }
115                 }
116             }
117 
118             ReadOperation::GetDataSize => {
119                 let data_size = parcel.get_data_size();
120                 println!("data size from parcel: {:?}", data_size);
121             }
122 
123             ReadOperation::ReadParcelableHolder { is_vintf } => {
124                 let stability = if is_vintf { Stability::Vintf } else { Stability::Local };
125                 let mut holder: ParcelableHolder = ParcelableHolder::new(stability);
126                 match holder.read_from_parcel(parcel.borrowed_ref()) {
127                     Ok(result) => result,
128                     Err(err) => {
129                         println!("error occurred while reading from parcel: {:?}", err)
130                     }
131                 }
132             }
133 
134             ReadOperation::ReadBasicTypes { instructions } => {
135                 for instruction in instructions.iter() {
136                     let read_index = instruction % READ_FUNCS.len();
137                     READ_FUNCS[read_index](parcel.borrowed_ref());
138                 }
139             }
140         }
141     }
142 }
143 
144 fuzz_target!(|operation: Operation| {
145     match operation {
146         Operation::Transact { code, flag, data } => {
147             do_transact(code, data, flag);
148         }
149 
150         Operation::Append { start, len, data1, data2, append_all } => {
151             do_append_fuzz(start, len, data1, data2, append_all);
152         }
153 
154         Operation::Read { read_operations, data } => {
155             do_read_fuzz(read_operations, data);
156         }
157     }
158 });
159