• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.h"
17 
18 #include <file_ex.h>
19 #include <parameters.h>
20 #include <string_ex.h>
21 
22 #include "accesstoken_kit.h"
23 #include "ipc_skeleton.h"
24 #include "system_ability_definition.h"
25 
26 #include "plugin_mgr.h"
27 #include "res_common_util.h"
28 #include "res_exe_type.h"
29 #include "res_sched_exe_constants.h"
30 #include "res_sched_exe_log.h"
31 #include "res_sched_exe_mgr.h"
32 
33 namespace OHOS {
34 namespace ResourceSchedule {
35 namespace {
36     constexpr int32_t DUMP_OPTION = 0;
37     constexpr int32_t DUMP_PARAM_INDEX = 1;
38     const int32_t ENG_MODE = OHOS::system::GetIntParameter("const.debuggable", 0);
39     const std::string DUMP_PERMISSION = "ohos.permission.DUMP";
40     constexpr int32_t PAYLOAD_MAX_SIZE = 4096;
41     constexpr int32_t KILL_PROCESS_FAILED = -1;
42     constexpr int32_t RSS_UID = 1096;
43     const std::string RES_TYPE_EXT = "extType";
44 
IsTypeVaild(uint32_t type)45     bool IsTypeVaild(uint32_t type)
46     {
47         return type >= ResExeType::RES_TYPE_FIRST && type < ResExeType::RES_TYPE_LAST;
48     }
49 
IsCallingClientRss()50     bool IsCallingClientRss()
51     {
52         int32_t clientUid = IPCSkeleton::GetCallingUid();
53         RSSEXE_LOGD("calling client uid is %{public}d, allowed uid is %{public}d", clientUid, RSS_UID);
54         return RSS_UID == clientUid;
55     }
56 
GetExtResType(uint32_t & resType,const nlohmann::json & context)57     bool GetExtResType(uint32_t& resType, const nlohmann::json& context)
58     {
59         if (resType != ResExeType::RES_TYPE_COMMON_SYNC && resType != ResExeType::RES_TYPE_COMMON_ASYNC) {
60             return true;
61         }
62         int type = 0;
63         if (!context.contains(RES_TYPE_EXT) || !context[RES_TYPE_EXT].is_string()
64             || !StrToInt(context[RES_TYPE_EXT], type)) {
65             RSSEXE_LOGE("use extend resType, but not send resTypeExt with payload");
66             return false;
67         }
68         resType = (uint32_t)type;
69         RSSEXE_LOGD("use extend resType = %{public}d.", resType);
70         return true;
71     }
72 }
73 
74 const bool REGISTER_RESULT =
75     SystemAbility::MakeAndRegisterAbility(DelayedSingleton<ResSchedExeService>::GetInstance().get());
76 
ResSchedExeService()77 ResSchedExeService::ResSchedExeService() : SystemAbility(RES_SCHED_EXE_ABILITY_ID, true)
78 {
79 }
80 
~ResSchedExeService()81 ResSchedExeService::~ResSchedExeService()
82 {
83 }
84 
OnStart()85 void ResSchedExeService::OnStart()
86 {
87     ResSchedExeMgr::GetInstance().Init();
88     if (!Publish(DelayedSingleton<ResSchedExeService>::GetInstance().get())) {
89         RSSEXE_LOGE("ResSchedExeService::Register service failed.");
90         return;
91     }
92     RSSEXE_LOGI("ResSchedExeService::OnStart.");
93 }
94 
OnStop()95 void ResSchedExeService::OnStop()
96 {
97     ResSchedExeMgr::GetInstance().Stop();
98     RSSEXE_LOGI("ResSchedExeService::OnStop!");
99 }
100 
SendRequestSync(uint32_t resType,int64_t value,const ResJsonType & context,ResJsonType & response,int32_t & funcResult)101 ErrCode ResSchedExeService::SendRequestSync(uint32_t resType, int64_t value,
102                                             const ResJsonType &context, ResJsonType &response, int32_t &funcResult)
103 {
104     RSSEXE_LOGD("ResSchedExeService start to exec SendRequestSync, restType: %{public}u", resType);
105     if (!IsCallingClientRss()) {
106         RSSEXE_LOGE("calling process has no permission!");
107         return ERR_INVALID_OPERATION;
108     }
109     if (!IsTypeVaild(resType)) {
110         RSSEXE_LOGE("The resType is invalid. Dos");
111         return ERR_INVALID_VALUE;
112     }
113 
114     nlohmann::json jsonContext = context.jsonContext;
115     if (jsonContext.size() > PAYLOAD_MAX_SIZE) {
116         RSSEXE_LOGE("The payload is too long. DoS.");
117         return ERR_INVALID_VALUE;
118     }
119     if (!GetExtResType(resType, jsonContext)) {
120         RSSEXE_LOGE("Get ResType Error DoS.");
121         return ERR_INVALID_VALUE;
122     }
123 
124     nlohmann::json jsonResponse;
125     funcResult = ResSchedExeMgr::GetInstance().SendRequestSync(resType, value, jsonContext, jsonResponse);
126     response.jsonContext = jsonResponse;
127     return ERR_OK;
128 }
129 
SendRequestAsync(uint32_t resType,int64_t value,const ResJsonType & context)130 ErrCode ResSchedExeService::SendRequestAsync(uint32_t resType, int64_t value, const ResJsonType& context)
131 {
132     RSSEXE_LOGD("ResSchedExeService start to exec SendRequestAsync, restType: %{public}u", resType);
133     if (!IsCallingClientRss()) {
134         RSSEXE_LOGE("calling process has no permission!");
135         return ERR_INVALID_OPERATION;
136     }
137     if (!IsTypeVaild(resType)) {
138         RSSEXE_LOGE("The resType is invalid. Dos");
139         return ERR_INVALID_VALUE;
140     }
141 
142     nlohmann::json jsonContext = context.jsonContext;
143     if (jsonContext.size() > PAYLOAD_MAX_SIZE) {
144         RSSEXE_LOGE("The payload is too long. DoS.");
145         return ERR_INVALID_VALUE;
146     }
147     if (!GetExtResType(resType, jsonContext)) {
148         RSSEXE_LOGE("Get ResType Error DoS.");
149         return ERR_INVALID_VALUE;
150     }
151 
152     ResSchedExeMgr::GetInstance().SendRequestAsync(resType, value, jsonContext);
153     return ERR_OK;
154 }
155 
KillProcess(uint32_t pid,int32_t & funcResult)156 ErrCode ResSchedExeService::KillProcess(uint32_t pid, int32_t& funcResult)
157 {
158     RSSEXE_LOGD("ResSchedExeService start to exec KillProcess, pid: %{public}u", pid);
159     if (!IsCallingClientRss()) {
160         RSSEXE_LOGE("Calling process has no permission!");
161         return ERR_INVALID_OPERATION;
162     }
163     if (pid <= 0) {
164         RSSEXE_LOGE("Pid should be more than 0.");
165         return ERR_INVALID_VALUE;
166     }
167 
168     funcResult = ResSchedExeMgr::GetInstance().KillProcess(static_cast<pid_t>(pid));
169     return ERR_OK;
170 }
171 
AllowDump()172 bool ResSchedExeService::AllowDump()
173 {
174     if (ENG_MODE == 0) {
175         RSSEXE_LOGE("Not eng mode");
176         return false;
177     }
178     Security::AccessToken::AccessTokenID tokenId = IPCSkeleton::GetCallingTokenID();
179     int32_t ret = Security::AccessToken::AccessTokenKit::VerifyAccessToken(tokenId, DUMP_PERMISSION);
180     if (ret != Security::AccessToken::PermissionState::PERMISSION_GRANTED) {
181         RSSEXE_LOGE("CheckPermission failed");
182         return false;
183     }
184     return true;
185 }
186 
Dump(int32_t fd,const std::vector<std::u16string> & args)187 int32_t ResSchedExeService::Dump(int32_t fd, const std::vector<std::u16string>& args)
188 {
189     if (!AllowDump()) {
190         return ResErrCode::RSSEXE_PERMISSION_DENIED;
191     }
192     RSSEXE_LOGI("Dump service.");
193     std::vector<std::string> argsInStr;
194     std::transform(args.begin(), args.end(), std::back_inserter(argsInStr),
195         [](const std::u16string &arg) {
196         std::string ret = Str16ToStr8(arg);
197         RSSEXE_LOGI("arg: %{public}s.", ret.c_str());
198         return ret;
199     });
200     std::string result;
201     if (argsInStr.size() == 0) {
202         // hidumper -s said '-h'
203         DumpUsage(result);
204     } else if (argsInStr.size() == DUMP_OPTION + 1) {
205         // hidumper -s said '-h' or hidumper -s said '-a'
206         if (argsInStr[DUMP_OPTION] == "-h") {
207             DumpUsage(result);
208         } else if (argsInStr[DUMP_OPTION] == "-a") {
209             DumpAllInfo(result);
210         } else if (argsInStr[DUMP_OPTION] == "-p") {
211             PluginMgr::GetInstance().DumpAllPlugin(result);
212         } else {
213             result.append("Error params.");
214         }
215     } else if (argsInStr.size() >= DUMP_PARAM_INDEX + 1) {
216         if (argsInStr[DUMP_OPTION] == "-p") {
217             std::vector<std::string> argsInStrToPlugin;
218             argsInStrToPlugin.assign(argsInStr.begin() + DUMP_PARAM_INDEX + 1, argsInStr.end());
219             PluginMgr::GetInstance().DumpOnePlugin(result, argsInStr[DUMP_PARAM_INDEX], argsInStrToPlugin);
220         }
221     }
222 
223     if (!SaveStringToFd(fd, result)) {
224         RSSEXE_LOGE("save to fd failed.");
225     }
226     return ResErrCode::RSSEXE_NO_ERR;
227 }
228 
DumpUsage(std::string & result)229 void ResSchedExeService::DumpUsage(std::string &result)
230 {
231     result.append("usage: resource schedule executor dump [<options>]\n")
232         .append("    -h: show the help.\n")
233         .append("    -a: show all info.\n")
234         .append("    -p: show the all plugin info.\n")
235         .append("    -p (plugin name): show one plugin info.\n");
236     PluginMgr::GetInstance().DumpHelpFromPlugin(result);
237 }
238 
DumpAllInfo(std::string & result)239 void ResSchedExeService::DumpAllInfo(std::string &result)
240 {
241     result.append("================Resource Schedule Executor Infos================\n");
242     PluginMgr::GetInstance().DumpAllPlugin(result);
243 }
244 } // namespace ResourceSchedule
245 } // namespace OHOS
246