1 /*
2 * Copyright (c) 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 "res_sched_exe_service_stub.h"
17
18 #include <string_ex.h>
19
20 #include "ipc_skeleton.h"
21
22 #include "ipc_util.h"
23 #include "res_exe_type.h"
24 #include "res_sched_exe_common_utils.h"
25 #include "res_sched_exe_constants.h"
26 #include "res_sched_exe_log.h"
27
28 namespace OHOS {
29 namespace ResourceSchedule {
30 namespace {
31 constexpr int32_t PAYLOAD_MAX_SIZE = 4096;
32 constexpr int32_t KILL_PROCESS_FAILED = -1;
33 constexpr int32_t RSS_UID = 1096;
34 const std::string RES_TYPE_EXT = "extType";
35
IsValidToken(MessageParcel & data)36 bool IsValidToken(MessageParcel& data)
37 {
38 std::u16string descriptor = ResSchedExeServiceStub::GetDescriptor();
39 std::u16string remoteDescriptor = data.ReadInterfaceToken();
40 return descriptor == remoteDescriptor;
41 }
42
IsTypeVaild(uint32_t type)43 bool IsTypeVaild(uint32_t type)
44 {
45 return type >= ResExeType::RES_TYPE_FIRST && type < ResExeType::RES_TYPE_LAST;
46 }
47
IsTypeSync(uint32_t type)48 bool IsTypeSync(uint32_t type)
49 {
50 return IsTypeVaild(type) && type < ResExeType::RES_TYPE_SYNC_END;
51 }
52
IsTypeDebug(uint32_t type)53 bool IsTypeDebug(uint32_t type)
54 {
55 return type == ResExeType::RES_TYPE_DEBUG;
56 }
57
GetExtResType(uint32_t & resType,const nlohmann::json & context)58 bool GetExtResType(uint32_t& resType, const nlohmann::json& context)
59 {
60 if (resType != ResExeType::RES_TYPE_COMMON_SYNC && resType != ResExeType::RES_TYPE_COMMON_ASYNC) {
61 return true;
62 }
63 int type = 0;
64 if (!context.contains(RES_TYPE_EXT) || !context[RES_TYPE_EXT].is_string()
65 || !StrToInt(context[RES_TYPE_EXT], type)) {
66 RSSEXE_LOGE("use extend resType, but not send resTypeExt with payload");
67 return false;
68 }
69 resType = (uint32_t)type;
70 RSSEXE_LOGD("use extend resType = %{public}d.", resType);
71 return true;
72 }
73
IsCallingClientRss()74 bool IsCallingClientRss()
75 {
76 int32_t clientUid = IPCSkeleton::GetCallingUid();
77 RSSEXE_LOGD("calling client uid is %{public}d, allowed uid is %{public}d", clientUid, RSS_UID);
78 return RSS_UID == clientUid;
79 }
80 }
81
ResSchedExeServiceStub()82 ResSchedExeServiceStub::ResSchedExeServiceStub()
83 {
84 Init();
85 }
86
~ResSchedExeServiceStub()87 ResSchedExeServiceStub::~ResSchedExeServiceStub()
88 {
89 }
90
Init()91 void ResSchedExeServiceStub::Init()
92 {
93 }
94
ReportRequestInner(MessageParcel & data,MessageParcel & reply)95 int32_t ResSchedExeServiceStub::ReportRequestInner(MessageParcel& data, MessageParcel& reply)
96 {
97 uint32_t resType = 0;
98 int64_t value = 0;
99 nlohmann::json context;
100 if (!ParseParcel(data, resType, value, context)) {
101 WRITE_PARCEL(reply, Int32, ResIpcErrCode::RSSEXE_DATA_ERROR,
102 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
103 return ResIpcErrCode::RSSEXE_DATA_ERROR;
104 }
105
106 int32_t uid = IPCSkeleton::GetCallingUid();
107 int32_t clientPid = IPCSkeleton::GetCallingPid();
108 RSSEXE_LOGD("receive data from ipc resType: %{public}u, value: %{public}lld, uid: %{public}d, pid: %{public}d",
109 resType, (long long)value, uid, clientPid);
110
111 if (context.size() > PAYLOAD_MAX_SIZE) {
112 RSSEXE_LOGE("The payload is too long. DoS.");
113 WRITE_PARCEL(reply, Int32, ResIpcErrCode::RSSEXE_DATA_ERROR,
114 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
115 return ResIpcErrCode::RSSEXE_DATA_ERROR;
116 }
117
118 bool isSync = IsTypeSync(resType);
119 if (!GetExtResType(resType, context)) {
120 WRITE_PARCEL(reply, Int32, ResIpcErrCode::RSSEXE_DATA_ERROR,
121 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
122 return ResIpcErrCode::RSSEXE_DATA_ERROR;
123 }
124 context["callingUid"] = std::to_string(uid);
125 context["clientPid"] = std::to_string(clientPid);
126
127 int32_t ret = ResErrCode::RSSEXE_NO_ERR;
128 nlohmann::json result;
129 if (isSync) {
130 ret = SendRequestSync(resType, value, context, result);
131 } else {
132 SendRequestAsync(resType, value, context);
133 }
134 WRITE_PARCEL(reply, Int32, ret, ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
135 WRITE_PARCEL(reply, String, result.dump(-1, ' ', false, nlohmann::detail::error_handler_t::replace),
136 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
137 return ret;
138 }
139
KillProcessInner(MessageParcel & data,MessageParcel & reply)140 int32_t ResSchedExeServiceStub::KillProcessInner(MessageParcel& data, MessageParcel& reply)
141 {
142 pid_t pid = -1;
143 READ_PARCEL(data, Int32, pid, false, ResSchedExeServiceStub);
144 if (pid <= 0) {
145 WRITE_PARCEL(reply, Int32, KILL_PROCESS_FAILED, ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
146 return ResIpcErrCode::RSSEXE_DATA_ERROR;
147 }
148
149 int32_t ret = KillProcess(pid);
150 WRITE_PARCEL(reply, Int32, ret, ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
151 return 0;
152 }
153
ReportDebugInner(MessageParcel & data)154 int32_t ResSchedExeServiceStub::ReportDebugInner(MessageParcel& data)
155 {
156 uint32_t resType = 0;
157 READ_PARCEL(data, Uint32, resType, ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
158 if (!IsTypeDebug(resType)) {
159 return ResIpcErrCode::RSSEXE_DATA_ERROR;
160 }
161
162 uint64_t curr = ResSchedExeCommonUtils::GetCurrentTimestampUs();
163 uint64_t start;
164 READ_PARCEL(data, Uint64, start, ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
165 RSSEXE_LOGD("IPC debug: server recieve request, current timestamp is %{public}lld.", (long long)curr);
166 RSSEXE_LOGD("IPC debug: server recieve request, cost time is %{public}lld.", (long long)(curr - start));
167 return ResErrCode::RSSEXE_NO_ERR;
168 }
169
OnRemoteRequest(uint32_t code,MessageParcel & data,MessageParcel & reply,MessageOption & option)170 int32_t ResSchedExeServiceStub::OnRemoteRequest(uint32_t code, MessageParcel &data,
171 MessageParcel &reply, MessageOption &option)
172 {
173 if (!IsCallingClientRss()) {
174 RSSEXE_LOGE("calling process has no permission!");
175 WRITE_PARCEL(reply, Int32, ResErrCode::RSSEXE_PERMISSION_DENIED,
176 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
177 return ResErrCode::RSSEXE_PERMISSION_DENIED;
178 }
179
180 if (!IsValidToken(data)) {
181 RSSEXE_LOGE("token is invalid");
182 WRITE_PARCEL(reply, Int32, ResIpcErrCode::RSSEXE_DATA_ERROR,
183 ResIpcErrCode::RSSEXE_DATA_ERROR, ResSchedExeServiceStub);
184 return ResIpcErrCode::RSSEXE_DATA_ERROR;
185 }
186
187 RSSEXE_LOGD("code = %{public}u, flags = %{public}d.", code, option.GetFlags());
188
189 switch (code) {
190 case ResIpcType::REQUEST_SEND_SYNC:
191 return ReportRequestInner(data, reply);
192 case ResIpcType::REQUEST_SEND_ASYNC:
193 return ReportRequestInner(data, reply);
194 case ResIpcType::REQUEST_KILL_PROCESS:
195 return KillProcessInner(data, reply);
196 case ResIpcType::REQUEST_SEND_DEBUG:
197 return ReportDebugInner(data);
198 default:
199 return IPCObjectStub::OnRemoteRequest(code, data, reply, option);
200 }
201 }
202
ParseParcel(MessageParcel & data,uint32_t & resType,int64_t & value,nlohmann::json & context)203 bool ResSchedExeServiceStub::ParseParcel(MessageParcel& data,
204 uint32_t& resType, int64_t& value, nlohmann::json& context)
205 {
206 READ_PARCEL(data, Uint32, resType, false, ResSchedExeServiceStub);
207 if (!IsTypeVaild(resType)) {
208 RSSEXE_LOGE("type:%{public}d is invalid", resType);
209 return false;
210 }
211
212 READ_PARCEL(data, Int64, value, false, ResSchedExeServiceStub);
213
214 std::string payload;
215 READ_PARCEL(data, String, payload, false, ResSchedExeServiceStub);
216 ResSchedExeCommonUtils::StringToJson(payload, context);
217 return true;
218 }
219 } // namespace ResourceSchedule
220 } // namespace OHOS
221
222