1 /*
2  * Copyright (c) 2022-2024 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 "common_net_diag_callback_test.h"
20 #include "iservice_registry.h"
21 #include "net_diag_callback_stub.h"
22 #include "netsys_native_client.h"
23 #include "notify_callback_stub.h"
24 #include "singleton.h"
25 #include "system_ability_definition.h"
26 #define private public
27 #include "iptables_wrapper.h"
28 #include "netsys_native_service.h"
29 #include "netsys_native_service_stub.h"
30 
31 namespace OHOS {
32 namespace NetManagerStandard {
33 namespace {
34 const uint8_t *g_baseFuzzData = nullptr;
35 size_t g_baseFuzzSize = 0;
36 size_t g_baseFuzzPos;
37 constexpr size_t STR_LEN = 10;
38 constexpr int32_t NUMBER_TWO = 2;
39 constexpr int32_t NUMBER_ONE = 1;
40 bool g_isWaitAsync = false;
41 } // namespace
42 
NetDiagGetData()43 template <class T> T NetDiagGetData()
44 {
45     T object{};
46     size_t netDiagSize = sizeof(object);
47     if (g_baseFuzzData == nullptr || netDiagSize > g_baseFuzzSize - g_baseFuzzPos) {
48         return object;
49     }
50     errno_t ret = memcpy_s(&object, netDiagSize, g_baseFuzzData + g_baseFuzzPos, netDiagSize);
51     if (ret != EOK) {
52         return {};
53     }
54     g_baseFuzzPos += netDiagSize;
55     return object;
56 }
57 
NetDiagGetString(int strlen)58 std::string NetDiagGetString(int strlen)
59 {
60     char cstr[strlen];
61     cstr[strlen - 1] = '\0';
62     for (int i = 0; i < strlen - 1; i++) {
63         cstr[i] = NetDiagGetData<char>();
64     }
65     std::string str(cstr);
66     return str;
67 }
68 
69 static bool g_isInited = false;
Init()70 __attribute__((no_sanitize("cfi"))) void Init()
71 {
72     nmd::IptablesWrapper::GetInstance();
73     g_isInited = DelayedSingleton<NetsysNative::NetsysNativeService>::GetInstance()->Init();
74 }
75 
OnRemoteRequest(uint32_t code,MessageParcel & data)76 __attribute__((no_sanitize("cfi"))) int32_t OnRemoteRequest(uint32_t code, MessageParcel &data)
77 {
78     if (!g_isInited) {
79         Init();
80     }
81 
82     MessageParcel reply;
83     MessageOption option;
84 
85     return DelayedSingleton<NetsysNative::NetsysNativeService>::GetInstance()->OnRemoteRequest(code, data, reply,
86                                                                                                option);
87 }
88 
WriteInterfaceToken(MessageParcel & data)89 bool WriteInterfaceToken(MessageParcel &data)
90 {
91     return data.WriteInterfaceToken(NetsysNative::NetsysNativeServiceStub::GetDescriptor());
92 }
93 
WriteInterfaceTokenCallback(MessageParcel & data)94 bool WriteInterfaceTokenCallback(MessageParcel &data)
95 {
96     return data.WriteInterfaceToken(NetsysNative::NotifyCallbackStub::GetDescriptor());
97 }
98 
IsDataAndSizeValid(const uint8_t * data,size_t size,MessageParcel & dataParcel)99 bool IsDataAndSizeValid(const uint8_t *data, size_t size, MessageParcel &dataParcel)
100 {
101     if ((data == nullptr) || (size == 0)) {
102         return false;
103     }
104     g_baseFuzzData = data;
105     g_baseFuzzSize = size;
106     g_baseFuzzPos = 0;
107 
108     return WriteInterfaceToken(dataParcel);
109 }
110 
NetDiagGetSocketInfoFuzzTest(const uint8_t * data,size_t size)111 void NetDiagGetSocketInfoFuzzTest(const uint8_t *data, size_t size)
112 {
113     MessageParcel dataParcel;
114     if (!IsDataAndSizeValid(data, size, dataParcel)) {
115         return;
116     }
117     const int maxProtoType = 5;
118     NetsysNative::NetDiagProtocolType protoclType =
119         static_cast<NetsysNative::NetDiagProtocolType>(NetDiagGetData<uint8_t>() % maxProtoType);
120     dataParcel.WriteUint8(static_cast<uint8_t>(protoclType));
121     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_SOCKETS_INFO),
122                     dataParcel);
123 }
124 
NetDiagGetRouteTableFuzzTest(const uint8_t * data,size_t size)125 void NetDiagGetRouteTableFuzzTest(const uint8_t *data, size_t size)
126 {
127     MessageParcel dataParcel;
128     if (!IsDataAndSizeValid(data, size, dataParcel)) {
129         return;
130     }
131     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_ROUTE_TABLE),
132                     dataParcel);
133 }
134 
NetDiagUpdateInterfaceConfigFuzzTest(const uint8_t * data,size_t size)135 __attribute__((no_sanitize("cfi"))) void NetDiagUpdateInterfaceConfigFuzzTest(const uint8_t *data, size_t size)
136 {
137     MessageParcel dataParcel;
138     if (!IsDataAndSizeValid(data, size, dataParcel)) {
139         return;
140     }
141     bool isAdd = (NetDiagGetData<int32_t>() % NUMBER_TWO == NUMBER_ONE) ? true : false;
142     OHOS::NetsysNative::NetDiagIfaceConfig config;
143     config.ifaceName_ = NetDiagGetString(STR_LEN);
144     config.linkEncap_ = NetDiagGetString(STR_LEN);
145     config.macAddr_ = NetDiagGetString(STR_LEN);
146     config.ipv4Addr_ = NetDiagGetString(STR_LEN);
147     config.ipv4Bcast_ = NetDiagGetString(STR_LEN);
148     config.ipv4Mask_ = NetDiagGetString(STR_LEN);
149     config.mtu_ = NetDiagGetData<uint32_t>();
150     config.txQueueLen_ = NetDiagGetData<uint32_t>();
151     config.rxBytes_ = NetDiagGetData<int32_t>();
152     config.txBytes_ = NetDiagGetData<int32_t>();
153 
154     if (!config.Marshalling(dataParcel)) {
155         return;
156     }
157     dataParcel.WriteString(NetDiagGetString(STR_LEN));
158     dataParcel.WriteBool(isAdd);
159     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_UPDATE_IFACE_CONFIG),
160                     dataParcel);
161 }
162 
NetDiagSetInterfaceActiveFuzzTest(const uint8_t * data,size_t size)163 void NetDiagSetInterfaceActiveFuzzTest(const uint8_t *data, size_t size)
164 {
165     MessageParcel dataParcel;
166     if (!IsDataAndSizeValid(data, size, dataParcel)) {
167         return;
168     }
169     const int numberTow = 2;
170     std::string iFaceName = NetDiagGetString(STR_LEN);
171     bool isUp = NetDiagGetData<uint32_t>() % numberTow == 0;
172 
173     dataParcel.WriteString(iFaceName);
174     dataParcel.WriteBool(isUp);
175 
176     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_SET_IFACE_ACTIVE_STATE),
177                     dataParcel);
178 }
179 
NetDiagGetInterfaceConfigFuzzTest(const uint8_t * data,size_t size)180 void NetDiagGetInterfaceConfigFuzzTest(const uint8_t *data, size_t size)
181 {
182     MessageParcel dataParcel;
183     if (!IsDataAndSizeValid(data, size, dataParcel)) {
184         return;
185     }
186 
187     std::string iFaceName = NetDiagGetString(STR_LEN);
188     dataParcel.WriteString(iFaceName);
189     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_GET_IFACE_CONFIG),
190                     dataParcel);
191 }
192 
NetDiagPingFuzzTest(const uint8_t * data,size_t size)193 __attribute__((no_sanitize("cfi"))) void NetDiagPingFuzzTest(const uint8_t *data, size_t size)
194 {
195     const int maxWaitSecond = 10;
196     const int numberTow = 2;
197     MessageParcel dataParcel;
198     if (!IsDataAndSizeValid(data, size, dataParcel)) {
199         return;
200     }
201     OHOS::NetsysNative::NetDiagPingOption pingOption;
202     pingOption.destination_ = NetDiagGetString(STR_LEN);
203     pingOption.source_ = NetDiagGetString(STR_LEN);
204     pingOption.count_ = NetDiagGetData<int16_t>();
205     pingOption.dataSize_ = NetDiagGetData<int16_t>();
206     pingOption.mark_ = NetDiagGetData<int16_t>();
207     pingOption.ttl_ = NetDiagGetData<int16_t>();
208     pingOption.timeOut_ = NetDiagGetData<int16_t>();
209     pingOption.duration_ = NetDiagGetData<int16_t>();
210     pingOption.flood_ = NetDiagGetData<int16_t>() % numberTow == 0;
211 
212     if (!pingOption.Marshalling(dataParcel)) {
213         return;
214     }
215 
216     sptr<NetsysNative::NetDiagCallbackStubTest> callBack = new NetsysNative::NetDiagCallbackStubTest();
217     if (!dataParcel.WriteRemoteObject(callBack->AsObject().GetRefPtr())) {
218         return;
219     }
220 
221     g_isWaitAsync = true;
222     OnRemoteRequest(static_cast<uint32_t>(NetsysNative::NetsysInterfaceCode::NETSYS_NETDIAG_PING_HOST), dataParcel);
223     std::chrono::steady_clock::time_point tp1 = std::chrono::steady_clock::now();
224     while (g_isWaitAsync) {
225         std::this_thread::sleep_for(std::chrono::seconds(1));
226         std::chrono::steady_clock::time_point tp2 = std::chrono::steady_clock::now();
227         if (std::chrono::duration_cast<std::chrono::seconds>(tp2 - tp1).count() > maxWaitSecond) {
228             break;
229         }
230     }
231 }
232 } // namespace NetManagerStandard
233 } // namespace OHOS
234 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)235 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
236 {
237     /* Run your code on data */
238     OHOS::NetManagerStandard::NetDiagGetSocketInfoFuzzTest(data, size);
239     OHOS::NetManagerStandard::NetDiagGetRouteTableFuzzTest(data, size);
240     OHOS::NetManagerStandard::NetDiagUpdateInterfaceConfigFuzzTest(data, size);
241     OHOS::NetManagerStandard::NetDiagSetInterfaceActiveFuzzTest(data, size);
242     OHOS::NetManagerStandard::NetDiagGetInterfaceConfigFuzzTest(data, size);
243     OHOS::NetManagerStandard::NetDiagPingFuzzTest(data, size);
244     return 0;
245 }