1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <securec.h>
17 #include <thread>
18
19 #include "iservice_registry.h"
20 #include "net_diag_callback_stub.h"
21 #include "netsys_native_client.h"
22 #include "notify_callback_stub.h"
23 #include "singleton.h"
24 #include "system_ability_definition.h"
25 #define private public
26 #include "iptables_wrapper.h"
27 #include "netsys_native_service.h"
28 #include "netsys_native_service_stub.h"
29
30 namespace OHOS {
31 namespace NetManagerStandard {
32 namespace {
33 const uint8_t *g_baseFuzzData = nullptr;
34 size_t g_baseFuzzSize = 0;
35 size_t g_baseFuzzPos;
36 constexpr size_t STR_LEN = 10;
37 constexpr int32_t NUMBER_TWO = 2;
38 constexpr int32_t NUMBER_ONE = 1;
39 bool g_isWaitAsync = false;
40 } // namespace
41
GetData()42 template <class T> T GetData()
43 {
44 T object{};
45 size_t objectSize = sizeof(object);
46 if (g_baseFuzzData == nullptr || objectSize > g_baseFuzzSize - g_baseFuzzPos) {
47 return object;
48 }
49 errno_t ret = memcpy_s(&object, objectSize, g_baseFuzzData + g_baseFuzzPos, objectSize);
50 if (ret != EOK) {
51 return {};
52 }
53 g_baseFuzzPos += objectSize;
54 return object;
55 }
56
GetStringFromData(int strlen)57 std::string GetStringFromData(int strlen)
58 {
59 char cstr[strlen];
60 cstr[strlen - 1] = '\0';
61 for (int i = 0; i < strlen - 1; i++) {
62 cstr[i] = GetData<char>();
63 }
64 std::string str(cstr);
65 return str;
66 }
67
68 class NetDiagCallbackControllerFuzzTest : public IRemoteStub<NetsysNative::INetDiagCallback> {
69 public:
NetDiagCallbackControllerFuzzTest()70 NetDiagCallbackControllerFuzzTest()
71 {
72 memberFuncMap_[static_cast<uint32_t>(NetsysNative::NetDiagInterfaceCode::ON_NOTIFY_PING_RESULT)] =
73 &NetDiagCallbackControllerFuzzTest::CmdNotifyPingResult;
74 }
75 virtual ~NetDiagCallbackControllerFuzzTest() = default;
76
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)77 int32_t OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) override
78 {
79 NETNATIVE_LOGI("Stub call start, code:[%{public}d]", code);
80 std::u16string myDescriptor = NetsysNative::NetDiagCallbackStub::GetDescriptor();
81 std::u16string remoteDescriptor = data.ReadInterfaceToken();
82 if (myDescriptor != remoteDescriptor) {
83 NETNATIVE_LOGE("Descriptor checked failed");
84 return NetManagerStandard::NETMANAGER_ERR_DESCRIPTOR_MISMATCH;
85 }
86
87 auto itFunc = memberFuncMap_.find(code);
88 if (itFunc != memberFuncMap_.end()) {
89 auto requestFunc = itFunc->second;
90 if (requestFunc != nullptr) {
91 return (this->*requestFunc)(data, reply);
92 }
93 }
94
95 NETNATIVE_LOGI("Stub default case, need check");
96 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
97 }
98
OnNotifyPingResult(const NetsysNative::NetDiagPingResult & pingResult)99 int32_t OnNotifyPingResult(const NetsysNative::NetDiagPingResult &pingResult) override
100 {
101 g_isWaitAsync = false;
102 NETNATIVE_LOGI(
103 "OnNotifyPingResult received dateSize_:%{public}d payloadSize_:%{public}d transCount_:%{public}d "
104 "recvCount_:%{public}d",
105 pingResult.dateSize_, pingResult.payloadSize_, pingResult.transCount_, pingResult.recvCount_);
106 return NetManagerStandard::NETMANAGER_SUCCESS;
107 }
108
109 private:
110 using NetDiagCallbackFunc = int32_t (NetDiagCallbackControllerFuzzTest::*)(MessageParcel &, MessageParcel &);
111
112 private:
CmdNotifyPingResult(MessageParcel & data,MessageParcel & reply)113 int32_t CmdNotifyPingResult(MessageParcel &data, MessageParcel &reply)
114 {
115 NetsysNative::NetDiagPingResult pingResult;
116 if (!NetsysNative::NetDiagPingResult::Unmarshalling(data, pingResult)) {
117 return NetManagerStandard::NETMANAGER_ERR_READ_DATA_FAIL;
118 }
119
120 int32_t result = OnNotifyPingResult(pingResult);
121 if (!reply.WriteInt32(result)) {
122 return NetManagerStandard::NETMANAGER_ERR_WRITE_REPLY_FAIL;
123 }
124 return NetManagerStandard::NETMANAGER_SUCCESS;
125 }
126
127 private:
128 std::map<uint32_t, NetDiagCallbackFunc> memberFuncMap_;
129 };
130
131 static bool g_isInited = false;
Init()132 void Init()
133 {
134 nmd::IptablesWrapper::GetInstance();
135 g_isInited = DelayedSingleton<NetsysNative::NetsysNativeService>::GetInstance()->Init();
136 }
137
OnRemoteRequest(uint32_t code,MessageParcel & data)138 int32_t OnRemoteRequest(uint32_t code, MessageParcel &data)
139 {
140 if (!g_isInited) {
141 Init();
142 }
143
144 MessageParcel reply;
145 MessageOption option;
146
147 return DelayedSingleton<NetsysNative::NetsysNativeService>::GetInstance()->OnRemoteRequest(code, data, reply,
148 option);
149 }
150
WriteInterfaceToken(MessageParcel & data)151 bool WriteInterfaceToken(MessageParcel &data)
152 {
153 return data.WriteInterfaceToken(NetsysNative::NetsysNativeServiceStub::GetDescriptor());
154 }
155
WriteInterfaceTokenCallback(MessageParcel & data)156 bool WriteInterfaceTokenCallback(MessageParcel &data)
157 {
158 return data.WriteInterfaceToken(NetsysNative::NotifyCallbackStub::GetDescriptor());
159 }
160
IsDataAndSizeValid(const uint8_t * data,size_t size,MessageParcel & dataParcel)161 bool IsDataAndSizeValid(const uint8_t *data, size_t size, MessageParcel &dataParcel)
162 {
163 if ((data == nullptr) || (size == 0)) {
164 return false;
165 }
166 g_baseFuzzData = data;
167 g_baseFuzzSize = size;
168 g_baseFuzzPos = 0;
169
170 return WriteInterfaceToken(dataParcel);
171 }
172
NetDiagGetSocketInfoFuzzTest(const uint8_t * data,size_t size)173 void NetDiagGetSocketInfoFuzzTest(const uint8_t *data, size_t size)
174 {
175 MessageParcel dataParcel;
176 if (!IsDataAndSizeValid(data, size, dataParcel)) {
177 return;
178 }
179 const int maxProtoType = 5;
180 NetsysNative::NetDiagProtocolType protoclType =
181 static_cast<NetsysNative::NetDiagProtocolType>(GetData<uint8_t>() % maxProtoType);
182 dataParcel.WriteUint8(static_cast<uint8_t>(protoclType));
183 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_SOCKETS_INFO),
184 dataParcel);
185 }
186
NetDiagGetRouteTableFuzzTest(const uint8_t * data,size_t size)187 void NetDiagGetRouteTableFuzzTest(const uint8_t *data, size_t size)
188 {
189 MessageParcel dataParcel;
190 if (!IsDataAndSizeValid(data, size, dataParcel)) {
191 return;
192 }
193 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_ROUTE_TABLE),
194 dataParcel);
195 }
196
NetDiagUpdateInterfaceConfigFuzzTest(const uint8_t * data,size_t size)197 void NetDiagUpdateInterfaceConfigFuzzTest(const uint8_t *data, size_t size)
198 {
199 MessageParcel dataParcel;
200 if (!IsDataAndSizeValid(data, size, dataParcel)) {
201 return;
202 }
203 bool isAdd = (GetData<int32_t>() % NUMBER_TWO == NUMBER_ONE) ? true : false;
204 OHOS::NetsysNative::NetDiagIfaceConfig config;
205 config.ifaceName_ = GetStringFromData(STR_LEN);
206 config.linkEncap_ = GetStringFromData(STR_LEN);
207 config.macAddr_ = GetStringFromData(STR_LEN);
208 config.ipv4Addr_ = GetStringFromData(STR_LEN);
209 config.ipv4Bcast_ = GetStringFromData(STR_LEN);
210 config.ipv4Mask_ = GetStringFromData(STR_LEN);
211 config.mtu_ = GetData<uint32_t>();
212 config.txQueueLen_ = GetData<uint32_t>();
213 config.rxBytes_ = GetData<int32_t>();
214 config.txBytes_ = GetData<int32_t>();
215
216 if (!config.Marshalling(dataParcel)) {
217 return;
218 }
219 dataParcel.WriteString(GetStringFromData(STR_LEN));
220 dataParcel.WriteBool(isAdd);
221 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_UPDATE_IFACE_CONFIG),
222 dataParcel);
223 }
224
NetDiagSetInterfaceActiveFuzzTest(const uint8_t * data,size_t size)225 void NetDiagSetInterfaceActiveFuzzTest(const uint8_t *data, size_t size)
226 {
227 MessageParcel dataParcel;
228 if (!IsDataAndSizeValid(data, size, dataParcel)) {
229 return;
230 }
231 const int numberTow = 2;
232 std::string iFaceName = GetStringFromData(STR_LEN);
233 bool isUp = GetData<uint32_t>() % numberTow == 0;
234
235 dataParcel.WriteString(iFaceName);
236 dataParcel.WriteBool(isUp);
237
238 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_SET_IFACE_ACTIVE_STATE),
239 dataParcel);
240 }
241
NetDiagGetInterfaceConfigFuzzTest(const uint8_t * data,size_t size)242 void NetDiagGetInterfaceConfigFuzzTest(const uint8_t *data, size_t size)
243 {
244 MessageParcel dataParcel;
245 if (!IsDataAndSizeValid(data, size, dataParcel)) {
246 return;
247 }
248
249 std::string iFaceName = GetStringFromData(STR_LEN);
250 dataParcel.WriteString(iFaceName);
251 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_IFACE_CONFIG),
252 dataParcel);
253 }
254
NetDiagPingFuzzTest(const uint8_t * data,size_t size)255 void NetDiagPingFuzzTest(const uint8_t *data, size_t size)
256 {
257 const int maxWaitSecond = 10;
258 const int numberTow = 2;
259 MessageParcel dataParcel;
260 if (!IsDataAndSizeValid(data, size, dataParcel)) {
261 return;
262 }
263 OHOS::NetsysNative::NetDiagPingOption pingOption;
264 pingOption.destination_ = GetStringFromData(STR_LEN);
265 pingOption.source_ = GetStringFromData(STR_LEN);
266 pingOption.count_ = GetData<int16_t>();
267 pingOption.dataSize_ = GetData<int16_t>();
268 pingOption.mark_ = GetData<int16_t>();
269 pingOption.ttl_ = GetData<int16_t>();
270 pingOption.timeOut_ = GetData<int16_t>();
271 pingOption.duration_ = GetData<int16_t>();
272 pingOption.flood_ = GetData<int16_t>() % numberTow == 0;
273
274 if (!pingOption.Marshalling(dataParcel)) {
275 return;
276 }
277
278 sptr<NetDiagCallbackControllerFuzzTest> callBack = new NetDiagCallbackControllerFuzzTest();
279
280 if (!dataParcel.WriteRemoteObject(callBack->AsObject().GetRefPtr())) {
281 return;
282 }
283
284 g_isWaitAsync = true;
285 OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_PING_HOST), dataParcel);
286 std::chrono::steady_clock::time_point tp1 = std::chrono::steady_clock::now();
287 while (g_isWaitAsync) {
288 std::this_thread::sleep_for(std::chrono::seconds(1));
289 std::chrono::steady_clock::time_point tp2 = std::chrono::steady_clock::now();
290 if (std::chrono::duration_cast<std::chrono::seconds>(tp2 - tp1).count() > maxWaitSecond) {
291 break;
292 }
293 }
294 }
295 } // namespace NetManagerStandard
296 } // namespace OHOS
297
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)298 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
299 {
300 /* Run your code on data */
301 OHOS::NetManagerStandard::NetDiagGetSocketInfoFuzzTest(data, size);
302 OHOS::NetManagerStandard::NetDiagGetRouteTableFuzzTest(data, size);
303 OHOS::NetManagerStandard::NetDiagUpdateInterfaceConfigFuzzTest(data, size);
304 OHOS::NetManagerStandard::NetDiagSetInterfaceActiveFuzzTest(data, size);
305 OHOS::NetManagerStandard::NetDiagGetInterfaceConfigFuzzTest(data, size);
306 OHOS::NetManagerStandard::NetDiagPingFuzzTest(data, size);
307 return 0;
308 }