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 "app_spawn_test_helper.h"
17
18 #include <cstdint>
19 #include <cstdio>
20 #include <cstdlib>
21 #include <fcntl.h>
22 #include <pthread.h>
23 #include <csignal>
24 #include <string>
25 #include <sys/eventfd.h>
26 #include <sys/wait.h>
27 #include <unistd.h>
28 #include <inttypes.h>
29
30 #include "appspawn.h"
31 #include "appspawn_client.h"
32 #include "appspawn_modulemgr.h"
33 #include "appspawn_msg.h"
34 #include "appspawn_server.h"
35 #include "appspawn_service.h"
36 #include "appspawn_manager.h"
37 #include "appspawn_utils.h"
38 #include "loop_event.h"
39 #include "parameters.h"
40 #include "securec.h"
41
42 #include "app_spawn_stub.h"
43
44 namespace OHOS {
45 typedef struct {
46 int32_t bundleIndex;
47 char bundleName[APP_LEN_BUNDLE_NAME]; // process name
48 } AppBundleInfo;
49
50 typedef struct {
51 uint32_t hapFlags;
52 char apl[APP_APL_MAX_LEN];
53 } AppDomainInfo;
54
55 const uint32_t AppSpawnTestServer::defaultProtectTime = 60000; // 60000 60s
56
57 uint32_t AppSpawnTestServer::serverId = 0;
TestChildLoopRun(AppSpawnContent * content,AppSpawnClient * client)58 static int TestChildLoopRun(AppSpawnContent *content, AppSpawnClient *client)
59 {
60 APPSPAWN_LOGV("ChildLoopRun ...");
61 sleep(1);
62 return 0;
63 }
64
~AppSpawnTestServer()65 AppSpawnTestServer::~AppSpawnTestServer()
66 {
67 if (localServer_) {
68 delete localServer_;
69 localServer_ = nullptr;
70 }
71 }
72
CloseCheckHandler(void)73 void AppSpawnTestServer::CloseCheckHandler(void)
74 {
75 APPSPAWN_LOGV("CloseCheckHandler");
76 #ifdef USER_TIMER_TO_CHECK
77 if (timer_ != nullptr) {
78 LE_StopTimer(LE_GetDefaultLoop(), timer_);
79 timer_ = nullptr;
80 }
81 #else
82 if (idle_) {
83 LE_DelIdle(idle_);
84 idle_ = nullptr;
85 }
86 #endif
87 }
88
StartCheckHandler(void)89 void AppSpawnTestServer::StartCheckHandler(void)
90 {
91 #ifdef USER_TIMER_TO_CHECK
92 int ret = LE_CreateTimer(LE_GetDefaultLoop(), &timer_, ProcessIdle, this);
93 if (ret == 0) {
94 ret = LE_StartTimer(LE_GetDefaultLoop(), timer_, 100, 10000000); // 100 10000000 repeat
95 }
96 #else
97 LE_AddIdle(LE_GetDefaultLoop(), &idle_, ProcessIdle, this, 10000000); // 10000000 repeat
98 #endif
99 }
100
ServiceThread()101 void AppSpawnTestServer::ServiceThread()
102 {
103 CmdArgs *args = nullptr;
104 pid_t pid = getpid();
105 APPSPAWN_LOGV("AppSpawnTestServer::ServiceThread %{public}s", serviceCmd_.c_str());
106
107 running_ = true;
108 // 测试server时,使用appspawn的server
109 if (testServer_) {
110 content_ = AppSpawnTestHelper::StartSpawnServer(serviceCmd_, args);
111 if (content_ == nullptr) {
112 return;
113 }
114 if (pid == getpid()) { // 主进程进行处理
115 APPSPAWN_LOGV("Service start timer %{public}s ", serviceCmd_.c_str());
116 StartCheckHandler();
117 AppSpawnMgr *content = reinterpret_cast<AppSpawnMgr *>(content_);
118 APPSPAWN_CHECK_ONLY_EXPER(content != nullptr, return);
119 AppSpawnedProcess *info = GetSpawnedProcessByName(NWEBSPAWN_SERVER_NAME);
120 if (info != nullptr) {
121 APPSPAWN_LOGV("Save nwebspawn pid: %{public}d %{public}d", info->pid, serverId_);
122 appPid_.store(info->pid);
123 }
124 // register
125 RegChildLooper(&content->content, TestChildLoopRun);
126 }
127 content_->runAppSpawn(content_, args->argc, args->argv);
128 if (pid != getpid()) { // 子进程退出
129 exit(0);
130 } else {
131 content_ = nullptr;
132 }
133 } else {
134 StartCheckHandler();
135 localServer_ = new LocalTestServer();
136 localServer_->Run(APPSPAWN_SOCKET_NAME, recvMsgProcess_);
137 }
138 APPSPAWN_LOGV("AppSpawnTestServer::ServiceThread finish %{public}s ", serviceCmd_.c_str());
139 if (args) {
140 free(args);
141 }
142 return;
143 }
144
Start(void)145 void AppSpawnTestServer::Start(void)
146 {
147 Start(nullptr);
148 }
149
ServiceHelperThread(void * arg)150 static void *ServiceHelperThread(void *arg)
151 {
152 AppSpawnTestServer *server = reinterpret_cast<AppSpawnTestServer *>(arg);
153 APPSPAWN_LOGV("AppSpawnTestServer::thread ");
154 server->ServiceThread();
155 return nullptr;
156 }
157
Start(RecvMsgProcess process,uint32_t time)158 void AppSpawnTestServer::Start(RecvMsgProcess process, uint32_t time)
159 {
160 APPSPAWN_LOGV("AppSpawnTestServer::Start serverId %{public}u", AppSpawnTestServer::serverId);
161 protectTime_ = time;
162 uint32_t retry = 0;
163 if (threadId_ != 0) {
164 return;
165 }
166 clock_gettime(CLOCK_MONOTONIC, &startTime_);
167 recvMsgProcess_ = process;
168 errno = 0;
169 int ret = 0;
170 do {
171 threadId_ = 0;
172 ret = pthread_create(&threadId_, nullptr, ServiceHelperThread, static_cast<void *>(this));
173 if (ret == 0) {
174 break;
175 }
176 APPSPAWN_LOGE("AppSpawnTestServer::Start create thread fail %{public}d %{public}d", ret, errno);
177 usleep(20000); // 20000 20ms
178 retry++;
179 } while (ret == EAGAIN && retry < 10); // 10 max retry
180
181 // wait server thread run
182 retry = 0;
183 while (!running_ && (retry < 10)) { // 10 max retry
184 usleep(20000); // 20000 20ms
185 retry++;
186 }
187 APPSPAWN_LOGV("AppSpawnTestServer::Start retry %{public}u", retry);
188 }
189
Stop()190 void AppSpawnTestServer::Stop()
191 {
192 APPSPAWN_LOGV("AppSpawnTestServer::Stop serverId %{public}u", AppSpawnTestServer::serverId);
193 if (threadId_ != 0) {
194 stop_ = true;
195 pthread_join(threadId_, nullptr);
196 threadId_ = 0;
197 APPSPAWN_LOGV("Stop");
198 }
199 }
200
KillNWebSpawnServer()201 void AppSpawnTestServer::KillNWebSpawnServer()
202 {
203 APPSPAWN_LOGV("Kill nwebspawn %{public}d", serverId_);
204 if (appPid_ > 0) {
205 kill(appPid_, SIGKILL);
206 }
207 }
208
StopSpawnService(void)209 void AppSpawnTestServer::StopSpawnService(void)
210 {
211 APPSPAWN_LOGV("StopSpawnService ");
212 if (serverStoped) {
213 CloseCheckHandler();
214 }
215 serverStoped = true;
216 if (testServer_) {
217 struct signalfd_siginfo siginfo = {};
218 siginfo.ssi_signo = SIGTERM;
219 siginfo.ssi_uid = 0;
220 ProcessSignal(&siginfo);
221 } else {
222 localServer_->Stop();
223 }
224 }
225
226 #ifdef USER_TIMER_TO_CHECK
ProcessIdle(const TimerHandle taskHandle,void * context)227 void AppSpawnTestServer::ProcessIdle(const TimerHandle taskHandle, void *context)
228 #else
229 void AppSpawnTestServer::ProcessIdle(const IdleHandle taskHandle, void *context)
230 #endif
231 {
232 APPSPAWN_LOGV("AppSpawnTestServer::ProcessIdle");
233 AppSpawnTestServer *server = reinterpret_cast<AppSpawnTestServer *>(const_cast<void *>(context));
234 if (server->stop_) {
235 server->StopSpawnService();
236 return;
237 }
238
239 struct timespec end;
240 clock_gettime(CLOCK_MONOTONIC, &end);
241 uint64_t diff = DiffTime(&server->startTime_, &end);
242 if (diff >= (server->protectTime_ * 1000)) { // 1000 ms -> us
243 APPSPAWN_LOGV("AppSpawnTestServer:: timeout %{public}u %{public}" PRIu64 "", server->protectTime_, diff);
244 server->StopSpawnService();
245 return;
246 }
247 }
248
HandleRecvMessage(const TaskHandle taskHandle,uint8_t * buffer,int bufferSize,int flags)249 static int HandleRecvMessage(const TaskHandle taskHandle, uint8_t * buffer, int bufferSize, int flags)
250 {
251 int socketFd = LE_GetSocketFd(taskHandle);
252 struct iovec iov = {
253 .iov_base = buffer,
254 .iov_len = bufferSize,
255 };
256 char ctrlBuffer[CMSG_SPACE(APP_MAX_FD_COUNT * sizeof(int))];
257 struct msghdr msg = {
258 .msg_iov = &iov,
259 .msg_iovlen = 1,
260 .msg_control = ctrlBuffer,
261 .msg_controllen = sizeof(ctrlBuffer),
262 };
263
264 AppSpawnConnection *connection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
265 errno = 0;
266 int recvLen = recvmsg(socketFd, &msg, flags);
267 APPSPAWN_CHECK_ONLY_LOG(errno == 0, "recvmsg with errno %d", errno);
268 struct cmsghdr *cmsg = nullptr;
269 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
270 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
271 int fdCount = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
272 int* fd = reinterpret_cast<int*>(CMSG_DATA(cmsg));
273 APPSPAWN_CHECK(fdCount <= APP_MAX_FD_COUNT,
274 return -1, "failed to recv fd %d %d", connection->receiverCtx.fdCount, fdCount);
275 APPSPAWN_CHECK(memcpy_s(connection->receiverCtx.fds, fdCount * sizeof(int), fd,
276 fdCount * sizeof(int)) == 0, return -1, "memcpy_s fd failed");
277 connection->receiverCtx.fdCount = fdCount;
278 }
279 }
280
281 return recvLen;
282 }
283
OnConnection(const LoopHandle loopHandle,const TaskHandle server)284 int LocalTestServer::OnConnection(const LoopHandle loopHandle, const TaskHandle server)
285 {
286 static uint32_t connectionId = 0;
287 TaskHandle stream;
288 LE_StreamInfo info = {};
289 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
290 info.baseInfo.close = OnClose;
291 info.baseInfo.userDataSize = sizeof(TestConnection);
292 info.disConnectComplete = nullptr;
293 info.sendMessageComplete = SendMessageComplete;
294 info.recvMessage = OnReceiveRequest;
295 info.handleRecvMsg = HandleRecvMessage;
296
297 ServerInfo *serverInfo = (ServerInfo *)LE_GetUserData(server);
298 APPSPAWN_CHECK(serverInfo != nullptr, return -1, "Failed to alloc stream");
299
300 LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
301 APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream");
302 TestConnection *connection = (TestConnection *)LE_GetUserData(stream);
303 APPSPAWN_CHECK(connection != nullptr, return -1, "Failed to alloc stream");
304 connection->connectionId = ++connectionId;
305 connection->stream = stream;
306 connection->msgRecvLen = 0;
307 (void)memset_s(&connection->msg, sizeof(connection->msg), 0, sizeof(connection->msg));
308 connection->buffer = nullptr;
309 connection->recvMsgProcess = serverInfo->recvMsgProcess;
310 APPSPAWN_LOGI("OnConnection connection.id %{public}d fd %{public}d ",
311 connection->connectionId, LE_GetSocketFd(stream));
312 return 0;
313 }
314
SendMessageComplete(const TaskHandle taskHandle,BufferHandle handle)315 void LocalTestServer::SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle)
316 {
317 return;
318 }
319
OnClose(const TaskHandle taskHandle)320 void LocalTestServer::OnClose(const TaskHandle taskHandle)
321 {
322 TestConnection *connection = (TestConnection *)LE_GetUserData(taskHandle);
323 APPSPAWN_CHECK(connection != nullptr, return, "Invalid connection");
324 APPSPAWN_LOGI("OnClose connection.id %{public}d socket %{public}d",
325 connection->connectionId, LE_GetSocketFd(taskHandle));
326
327 AppSpawnConnection *spawnConnection = (AppSpawnConnection *) LE_GetUserData(taskHandle);
328 if (spawnConnection != nullptr) {
329 int fdCount = spawnConnection->receiverCtx.fdCount;
330 for (int i = 0; i < fdCount; i++) {
331 APPSPAWN_LOGI("OnClose close fd %d", spawnConnection->receiverCtx.fds[i]);
332 if (spawnConnection->receiverCtx.fds[i] >= 0) {
333 close(spawnConnection->receiverCtx.fds[i]);
334 }
335 }
336 }
337 }
338
OnReceiveRequest(const TaskHandle taskHandle,const uint8_t * buffer,uint32_t buffLen)339 void LocalTestServer::OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen)
340 {
341 TestConnection *connection = (TestConnection *)LE_GetUserData(taskHandle);
342 APPSPAWN_CHECK(connection != nullptr, LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
343 return, "Failed to get client form socket");
344
345 if (connection->recvMsgProcess) {
346 connection->recvMsgProcess(connection, buffer, buffLen);
347 }
348 }
349
Run(const char * socketName,RecvMsgProcess recvMsg)350 int LocalTestServer::Run(const char *socketName, RecvMsgProcess recvMsg)
351 {
352 char path[128] = {0}; // 128 max path
353 int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", APPSPAWN_SOCKET_DIR, socketName);
354 APPSPAWN_CHECK(ret >= 0, return -1, "Failed to snprintf_s %{public}d", ret);
355 LE_StreamServerInfo info = {};
356 info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER;
357 info.baseInfo.userDataSize = sizeof(ServerInfo);
358 info.socketId = -1;
359 info.server = path;
360 info.baseInfo.close = nullptr;
361 info.incommingConnect = OnConnection;
362
363 MakeDirRec(path, 0711, 0); // 0711 default mask
364 ret = LE_CreateStreamServer(LE_GetDefaultLoop(), &serverHandle_, &info);
365 APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s errno: %{public}d", path, errno);
366 APPSPAWN_LOGI("LocalTestServer path %{public}s fd %{public}d", path, LE_GetSocketFd(serverHandle_));
367
368 ServerInfo *serverInfo = (ServerInfo *)LE_GetUserData(serverHandle_);
369 APPSPAWN_CHECK(serverInfo != nullptr, return -1, "Failed to alloc stream");
370 serverInfo->local = this;
371 serverInfo->recvMsgProcess = recvMsg;
372 LE_RunLoop(LE_GetDefaultLoop());
373 LE_CloseStreamTask(LE_GetDefaultLoop(), serverHandle_);
374 LE_StopLoop(LE_GetDefaultLoop());
375 LE_CloseLoop(LE_GetDefaultLoop());
376 APPSPAWN_LOGI("LocalTestServer exit");
377 return 0;
378 }
379
Stop()380 void LocalTestServer::Stop()
381 {
382 APPSPAWN_LOGI("Stop LocalTestServer ");
383 LE_StopLoop(LE_GetDefaultLoop());
384 }
385
SendResponse(const AppSpawnMsg * msg,int result,pid_t pid)386 int TestConnection::SendResponse(const AppSpawnMsg *msg, int result, pid_t pid)
387 {
388 APPSPAWN_LOGV("SendResponse result: %{public}d pid: %{public}d", result, pid);
389 uint32_t bufferSize = sizeof(AppSpawnResponseMsg);
390 BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize);
391 AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, nullptr, &bufferSize);
392 int ret = memcpy_s(buffer, bufferSize, msg, sizeof(AppSpawnMsg));
393 APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
394 buffer->result.result = result;
395 buffer->result.pid = pid;
396 return LE_Send(LE_GetDefaultLoop(), stream, handle, bufferSize);
397 }
398
GenRandom(void)399 uint32_t AppSpawnTestHelper::GenRandom(void)
400 {
401 uint32_t random = 0;
402 int fd = open("/dev/random", O_RDONLY);
403 if (fd >= 0) {
404 read(fd, &random, sizeof(random));
405 close(fd);
406 }
407 return random;
408 }
409
ToCmdList(const char * cmd)410 CmdArgs *AppSpawnTestHelper::ToCmdList(const char *cmd)
411 {
412 const uint32_t maxArgc = 20;
413 const uint32_t length = sizeof(CmdArgs) + maxArgc * sizeof(char *) + strlen(cmd) + APP_LEN_PROC_NAME + 1 + 2;
414 char *buffer = static_cast<char *>(malloc(length));
415 CmdArgs *args = reinterpret_cast<CmdArgs *>(buffer);
416 APPSPAWN_CHECK(buffer != nullptr, return nullptr, "Failed to alloc args");
417 (void)memset_s(args, length, 0, length);
418 char *start = buffer + sizeof(CmdArgs) + maxArgc * sizeof(char *);
419 char *end = buffer + length;
420 uint32_t index = 0;
421 char *curr = const_cast<char *>(cmd);
422 while (isspace(*curr)) {
423 curr++;
424 }
425
426 while (index < (maxArgc - 1) && *curr != '\0') {
427 if (args->argv[index] == nullptr) {
428 args->argv[index] = start;
429 }
430 *start = *curr;
431 if (isspace(*curr)) {
432 *start = '\0';
433 // 为SetProcessName 预留空间
434 start = (index == 0) ? start + APP_LEN_PROC_NAME : start + 1;
435 while (isspace(*curr) && *curr != '\0') {
436 curr++;
437 }
438 if (*curr != '\0') {
439 index++;
440 }
441 } else {
442 start++;
443 curr++;
444 }
445 }
446
447 index++;
448 args->argv[index] = end - 2; // 2 last
449 args->argv[index][0] = '#';
450 args->argv[index][1] = '\0';
451 args->argc = index + 1;
452 return args;
453 }
454
AddDacInfo(AppSpawnReqMsgHandle & reqHandle)455 int AppSpawnTestHelper::AddDacInfo(AppSpawnReqMsgHandle &reqHandle)
456 {
457 AppDacInfo dacInfo = {};
458 dacInfo.uid = defaultTestUid_;
459 dacInfo.gid = defaultTestGid_;
460 dacInfo.gidCount = 2; // 2 count
461 dacInfo.gidTable[0] = defaultTestGidGroup_;
462 dacInfo.gidTable[1] = defaultTestGidGroup_ + 1;
463 (void)strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), "test-app-name");
464 return AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo);
465 }
466
AddFdInfo(AppSpawnReqMsgHandle & reqHandle)467 int AppSpawnTestHelper::AddFdInfo(AppSpawnReqMsgHandle &reqHandle)
468 {
469 if (fdArg < 0) {
470 fdArg = open("/dev/random", O_RDONLY);
471 }
472 APPSPAWN_LOGE("Add fd info %d", fdArg);
473 APPSPAWN_CHECK(fdArg >= 0, return -1, "open fd failed ");
474 return AppSpawnReqMsgAddFd(reqHandle, "fdname", fdArg);
475 }
476
CreateMsg(AppSpawnClientHandle handle,uint32_t msgType,int base)477 AppSpawnReqMsgHandle AppSpawnTestHelper::CreateMsg(AppSpawnClientHandle handle, uint32_t msgType, int base)
478 {
479 AppSpawnReqMsgHandle reqHandle = 0;
480 int ret = AppSpawnReqMsgCreate(static_cast<AppSpawnMsgType>(msgType), processName_.c_str(), &reqHandle);
481 APPSPAWN_CHECK(ret == 0, return INVALID_REQ_HANDLE, "Failed to create req %{public}s", processName_.c_str());
482 APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS, return reqHandle);
483 do {
484 ret = AddFdInfo(reqHandle);
485 APPSPAWN_CHECK(ret == 0, break, "Failed to add fd %{public}s", processName_.c_str());
486 ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 100, processName_.c_str()); // 100 test index
487 APPSPAWN_CHECK(ret == 0, break, "Failed to add bundle info req %{public}s", processName_.c_str());
488 ret = AddDacInfo(reqHandle);
489 APPSPAWN_CHECK(ret == 0, break, "Failed to add dac %{public}s", processName_.c_str());
490 ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678); // 12345678
491 APPSPAWN_CHECK(ret == 0, break, "Failed to add access token %{public}s", processName_.c_str());
492
493 if (defaultMsgFlags_ != 0) {
494 (void)AppSpawnReqMsgSetFlags(reqHandle, TLV_MSG_FLAGS, defaultMsgFlags_);
495 }
496 if (base) {
497 return reqHandle;
498 }
499 const char *testData = "ssssssssssssss sssssssss ssssssss";
500 ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1",
501 reinterpret_cast<uint8_t *>(const_cast<char *>(testData)), strlen(testData));
502 APPSPAWN_CHECK(ret == 0, break, "Failed to ext tlv %{public}s", processName_.c_str());
503 size_t count = permissions_.size();
504 for (size_t i = 0; i < count; i++) {
505 ret = AppSpawnReqMsgAddPermission(reqHandle, permissions_[i]);
506 APPSPAWN_CHECK(ret == 0, break, "Failed to permission %{public}s", permissions_[i]);
507 }
508
509 ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle, 1, 0);
510 APPSPAWN_CHECK(ret == 0, break, "Failed to internet info %{public}s", processName_.c_str());
511
512 ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, "ohos.permission.FILE_ACCESS_MANAGER");
513 APPSPAWN_CHECK(ret == 0, break, "Failed to ownerid %{public}s", processName_.c_str());
514 const char *renderCmd = "/system/bin/sh ls -l ";
515 ret = AppSpawnReqMsgAddExtInfo(reqHandle, MSG_EXT_NAME_RENDER_CMD,
516 reinterpret_cast<const uint8_t *>(renderCmd), strlen(renderCmd));
517 APPSPAWN_CHECK(ret == 0, break, "Failed to render cmd %{public}s", processName_.c_str());
518 ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, defaultApl_.c_str());
519 APPSPAWN_CHECK(ret == 0, break, "Failed to domain info %{public}s", processName_.c_str());
520 return reqHandle;
521 } while (0);
522 AppSpawnReqMsgFree(reqHandle);
523 return INVALID_REQ_HANDLE;
524 }
525
CreateAppSpawnMsg(AppSpawnMsg * msg)526 AppSpawnMsgNode *AppSpawnTestHelper::CreateAppSpawnMsg(AppSpawnMsg *msg)
527 {
528 AppSpawnMsgNode *msgNode = static_cast<AppSpawnMsgNode *>(calloc(1, sizeof(AppSpawnMsgNode)));
529 APPSPAWN_CHECK(msgNode != nullptr, return nullptr, "Failed to create receiver");
530 int ret = memcpy_s(&msgNode->msgHeader, sizeof(msgNode->msgHeader), msg, sizeof(msgNode->msgHeader));
531 APPSPAWN_CHECK(ret == 0, free(msgNode);
532 return nullptr, "Failed to memcpy msg");
533 msgNode->buffer = static_cast<uint8_t *>(malloc(msg->msgLen));
534 APPSPAWN_CHECK(msgNode->buffer != nullptr, free(msgNode);
535 return nullptr, "Failed to memcpy msg");
536 uint32_t totalCount = msg->tlvCount + TLV_MAX;
537 msgNode->tlvOffset = static_cast<uint32_t *>(malloc(totalCount * sizeof(uint32_t)));
538 APPSPAWN_CHECK(msgNode->tlvOffset != nullptr, free(msgNode);
539 return nullptr, "Failed to alloc memory for recv message");
540 for (uint32_t i = 0; i < totalCount; i++) {
541 msgNode->tlvOffset[i] = INVALID_OFFSET;
542 }
543 return msgNode;
544 }
545
GetAppProperty(AppSpawnClientHandle handle,AppSpawnReqMsgHandle reqHandle)546 AppSpawningCtx *AppSpawnTestHelper::GetAppProperty(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle)
547 {
548 AppSpawnReqMsgNode *reqNode = static_cast<AppSpawnReqMsgNode *>(reqHandle);
549 APPSPAWN_CHECK(reqNode != nullptr && reqNode->msg != nullptr, AppSpawnReqMsgFree(reqHandle);
550 return nullptr, "Invalid reqNode");
551
552 AppSpawnMsgNode *msgNode = CreateAppSpawnMsg(reqNode->msg);
553 APPSPAWN_CHECK(msgNode != nullptr, return nullptr, "Failed to alloc for msg");
554
555 uint32_t bufferSize = reqNode->msg->msgLen;
556 uint32_t currIndex = 0;
557 uint32_t bufferStart = sizeof(AppSpawnMsg);
558 ListNode *node = reqNode->msgBlocks.next;
559 while (node != &reqNode->msgBlocks) {
560 AppSpawnMsgBlock *block = ListEntry(node, AppSpawnMsgBlock, node);
561 int ret = memcpy_s(msgNode->buffer + currIndex, bufferSize - currIndex,
562 block->buffer + bufferStart, block->currentIndex - bufferStart);
563 if (ret != 0) {
564 AppSpawnReqMsgFree(reqHandle);
565 DeleteAppSpawnMsg(msgNode);
566 return nullptr;
567 }
568 currIndex += block->currentIndex - bufferStart;
569 bufferStart = 0;
570 node = node->next;
571 }
572 APPSPAWN_LOGV("GetAppProperty header magic 0x%{public}x type %{public}u id %{public}u len %{public}u %{public}s",
573 msgNode->msgHeader.magic, msgNode->msgHeader.msgType,
574 msgNode->msgHeader.msgId, msgNode->msgHeader.msgLen, msgNode->msgHeader.processName);
575
576 // delete reqHandle
577 AppSpawnReqMsgFree(reqHandle);
578 int ret = DecodeAppSpawnMsg(msgNode);
579 APPSPAWN_CHECK(ret == 0, DeleteAppSpawnMsg(msgNode);
580 return nullptr, "Decode msg fail");
581 AppSpawningCtx *property = CreateAppSpawningCtx();
582 APPSPAWN_CHECK_ONLY_EXPER(property != nullptr, DeleteAppSpawnMsg(msgNode);
583 return nullptr);
584 property->message = msgNode;
585 SetDefaultTestData();
586 return property;
587 }
588
SetDefaultTestData()589 void AppSpawnTestHelper::SetDefaultTestData()
590 {
591 processName_ = std::string("com.example.myapplication");
592 defaultTestUid_ = 20010029; // 20010029 test
593 defaultTestGid_ = 20010029; // 20010029 test
594 defaultTestGidGroup_ = 20010029; // 20010029 test
595 defaultTestBundleIndex_ = 100; // 100 test
596 defaultApl_ = std::string("system_core");
597 defaultMsgFlags_ = 0;
598 }
599
CreateSocket(int type)600 int AppSpawnTestHelper::CreateSocket(int type)
601 {
602 const uint32_t maxCount = 10;
603 uint32_t count = 0;
604 int socketId = -1;
605 while ((socketId < 0) && (count < maxCount)) {
606 usleep(20000); // 20000 20ms
607 socketId = CreateClientSocket(type, 2); // 2s
608 if (socketId > 0) {
609 return socketId;
610 }
611 count++;
612 }
613 return socketId;
614 }
615
CreateSendMsg(std::vector<uint8_t> & buffer,uint32_t msgType,uint32_t & msgLen,const std::vector<AddTlvFunction> & addTlvFuncs)616 int AppSpawnTestHelper::CreateSendMsg(std::vector<uint8_t> &buffer, uint32_t msgType, uint32_t &msgLen,
617 const std::vector<AddTlvFunction> &addTlvFuncs)
618 {
619 if (buffer.size() < sizeof(AppSpawnMsg)) {
620 return -1;
621 }
622 AppSpawnMsg *msg = reinterpret_cast<AppSpawnMsg *>(buffer.data());
623 msg->magic = APPSPAWN_MSG_MAGIC;
624 msg->msgType = msgType;
625 msg->msgLen = sizeof(AppSpawnMsg);
626 msg->msgId = 1;
627 msg->tlvCount = 0;
628 (void)strcpy_s(msg->processName, sizeof(msg->processName), processName_.c_str());
629 // add tlv
630 uint32_t currLen = sizeof(AppSpawnMsg);
631 for (auto addTlvFunc : addTlvFuncs) {
632 uint32_t realLen = 0;
633 uint32_t tlvCount = 0;
634 int ret = addTlvFunc(buffer.data() + currLen, buffer.size() - currLen, realLen, tlvCount);
635 APPSPAWN_CHECK(ret == 0 && (currLen + realLen) < buffer.size(),
636 return -1, "Failed add tlv to msg %{public}s", processName_.c_str());
637 msg->msgLen += realLen;
638 currLen += realLen;
639 msg->tlvCount += tlvCount;
640 }
641 msgLen = msg->msgLen;
642 APPSPAWN_LOGV("CreateSendMsg msgLen %{public}d", msgLen);
643 return 0;
644 }
645
AddOneTlv(uint8_t * buffer,uint32_t bufferLen,const AppSpawnTlv & tlv,const uint8_t * data)646 static int inline AddOneTlv(uint8_t *buffer, uint32_t bufferLen, const AppSpawnTlv &tlv, const uint8_t *data)
647 {
648 if (tlv.tlvLen > bufferLen) {
649 return -1;
650 }
651 int ret = memcpy_s(buffer, bufferLen, &tlv, sizeof(tlv));
652 APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
653 ret = memcpy_s(buffer + sizeof(tlv), bufferLen - sizeof(tlv), data, tlv.tlvLen - sizeof(tlv));
654 APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize");
655 return 0;
656 }
657
658 #define ADD_TLV(type, value, currLen, tlvCount) \
659 do { \
660 AppSpawnTlv d_tlv = {}; \
661 d_tlv.tlvType = (type); \
662 d_tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(value); \
663 ret = AddOneTlv(buffer + (currLen), bufferLen - (currLen), d_tlv, (uint8_t *)&(value)); \
664 APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", d_tlv.tlvType); \
665 (currLen) += d_tlv.tlvLen; \
666 (tlvCount)++; \
667 } while (0)
668
AddBaseTlv(uint8_t * buffer,uint32_t bufferLen,uint32_t & realLen,uint32_t & tlvCount)669 int AppSpawnTestHelper::AddBaseTlv(uint8_t *buffer, uint32_t bufferLen, uint32_t &realLen, uint32_t &tlvCount)
670 {
671 // add app flage
672 uint32_t currLen = 0;
673 uint32_t flags[2] = {1, 0b1010};
674 AppSpawnTlv tlv = {};
675 tlv.tlvType = TLV_MSG_FLAGS;
676 tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(flags);
677 int ret = AddOneTlv(buffer + currLen, bufferLen - currLen, tlv, (uint8_t *)flags);
678 APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", tlv.tlvType);
679 currLen += tlv.tlvLen;
680 tlvCount++;
681
682 tlv.tlvType = TLV_PERMISSION;
683 tlv.tlvLen = sizeof(AppSpawnTlv) + sizeof(flags);
684 ret = AddOneTlv(buffer + currLen, bufferLen - currLen, tlv, (uint8_t *)flags);
685 APPSPAWN_CHECK(ret == 0, return -1, "Failed add tlv %{public}u", tlv.tlvType);
686 currLen += tlv.tlvLen;
687 tlvCount++;
688
689 AppDomainInfo domainInfo = {0, "normal"};
690 ADD_TLV(TLV_DOMAIN_INFO, domainInfo, currLen, tlvCount);
691
692 AppSpawnMsgAccessToken token = {12345678}; // 12345678
693 ADD_TLV(TLV_ACCESS_TOKEN_INFO, token, currLen, tlvCount);
694
695 AppSpawnMsgInternetInfo internetInfo = {0, 1};
696 ADD_TLV(TLV_INTERNET_INFO, internetInfo, currLen, tlvCount);
697
698 // add bundle info
699 AppBundleInfo info = {};
700 (void)strcpy_s(info.bundleName, sizeof(info.bundleName), "test-bundleName");
701 info.bundleIndex = 100; // 100 test index
702 ADD_TLV(TLV_BUNDLE_INFO, info, currLen, tlvCount);
703
704 // add dac
705 AppDacInfo dacInfo = {};
706 dacInfo.uid = 20010029; // 20010029 test uid
707 dacInfo.gid = 20010029; // 20010029 test gid
708 dacInfo.gidCount = 2; // 2 count
709 dacInfo.gidTable[0] = 20010029; // 20010029 test gid
710 dacInfo.gidTable[1] = 20010030; // 20010030 test gid
711 ADD_TLV(TLV_DAC_INFO, dacInfo, currLen, tlvCount);
712 realLen = currLen;
713 return 0;
714 }
715
StartSpawnServer(std::string & cmd,CmdArgs * & args)716 AppSpawnContent *AppSpawnTestHelper::StartSpawnServer(std::string &cmd, CmdArgs *&args)
717 {
718 args = AppSpawnTestHelper::ToCmdList(cmd.c_str());
719 APPSPAWN_CHECK(args != nullptr, return nullptr, "Failed to alloc args");
720
721 AppSpawnStartArg startRrg = {};
722 startRrg.mode = MODE_FOR_APP_SPAWN;
723 startRrg.socketName = APPSPAWN_SOCKET_NAME;
724 startRrg.serviceName = APPSPAWN_SERVER_NAME;
725 startRrg.moduleType = MODULE_APPSPAWN;
726 startRrg.initArg = 1;
727 if (args->argc <= MODE_VALUE_INDEX) { // appspawn start
728 startRrg.mode = MODE_FOR_APP_SPAWN;
729 } else if (strcmp(args->argv[MODE_VALUE_INDEX], "app_cold") == 0) { // cold start
730 APPSPAWN_CHECK(args->argc >= ARG_NULL, free(args);
731 return nullptr, "Invalid arg for cold start %{public}d", args->argc);
732 startRrg.mode = MODE_FOR_APP_COLD_RUN;
733 startRrg.initArg = 0;
734 } else if (strcmp(args->argv[MODE_VALUE_INDEX], "nweb_cold") == 0) { // cold start
735 APPSPAWN_CHECK(args->argc >= ARG_NULL, free(args);
736 return nullptr, "Invalid arg for cold start %{public}d", args->argc);
737 startRrg.mode = MODE_FOR_NWEB_COLD_RUN;
738 startRrg.serviceName = NWEBSPAWN_SERVER_NAME;
739 startRrg.initArg = 0;
740 } else if (strcmp(args->argv[MODE_VALUE_INDEX], NWEBSPAWN_SERVER_NAME) == 0) { // nweb spawn start
741 startRrg.mode = MODE_FOR_NWEB_SPAWN;
742 startRrg.moduleType = MODULE_NWEBSPAWN;
743 startRrg.socketName = NWEBSPAWN_SOCKET_NAME;
744 startRrg.serviceName = NWEBSPAWN_SERVER_NAME;
745 }
746 APPSPAWN_LOGV("Start service %{public}s", startRrg.serviceName);
747 AppSpawnContent *content = StartSpawnService(&startRrg, APP_LEN_PROC_NAME, args->argc, args->argv);
748 if (content == nullptr) {
749 free(args);
750 }
751 return content;
752 }
753 } // namespace OHOS
754
MODULE_CONSTRUCTOR(void)755 MODULE_CONSTRUCTOR(void)
756 {
757 MakeDirRec(APPSPAWN_MSG_DIR "appspawn", 0771, 1);
758 MakeDirRec(APPSPAWN_MSG_DIR "nwebspawn", 0771, 1);
759 }
760