1 /*
2 * Copyright (c) 2021-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 "hiview_service_ability_stub.h"
17
18 #include <unordered_map>
19 #include <vector>
20
21 #include "accesstoken_kit.h"
22 #include "ash_memory_utils.h"
23 #include "client/trace_collector.h"
24 #include "errors.h"
25 #include "hiview_err_code.h"
26 #include "ipc_skeleton.h"
27 #include "logger.h"
28
29 namespace OHOS {
30 namespace HiviewDFX {
31 namespace {
32 DEFINE_LOG_TAG("HiViewSA-HiViewServiceAbilityStub");
33 const std::string ASH_MEM_NAME = "HiviewLogLibrary SharedMemory";
34 constexpr uint32_t ASH_MEM_SIZE = 107 * 5000; // 535k
35
36 const std::unordered_map<uint32_t, std::string> ALL_PERMISSION_MAP = {
37 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_LIST),
38 "ohos.permission.READ_HIVIEW_SYSTEM"},
39 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_COPY),
40 "ohos.permission.READ_HIVIEW_SYSTEM"},
41 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_MOVE),
42 "ohos.permission.WRITE_HIVIEW_SYSTEM"},
43 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_REMOVE),
44 "ohos.permission.WRITE_HIVIEW_SYSTEM"},
45 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_SNAPSHOT_TRACE),
46 "ohos.permission.WRITE_HIVIEW_SYSTEM"},
47 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_DUMP_SNAPSHOT_TRACE),
48 "ohos.permission.READ_HIVIEW_SYSTEM"},
49 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_RECORDING_TRACE),
50 "ohos.permission.WRITE_HIVIEW_SYSTEM"},
51 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_ON),
52 "ohos.permission.READ_HIVIEW_SYSTEM"},
53 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_OFF),
54 "ohos.permission.READ_HIVIEW_SYSTEM"},
55 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_CLOSE_TRACE),
56 "ohos.permission.WRITE_HIVIEW_SYSTEM"},
57 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECOVER_TRACE),
58 "ohos.permission.WRITE_HIVIEW_SYSTEM"}
59 };
60
61 const std::unordered_map<uint32_t, std::string> TRACE_PERMISSION_MAP = {
62 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_SNAPSHOT_TRACE),
63 "ohos.permission.DUMP"},
64 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_DUMP_SNAPSHOT_TRACE),
65 "ohos.permission.DUMP"},
66 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_RECORDING_TRACE),
67 "ohos.permission.DUMP"},
68 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_ON),
69 "ohos.permission.DUMP"},
70 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_OFF),
71 "ohos.permission.DUMP"},
72 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_CLOSE_TRACE),
73 "ohos.permission.DUMP"},
74 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECOVER_TRACE),
75 "ohos.permission.DUMP"}
76 };
77
HasAccessPermission(uint32_t code,const std::unordered_map<uint32_t,std::string> & permissions)78 bool HasAccessPermission(uint32_t code, const std::unordered_map<uint32_t, std::string>& permissions)
79 {
80 using namespace Security::AccessToken;
81 auto iter = permissions.find(code);
82 if (iter == permissions.end()) {
83 return false;
84 }
85 AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID();
86 int verifyResult = AccessTokenKit::VerifyAccessToken(callerToken, iter->second);
87 if (verifyResult == PERMISSION_GRANTED) {
88 return true;
89 }
90 HIVIEW_LOGW("%{public}s not granted, code: %{public}u", iter->second.c_str(), code);
91 return false;
92 }
93
WriteTracePracelableToMessage(MessageParcel & dest,Parcelable & data)94 int32_t WriteTracePracelableToMessage(MessageParcel& dest, Parcelable& data)
95 {
96 if (!dest.WriteParcelable(&data)) {
97 HIVIEW_LOGW("failed to write TraceErrorCodeWrapper to parcel");
98 return TraceErrCode::ERR_WRITE_MSG_PARCEL;
99 }
100 return TraceErrCode::ERR_OK;
101 }
102 }
103
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)104 int32_t HiviewServiceAbilityStub::OnRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply,
105 MessageOption &option)
106 {
107 HIVIEW_LOGI("cmd = %{public}d, flags= %{public}d", code, option.GetFlags());
108 std::u16string descripter = HiviewServiceAbilityStub::GetDescriptor();
109 std::u16string remoteDescripter = data.ReadInterfaceToken();
110 if (descripter != remoteDescripter) {
111 return -ERR_INVALID_VALUE;
112 }
113 if (!IsPermissionGranted(code)) {
114 return HiviewNapiErrCode::ERR_PERMISSION_CHECK;
115 }
116 auto requestHandler = GetRequestHandler(code);
117 if (requestHandler == nullptr) {
118 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
119 }
120 return requestHandler(data, reply, option);
121 }
122
IsPermissionGranted(uint32_t code)123 bool HiviewServiceAbilityStub::IsPermissionGranted(uint32_t code)
124 {
125 return HasAccessPermission(code, ALL_PERMISSION_MAP) || HasAccessPermission(code, TRACE_PERMISSION_MAP);
126 }
127
GetRequestHandlers()128 std::unordered_map<uint32_t, RequestHandler> HiviewServiceAbilityStub::GetRequestHandlers()
129 {
130 static std::unordered_map<uint32_t, RequestHandler> requestHandlers = {
131 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_LIST),
132 std::bind(&HiviewServiceAbilityStub::HandleListRequest, this,
133 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
134 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_COPY),
135 std::bind(&HiviewServiceAbilityStub::HandleCopyRequest, this,
136 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
137 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_MOVE),
138 std::bind(&HiviewServiceAbilityStub::HandleMoveRequest, this,
139 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
140 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_REMOVE),
141 std::bind(&HiviewServiceAbilityStub::HandleRemoveRequest, this,
142 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)}
143 };
144 return requestHandlers;
145 }
146
GetTraceRequestHandlers()147 std::unordered_map<uint32_t, RequestHandler> HiviewServiceAbilityStub::GetTraceRequestHandlers()
148 {
149 static std::unordered_map<uint32_t, RequestHandler> requestHandlers = {
150 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_SNAPSHOT_TRACE),
151 std::bind(&HiviewServiceAbilityStub::HandleOpenSnapshotTraceRequest, this,
152 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
153 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_DUMP_SNAPSHOT_TRACE),
154 std::bind(&HiviewServiceAbilityStub::HandleDumpSnapshotTraceRequest, this,
155 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
156 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_OPEN_RECORDING_TRACE),
157 std::bind(&HiviewServiceAbilityStub::HandleOpenRecordingTraceRequest, this,
158 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
159 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_ON),
160 std::bind(&HiviewServiceAbilityStub::HandleRecordingTraceOnRequest, this,
161 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
162 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECORDING_TRACE_OFF),
163 std::bind(&HiviewServiceAbilityStub::HandleRecordingTraceOffRequest, this,
164 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
165 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_CLOSE_TRACE),
166 std::bind(&HiviewServiceAbilityStub::HandleCloseTraceRequest, this,
167 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)},
168 {static_cast<uint32_t>(HiviewServiceInterfaceCode::HIVIEW_SERVICE_ID_RECOVER_TRACE),
169 std::bind(&HiviewServiceAbilityStub::HandleRecoverTraceRequest, this,
170 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)}
171 };
172 return requestHandlers;
173 }
174
GetRequestHandler(uint32_t code)175 RequestHandler HiviewServiceAbilityStub::GetRequestHandler(uint32_t code)
176 {
177 std::vector<std::unordered_map<uint32_t, RequestHandler>> allHandlerMaps = {
178 GetRequestHandlers(),
179 GetTraceRequestHandlers()
180 };
181 for (auto handlerMap : allHandlerMaps) {
182 auto iter = handlerMap.find(code);
183 if (iter == handlerMap.end()) {
184 continue;
185 }
186 return iter->second;
187 }
188 HIVIEW_LOGE("function for handling request isn't found");
189 return nullptr;
190 }
191
HandleListRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)192 int32_t HiviewServiceAbilityStub::HandleListRequest(MessageParcel& data, MessageParcel& reply, MessageOption& option)
193 {
194 std::string logType;
195 if (!data.ReadString(logType)) {
196 HIVIEW_LOGE("cannot get log type");
197 return HiviewNapiErrCode::ERR_DEFAULT;
198 }
199 std::vector<HiviewFileInfo> fileInfos;
200 int32_t ret = List(logType, fileInfos);
201 if (ret != ERR_OK) {
202 return ret;
203 }
204 HIVIEW_LOGW("file list num:%{public}d", fileInfos.size());
205 sptr<Ashmem> ashmem = AshMemoryUtils::GetAshmem(ASH_MEM_NAME, ASH_MEM_SIZE);
206 if (ashmem == nullptr) {
207 HIVIEW_LOGE("ge ashmem failed.");
208 return HiviewNapiErrCode::ERR_DEFAULT;
209 }
210 std::vector<uint32_t> allSize;
211 if (!AshMemoryUtils::WriteBulkData<HiviewFileInfo>(fileInfos, ashmem, ASH_MEM_SIZE, allSize)) {
212 HIVIEW_LOGE("WriteBulkData failed.");
213 return HiviewNapiErrCode::ERR_DEFAULT;
214 }
215 if (!reply.WriteUInt32Vector(allSize)) {
216 HIVIEW_LOGE("write size failed.");
217 return HiviewNapiErrCode::ERR_DEFAULT;
218 }
219 if (!reply.WriteAshmem(ashmem)) {
220 HIVIEW_LOGE("write ashmem failed.");
221 return HiviewNapiErrCode::ERR_DEFAULT;
222 }
223 return ERR_OK;
224 }
225
HandleCopyRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)226 int32_t HiviewServiceAbilityStub::HandleCopyRequest(MessageParcel& data, MessageParcel& reply, MessageOption& option)
227 {
228 return HandleCopyOrMoveRequest(data, reply, option, false);
229 }
230
HandleMoveRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)231 int32_t HiviewServiceAbilityStub::HandleMoveRequest(MessageParcel& data, MessageParcel& reply, MessageOption& option)
232 {
233 return HandleCopyOrMoveRequest(data, reply, option, true);
234 }
235
HandleCopyOrMoveRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option,bool isMove)236 int32_t HiviewServiceAbilityStub::HandleCopyOrMoveRequest(
237 MessageParcel& data, MessageParcel& reply, MessageOption& option, bool isMove)
238 {
239 std::string logType;
240 if (!data.ReadString(logType)) {
241 HIVIEW_LOGW("cannot get logtype");
242 return HiviewNapiErrCode::ERR_DEFAULT;
243 }
244 std::string logName;
245 if (!data.ReadString(logName)) {
246 HIVIEW_LOGW("cannot get log type");
247 return HiviewNapiErrCode::ERR_DEFAULT;
248 }
249 std::string dest;
250 if (!data.ReadString(dest)) {
251 HIVIEW_LOGW("cannot get dest dir");
252 return HiviewNapiErrCode::ERR_DEFAULT;
253 }
254 if (dest.find("..") != std::string::npos) {
255 HIVIEW_LOGW("invalid dest: %{public}s", dest.c_str());
256 return HiviewNapiErrCode::ERR_DEFAULT;
257 }
258 int32_t ret = isMove ? Move(logType, logName, dest) : Copy(logType, logName, dest);
259 if (!reply.WriteInt32(ret)) {
260 return HiviewNapiErrCode::ERR_DEFAULT;
261 }
262 return ERR_OK;
263 }
264
HandleRemoveRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)265 int32_t HiviewServiceAbilityStub::HandleRemoveRequest(MessageParcel& data, MessageParcel& reply, MessageOption& option)
266 {
267 std::string logType;
268 if (!data.ReadString(logType)) {
269 HIVIEW_LOGW("cannot get log type");
270 return HiviewNapiErrCode::ERR_DEFAULT;
271 }
272 std::string logName;
273 if (!data.ReadString(logName)) {
274 HIVIEW_LOGW("cannot get log name");
275 return HiviewNapiErrCode::ERR_DEFAULT;
276 }
277 int32_t ret = Remove(logType, logName);
278 if (!reply.WriteInt32(ret)) {
279 return HiviewNapiErrCode::ERR_DEFAULT;
280 }
281 return ERR_OK;
282 }
283
HandleOpenSnapshotTraceRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)284 int32_t HiviewServiceAbilityStub::HandleOpenSnapshotTraceRequest(MessageParcel& data, MessageParcel& reply,
285 MessageOption& option)
286 {
287 std::vector<std::string> tagGroups;
288 if (!data.ReadStringVector(&tagGroups)) {
289 HIVIEW_LOGW("failed to read tag groups from parcel");
290 return TraceErrCode::ERR_READ_MSG_PARCEL;
291 }
292 auto ret = OpenSnapshotTrace(tagGroups);
293 return WriteTracePracelableToMessage(reply, ret);
294 }
295
HandleDumpSnapshotTraceRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)296 int32_t HiviewServiceAbilityStub::HandleDumpSnapshotTraceRequest(MessageParcel& data, MessageParcel& reply,
297 MessageOption& option)
298 {
299 int32_t caller = UCollectClient::TraceCollector::Caller::OTHER;
300 if (!data.ReadInt32(caller)) {
301 HIVIEW_LOGW("failed to read trace caller from parcel");
302 return TraceErrCode::ERR_READ_MSG_PARCEL;
303 }
304 auto ret = DumpSnapshotTrace(caller);
305 return WriteTracePracelableToMessage(reply, ret);
306 }
307
HandleOpenRecordingTraceRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)308 int32_t HiviewServiceAbilityStub::HandleOpenRecordingTraceRequest(MessageParcel& data, MessageParcel& reply,
309 MessageOption& option)
310 {
311 std::string tags;
312 if (!data.ReadString(tags)) {
313 HIVIEW_LOGW("failed to read tags from parcel");
314 return TraceErrCode::ERR_READ_MSG_PARCEL;
315 }
316 auto ret = OpenRecordingTrace(tags);
317 return WriteTracePracelableToMessage(reply, ret);
318 }
319
HandleRecordingTraceOnRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)320 int32_t HiviewServiceAbilityStub::HandleRecordingTraceOnRequest(MessageParcel& data, MessageParcel& reply,
321 MessageOption& option)
322 {
323 auto ret = RecordingTraceOn();
324 return WriteTracePracelableToMessage(reply, ret);
325 }
326
HandleRecordingTraceOffRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)327 int32_t HiviewServiceAbilityStub::HandleRecordingTraceOffRequest(MessageParcel& data, MessageParcel& reply,
328 MessageOption& option)
329 {
330 auto ret = RecordingTraceOff();
331 return WriteTracePracelableToMessage(reply, ret);
332 }
333
HandleCloseTraceRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)334 int32_t HiviewServiceAbilityStub::HandleCloseTraceRequest(MessageParcel& data, MessageParcel& reply,
335 MessageOption& option)
336 {
337 auto ret = CloseTrace();
338 return WriteTracePracelableToMessage(reply, ret);
339 }
340
HandleRecoverTraceRequest(MessageParcel & data,MessageParcel & reply,MessageOption & option)341 int32_t HiviewServiceAbilityStub::HandleRecoverTraceRequest(MessageParcel& data, MessageParcel& reply,
342 MessageOption& option)
343 {
344 auto ret = RecoverTrace();
345 return WriteTracePracelableToMessage(reply, ret);
346 }
347 } // namespace HiviewDFX
348 } // namespace OHOS