1 /*
2 * Copyright (C) 2023 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 #include <BnTestService.h>
18 #include <fuzzbinder/libbinder_driver.h>
19
20 #include <binder/IPCThreadState.h>
21 #include <log/log.h>
22
23 #include <private/android_filesystem_config.h>
24
25 using android::binder::Status;
26
27 namespace android {
28
29 enum class CrashType {
30 NONE,
31 ON_PLAIN,
32 ON_BINDER,
33 ON_KNOWN_UID,
34 ON_SYSTEM_AID,
35 ON_ROOT_AID,
36 ON_DUMP_TRANSACT,
37 ON_SHELL_CMD_TRANSACT,
38 CRASH_ALWAYS,
39 };
40
41 // This service is to verify that fuzzService is functioning properly
42 class TestService : public BnTestService {
43 public:
TestService(CrashType crash)44 TestService(CrashType crash) : mCrash(crash) {}
45
onData()46 void onData() {
47 switch (mCrash) {
48 case CrashType::ON_PLAIN: {
49 LOG_ALWAYS_FATAL("Expected crash, PLAIN.");
50 break;
51 }
52 case CrashType::ON_KNOWN_UID: {
53 if (IPCThreadState::self()->getCallingUid() == getuid()) {
54 LOG_ALWAYS_FATAL("Expected crash, KNOWN_UID.");
55 }
56 break;
57 }
58 case CrashType::ON_SYSTEM_AID: {
59 if (IPCThreadState::self()->getCallingUid() == AID_SYSTEM) {
60 LOG_ALWAYS_FATAL("Expected crash, AID_SYSTEM.");
61 }
62 break;
63 }
64 case CrashType::ON_ROOT_AID: {
65 if (IPCThreadState::self()->getCallingUid() == AID_ROOT) {
66 LOG_ALWAYS_FATAL("Expected crash, AID_ROOT.");
67 }
68 break;
69 }
70 default:
71 break;
72 }
73 }
74
setIntData(int)75 Status setIntData(int /*input*/) override {
76 onData();
77 return Status::ok();
78 }
79
setCharData(char16_t)80 Status setCharData(char16_t /*input*/) override {
81 onData();
82 return Status::ok();
83 }
84
setBooleanData(bool)85 Status setBooleanData(bool /*input*/) override {
86 onData();
87 return Status::ok();
88 }
89
setService(const sp<ITestService> & service)90 Status setService(const sp<ITestService>& service) override {
91 onData();
92 if (mCrash == CrashType::ON_BINDER && service != nullptr) {
93 LOG_ALWAYS_FATAL("Expected crash, BINDER.");
94 }
95 return Status::ok();
96 }
97
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)98 status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override {
99 if (mCrash == CrashType::ON_DUMP_TRANSACT && code == DUMP_TRANSACTION) {
100 LOG_ALWAYS_FATAL("Expected crash, DUMP.");
101 } else if (mCrash == CrashType::ON_SHELL_CMD_TRANSACT &&
102 code == SHELL_COMMAND_TRANSACTION) {
103 LOG_ALWAYS_FATAL("Expected crash, SHELL_CMD.");
104 }
105 return BnTestService::onTransact(code, data, reply, flags);
106 }
107
108 private:
109 CrashType mCrash;
110 };
111
112 CrashType gCrashType = CrashType::NONE;
113
LLVMFuzzerInitialize(int * argc,char *** argv)114 extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv) {
115 if (*argc < 2) {
116 // This fuzzer is also used as test fuzzer to check infra pipeline.
117 // It should always run and find a crash in TestService.
118 gCrashType = CrashType::CRASH_ALWAYS;
119 return 0;
120 }
121
122 std::string arg = std::string((*argv)[1]);
123
124 // ignore first argument, because we consume it
125 (*argv)[1] = (*argv[0]);
126 (*argc)--;
127 (*argv)++;
128
129 if (arg == "PLAIN") {
130 gCrashType = CrashType::ON_PLAIN;
131 } else if (arg == "KNOWN_UID") {
132 gCrashType = CrashType::ON_KNOWN_UID;
133 } else if (arg == "AID_SYSTEM") {
134 gCrashType = CrashType::ON_SYSTEM_AID;
135 } else if (arg == "AID_ROOT") {
136 gCrashType = CrashType::ON_ROOT_AID;
137 } else if (arg == "BINDER") {
138 gCrashType = CrashType::ON_BINDER;
139 } else if (arg == "DUMP") {
140 gCrashType = CrashType::ON_DUMP_TRANSACT;
141 } else if (arg == "SHELL_CMD") {
142 gCrashType = CrashType::ON_SHELL_CMD_TRANSACT;
143 } else {
144 printf("INVALID ARG\n");
145 exit(0); // success because this is a crash test
146 }
147
148 return 0;
149 }
150
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)151 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
152 if (gCrashType == CrashType::CRASH_ALWAYS) {
153 LOG_ALWAYS_FATAL("Expected crash, This fuzzer will always crash.");
154 }
155 auto service = sp<TestService>::make(gCrashType);
156 fuzzService(service, FuzzedDataProvider(data, size));
157 return 0;
158 }
159
160 } // namespace android
161