• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }