1 /*
2 * Copyright (c) 2020 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 "bundle_daemon.h"
17
18 #include <string>
19
20 #include "bundle_daemon_log.h"
21 #include "liteipc_adapter.h"
22 #include "ohos_errno.h"
23 #include "ohos_init.h"
24 #include "samgr_lite.h"
25 #include "serializer.h"
26
27 namespace OHOS {
28 namespace {
29 constexpr int STACK_SIZE = 0x800;
30 constexpr int QUEUE_SIZE = 20;
31 constexpr pid_t BMS_UID = 7;
32 }
33 constexpr InvokeFunc BundleDaemon::invokeFuncs[];
34
35 static BundleDaemonFeature g_defaultApi = {
36 SERVER_IPROXY_IMPL_BEGIN,
37 .Invoke = BundleDaemon::Invoke,
38 IPROXY_END,
39 };
40
Init()41 static void Init()
42 {
43 SamgrLite *samgrLite = SAMGR_GetInstance();
44 if (samgrLite == nullptr) {
45 PRINTE("BundleDaemon", "get samgr is nullptr");
46 return;
47 }
48 BOOL result = samgrLite->RegisterService(&BundleDaemon::GetInstance());
49 if (!result) {
50 PRINTE("BundleDaemon", "register bundle_daemon service fail");
51 return;
52 }
53 result = samgrLite->RegisterDefaultFeatureApi(BDS_SERVICE, GET_IUNKNOWN(g_defaultApi));
54 PRINTE("BundleDaemon", "register default feature api %{public}s", result ? "success" : "fail");
55 }
56 SYSEX_SERVICE_INIT(Init);
57
BundleDaemon()58 BundleDaemon::BundleDaemon()
59 {
60 this->Service::GetName = BundleDaemon::GetServiceName;
61 this->Service::Initialize = BundleDaemon::ServiceInitialize;
62 this->Service::MessageHandle = BundleDaemon::ServiceMessageHandle;
63 this->Service::GetTaskConfig = BundleDaemon::GetServiceTaskConfig;
64 }
65
66
~BundleDaemon()67 BundleDaemon::~BundleDaemon()
68 {
69 delete bundleMsClient_;
70 }
71
GetServiceName(Service * service)72 const char *BundleDaemon::GetServiceName(Service *service)
73 {
74 (void)service;
75 return BDS_SERVICE;
76 }
77
ServiceInitialize(Service * service,Identity identity)78 BOOL BundleDaemon::ServiceInitialize(Service *service, Identity identity)
79 {
80 if (service == nullptr) {
81 return FALSE;
82 }
83 BundleDaemon *bundleDaemon = static_cast<BundleDaemon *>(service);
84 bundleDaemon->identity_ = identity;
85 return TRUE;
86 }
87
GetServiceTaskConfig(Service * service)88 TaskConfig BundleDaemon::GetServiceTaskConfig(Service *service)
89 {
90 TaskConfig config = {LEVEL_HIGH, PRI_NORMAL, STACK_SIZE, QUEUE_SIZE, SINGLE_TASK};
91 return config;
92 }
93
ServiceMessageHandle(Service * service,Request * request)94 BOOL BundleDaemon::ServiceMessageHandle(Service *service, Request *request)
95 {
96 if (request == nullptr) {
97 return FALSE;
98 }
99 return TRUE;
100 }
101
Invoke(IServerProxy * iProxy,int32_t funcId,void * origin,IpcIo * req,IpcIo * reply)102 int32_t BundleDaemon::Invoke(IServerProxy *iProxy, int32_t funcId, void *origin, IpcIo *req, IpcIo *reply)
103 {
104 PRINTI("BundleDaemon", "bundle_daemon invoke start %{public}d", funcId);
105 if (origin == nullptr || req == nullptr) {
106 PRINTE("BundleDaemon", "invalid param");
107 return EC_INVALID;
108 }
109 // check permission
110 pid_t uid = GetCallingUid(origin);
111 if (uid != BMS_UID) {
112 PRINTE("BundleDaemon", "permission denied");
113 return EC_PERMISSION;
114 }
115 if (funcId == REGISTER_CALLBACK) {
116 #ifdef __LINUX__
117 return EC_SUCCESS;
118 #else
119 return RegisterCallbackInvoke(req);
120 #endif
121 }
122 #ifndef __LINUX__
123 if (BundleDaemon::GetInstance().bundleMsClient_ == nullptr) {
124 PRINTE("BundleDaemon", "bundleMsClient is nullptr");
125 return EC_NOINIT;
126 }
127 #endif
128 int32_t ret = EC_COMMU;
129 if (funcId >= EXTRACT_HAP && funcId < BDS_CMD_END) {
130 ret = (BundleDaemon::invokeFuncs[funcId])(req);
131 }
132 #ifdef __LINUX__
133 IpcIoPushInt32(reply, ret);
134 return ret;
135 #else
136 return BundleDaemon::GetInstance().bundleMsClient_->SendReply(ret);
137 #endif
138 }
139
RegisterCallbackInvoke(IpcIo * req)140 int32_t BundleDaemon::RegisterCallbackInvoke(IpcIo *req)
141 {
142 SvcIdentity *svcIdentity = IpcIoPopSvc(req);
143 if (svcIdentity == nullptr) {
144 return EC_INVALID;
145 }
146 BundleDaemon::GetInstance().bundleMsClient_ = new BundleMsClient(*svcIdentity);
147 return BundleDaemon::GetInstance().bundleMsClient_->SendReply(EC_SUCCESS);
148 }
149
ObtainStringFromIpc(IpcIo * req,std::string & firstStr,std::string & secondStr)150 static int32_t ObtainStringFromIpc(IpcIo *req, std::string &firstStr, std::string &secondStr)
151 {
152 #ifdef __LINUX__
153 size_t length = 0;
154 std::string innerStr = reinterpret_cast<char *>(IpcIoPopString(req, &length));
155 #else
156 BuffPtr *buff = IpcIoPopDataBuff(req);
157 if (buff == nullptr || buff->buffSz == 0) {
158 return EC_INVALID;
159 }
160 std::string innerStr = reinterpret_cast<char *>(buff->buff);
161 #endif
162 uint32_t len = IpcIoPopUint16(req);
163 if (innerStr.length() <= len) {
164 #ifndef __LINUX__
165 FreeBuffer(nullptr, buff->buff);
166 #endif
167 return EC_INVALID;
168 }
169 firstStr = innerStr.substr(0, len);
170 secondStr = innerStr.substr(len);
171 #ifndef __LINUX__
172 FreeBuffer(nullptr, buff->buff);
173 #endif
174 return EC_SUCCESS;
175 }
176
ExtractHapInvoke(IpcIo * req)177 int32_t BundleDaemon::ExtractHapInvoke(IpcIo *req)
178 {
179 std::string hapPath = "";
180 std::string codePath = "";
181 int32_t ret = ObtainStringFromIpc(req, hapPath, codePath);
182 if (ret != EC_SUCCESS) {
183 return ret;
184 }
185 return BundleDaemon::GetInstance().handler_.ExtractHap(hapPath.c_str(), codePath.c_str());
186 }
187
RenameFileInvoke(IpcIo * req)188 int32_t BundleDaemon::RenameFileInvoke(IpcIo *req)
189 {
190 std::string oldFile = "";
191 std::string newFile = "";
192 int32_t ret = ObtainStringFromIpc(req, oldFile, newFile);
193 if (ret != EC_SUCCESS) {
194 return ret;
195 }
196 return BundleDaemon::GetInstance().handler_.RenameFile(oldFile.c_str(), newFile.c_str());
197 }
198
CreatePermissionInvoke(IpcIo * req)199 int32_t BundleDaemon::CreatePermissionInvoke(IpcIo *req)
200 {
201 return BundleDaemon::GetInstance().handler_.CreatePermissionDir();
202 }
203
CreateDataDirectoryInvoke(IpcIo * req)204 int32_t BundleDaemon::CreateDataDirectoryInvoke(IpcIo *req)
205 {
206 size_t len = 0;
207 const char *dataPath = reinterpret_cast<char *>(IpcIoPopString(req, &len));
208 if (dataPath == nullptr || len == 0) {
209 return EC_INVALID;
210 }
211 int32_t uid = IpcIoPopInt32(req);
212 int32_t gid = IpcIoPopInt32(req);
213 bool isChown = IpcIoPopBool(req);
214
215 return BundleDaemon::GetInstance().handler_.CreateDataDirectory(dataPath, uid, gid, isChown);
216 }
217
StoreContentToFileInvoke(IpcIo * req)218 int32_t BundleDaemon::StoreContentToFileInvoke(IpcIo *req)
219 {
220 size_t len = 0;
221 const char *path = reinterpret_cast<char *>(IpcIoPopString(req, &len));
222 if (path == nullptr || len == 0) {
223 return EC_INVALID;
224 }
225 #ifdef __LINUX__
226 size_t buffLen = 0;
227 const char *buff = reinterpret_cast<char *>(IpcIoPopString(req, &buffLen));
228 if (buff == nullptr || buffLen == 0) {
229 return EC_INVALID;
230 }
231 int32_t ret = BundleDaemon::GetInstance().handler_.StoreContentToFile(path, buff, buffLen);
232 #else
233 BuffPtr *buffPtr = IpcIoPopDataBuff(req);
234 if (buffPtr == nullptr || buffPtr->buffSz == 0) {
235 return EC_INVALID;
236 }
237 char *buff = reinterpret_cast<char *>(buffPtr->buff);
238 if (buff == nullptr) {
239 return EC_INVALID;
240 }
241
242 int32_t ret = BundleDaemon::GetInstance().handler_.StoreContentToFile(path, buff, buffPtr->buffSz);
243 FreeBuffer(nullptr, buffPtr->buff);
244 #endif
245 return ret;
246 }
247
MoveFileInvoke(IpcIo * req)248 int32_t BundleDaemon::MoveFileInvoke(IpcIo *req)
249 {
250 size_t len = 0;
251 const char *oldFile = reinterpret_cast<char *>(IpcIoPopString(req, &len));
252 if (oldFile == nullptr || len == 0) {
253 return EC_INVALID;
254 }
255 const char *newFile = reinterpret_cast<char *>(IpcIoPopString(req, &len));
256 if (newFile == nullptr || len == 0) {
257 return EC_INVALID;
258 }
259 return BundleDaemon::GetInstance().handler_.MoveFile(oldFile, newFile);
260 }
261
RemoveFileInvoke(IpcIo * req)262 int32_t BundleDaemon::RemoveFileInvoke(IpcIo *req)
263 {
264 size_t len = 0;
265 const char *path = reinterpret_cast<char *>(IpcIoPopString(req, &len));
266 if (path == nullptr || len == 0) {
267 return EC_INVALID;
268 }
269 return BundleDaemon::GetInstance().handler_.RemoveFile(path);
270 }
271
RemoveInstallDirectoryInvoke(IpcIo * req)272 int32_t BundleDaemon::RemoveInstallDirectoryInvoke(IpcIo *req)
273 {
274 std::string codePath = "";
275 std::string dataPath = "";
276 int32_t ret = ObtainStringFromIpc(req, codePath, dataPath);
277 if (ret != EC_SUCCESS) {
278 return ret;
279 }
280 bool keepData = IpcIoPopBool(req);
281 return BundleDaemon::GetInstance().handler_.RemoveInstallDirectory(codePath.c_str(), dataPath.c_str(), keepData);
282 }
283 } // OHOS
284