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