• 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 "appspawn_client.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <pthread.h>
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include <linux/in.h>
25 #include <linux/socket.h>
26 #include <linux/tcp.h>
27 #include <sys/socket.h>
28 #include <sys/time.h>
29 #include <sys/types.h>
30 #include <sys/un.h>
31 
32 #include "appspawn_mount_permission.h"
33 #include "appspawn_hook.h"
34 #include "appspawn_utils.h"
35 #include "parameter.h"
36 #include "securec.h"
37 
38 #define USER_LOCK_STATUS_SIZE 8
39 static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
40 static AppSpawnReqMsgMgr *g_clientInstance[CLIENT_MAX] = {NULL};
41 
GetDefaultTimeout(uint32_t def)42 static uint32_t GetDefaultTimeout(uint32_t def)
43 {
44     uint32_t value = def;
45     char data[32] = {};  // 32 length
46     int ret = GetParameter("persist.appspawn.reqMgr.timeout", "0", data, sizeof(data));
47     if (ret > 0 && strcmp(data, "0") != 0) {
48         errno = 0;
49         value = (uint32_t)atoi(data);
50         return (errno != 0) ? def : value;
51     }
52     return value;
53 }
54 
InitClientInstance(AppSpawnClientType type)55 static int InitClientInstance(AppSpawnClientType type)
56 {
57     pthread_mutex_lock(&g_mutex);
58     if (g_clientInstance[type] != NULL) {
59         pthread_mutex_unlock(&g_mutex);
60         return 0;
61     }
62     AppSpawnReqMsgMgr *clientInstance = malloc(sizeof(AppSpawnReqMsgMgr) + RECV_BLOCK_LEN);
63     if (clientInstance == NULL) {
64         pthread_mutex_unlock(&g_mutex);
65         return APPSPAWN_SYSTEM_ERROR;
66     }
67     // init
68     clientInstance->type = type;
69     clientInstance->msgNextId = 1;
70     clientInstance->timeout = GetDefaultTimeout(TIMEOUT_DEF);
71     clientInstance->maxRetryCount = MAX_RETRY_SEND_COUNT;
72     clientInstance->socketId = -1;
73     pthread_mutex_init(&clientInstance->mutex, NULL);
74     // init recvBlock
75     OH_ListInit(&clientInstance->recvBlock.node);
76     clientInstance->recvBlock.blockSize = RECV_BLOCK_LEN;
77     clientInstance->recvBlock.currentIndex = 0;
78     g_clientInstance[type] = clientInstance;
79     pthread_mutex_unlock(&g_mutex);
80     return 0;
81 }
82 
CloseClientSocket(int socketId)83 APPSPAWN_STATIC void CloseClientSocket(int socketId)
84 {
85     APPSPAWN_LOGV("Closed socket with fd %{public}d", socketId);
86     if (socketId >= 0) {
87         int flag = 0;
88         setsockopt(socketId, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
89         close(socketId);
90     }
91 }
92 
CreateClientSocket(uint32_t type,uint32_t timeout)93 APPSPAWN_STATIC int CreateClientSocket(uint32_t type, uint32_t timeout)
94 {
95     const char *socketName;
96 
97     switch (type) {
98         case CLIENT_FOR_APPSPAWN:
99             socketName = APPSPAWN_SOCKET_NAME;
100             break;
101         case CLIENT_FOR_CJAPPSPAWN:
102             socketName = CJAPPSPAWN_SOCKET_NAME;
103             break;
104         case CLIENT_FOR_NATIVESPAWN:
105             socketName = NATIVESPAWN_SOCKET_NAME;
106             break;
107         default:
108             socketName = NWEBSPAWN_SOCKET_NAME;
109             break;
110     }
111 
112     int socketFd = socket(AF_UNIX, SOCK_STREAM, 0);  // SOCK_SEQPACKET
113     APPSPAWN_CHECK(socketFd >= 0, return -1,
114         "Socket socket fd: %{public}s error: %{public}d", socketName, errno);
115     int ret = 0;
116     do {
117         int flag = 1;
118         ret = setsockopt(socketFd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
119         flag = 1;
120         ret = setsockopt(socketFd, SOL_SOCKET, SO_PASSCRED, &flag, sizeof(flag));
121         APPSPAWN_CHECK(ret == 0, break, "Set opt SO_PASSCRED name: %{public}s error: %{public}d", socketName, errno);
122 
123         struct timeval timeoutVal = {timeout, 0};
124         ret = setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, &timeoutVal, sizeof(timeoutVal));
125         APPSPAWN_CHECK(ret == 0, break, "Set opt SO_SNDTIMEO name: %{public}s error: %{public}d", socketName, errno);
126         ret = setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, &timeoutVal, sizeof(timeoutVal));
127         APPSPAWN_CHECK(ret == 0, break, "Set opt SO_RCVTIMEO name: %{public}s error: %{public}d", socketName, errno);
128 
129         ret = APPSPAWN_SYSTEM_ERROR;
130         struct sockaddr_un addr;
131         socklen_t pathSize = sizeof(addr.sun_path);
132         int pathLen = snprintf_s(addr.sun_path, pathSize, (pathSize - 1), "%s%s", APPSPAWN_SOCKET_DIR, socketName);
133         APPSPAWN_CHECK(pathLen > 0, break, "Format path %{public}s error: %{public}d", socketName, errno);
134         addr.sun_family = AF_LOCAL;
135         socklen_t socketAddrLen = (socklen_t)(offsetof(struct sockaddr_un, sun_path) + (socklen_t)pathLen + 1);
136         ret = connect(socketFd, (struct sockaddr *)(&addr), socketAddrLen);
137         APPSPAWN_CHECK(ret == 0, break,
138             "Failed to connect %{public}s error: %{public}d", addr.sun_path, errno);
139         APPSPAWN_LOGI("Create socket success %{public}s socketFd: %{public}d", addr.sun_path, socketFd);
140         return socketFd;
141     } while (0);
142     CloseClientSocket(socketFd);
143     return -1;
144 }
145 
UpdateSocketTimeout(uint32_t timeout,int socketFd)146 APPSPAWN_STATIC int UpdateSocketTimeout(uint32_t timeout, int socketFd)
147 {
148     struct timeval timeoutVal = {timeout, 0};
149     int ret = setsockopt(socketFd, SOL_SOCKET, SO_SNDTIMEO, &timeoutVal, sizeof(timeoutVal));
150     APPSPAWN_CHECK(ret == 0, return ret, "Set opt SO_SNDTIMEO error: %{public}d", errno);
151     ret = setsockopt(socketFd, SOL_SOCKET, SO_RCVTIMEO, &timeoutVal, sizeof(timeoutVal));
152     APPSPAWN_CHECK(ret == 0, return ret, "Set opt SO_RCVTIMEO error: %{public}d", errno);
153     return ret;
154 }
155 
ReadMessage(int socketFd,uint32_t sendMsgId,uint8_t * buf,int len,AppSpawnResult * result)156 static int ReadMessage(int socketFd, uint32_t sendMsgId, uint8_t *buf, int len, AppSpawnResult *result)
157 {
158     ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len));
159     APPSPAWN_CHECK(rLen >= 0, return APPSPAWN_TIMEOUT,
160         "Read message from fd %{public}d rLen %{public}zd errno: %{public}d", socketFd, rLen, errno);
161     if ((size_t)rLen >= sizeof(AppSpawnResponseMsg)) {
162         AppSpawnResponseMsg *msg = (AppSpawnResponseMsg *)(buf);
163         APPSPAWN_CHECK_ONLY_LOG(sendMsgId == msg->msgHdr.msgId,
164             "Invalid msg recvd %{public}u %{public}u", sendMsgId, msg->msgHdr.msgId);
165         return memcpy_s(result, sizeof(AppSpawnResult), &msg->result, sizeof(msg->result));
166     }
167     return APPSPAWN_TIMEOUT;
168 }
169 
WriteMessage(int socketFd,const uint8_t * buf,ssize_t len,int * fds,int * fdCount)170 static int WriteMessage(int socketFd, const uint8_t *buf, ssize_t len, int *fds, int *fdCount)
171 {
172     ssize_t written = 0;
173     ssize_t remain = len;
174     const uint8_t *offset = buf;
175     struct iovec iov = {
176         .iov_base = (void *) offset,
177         .iov_len = len,
178     };
179     struct msghdr msg = {
180         .msg_iov = &iov,
181         .msg_iovlen = 1,
182     };
183     char *ctrlBuffer = NULL;
184     if (fdCount != NULL && fds != NULL && *fdCount > 0) {
185         msg.msg_controllen = CMSG_SPACE(*fdCount * sizeof(int));
186         ctrlBuffer = (char *) malloc(msg.msg_controllen);
187         APPSPAWN_CHECK(ctrlBuffer != NULL, return -1,
188             "WriteMessage fail to alloc memory for msg_control %{public}d %{public}d", msg.msg_controllen, errno);
189         msg.msg_control = ctrlBuffer;
190         struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
191         APPSPAWN_CHECK(cmsg != NULL, free(ctrlBuffer);
192             return -1, "WriteMessage fail to get CMSG_FIRSTHDR %{public}d", errno);
193         cmsg->cmsg_len = CMSG_LEN(*fdCount * sizeof(int));
194         cmsg->cmsg_type = SCM_RIGHTS;
195         cmsg->cmsg_level = SOL_SOCKET;
196         int ret = memcpy_s(CMSG_DATA(cmsg), cmsg->cmsg_len, fds, *fdCount * sizeof(int));
197         APPSPAWN_CHECK(ret == 0, free(ctrlBuffer);
198             return -1, "WriteMessage fail to memcpy_s fd %{public}d", errno);
199         APPSPAWN_LOGV("build fd info count %{public}d", *fdCount);
200     }
201     for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) {
202         errno = 0;
203         wLen = sendmsg(socketFd, &msg, MSG_NOSIGNAL);
204         APPSPAWN_LOGV("Write msg errno: %{public}d %{public}zd", errno, wLen);
205         APPSPAWN_CHECK((wLen > 0) || (errno == EINTR), free(ctrlBuffer);
206             return -errno,
207             "Failed to write message to fd %{public}d, wLen %{public}zd errno: %{public}d", socketFd, wLen, errno);
208     }
209     free(ctrlBuffer);
210     return written == len ? 0 : -EFAULT;
211 }
212 
HandleMsgSend(AppSpawnReqMsgMgr * reqMgr,int socketId,AppSpawnReqMsgNode * reqNode)213 static int HandleMsgSend(AppSpawnReqMsgMgr *reqMgr, int socketId, AppSpawnReqMsgNode *reqNode)
214 {
215     APPSPAWN_LOGV("HandleMsgSend reqId: %{public}u msgId: %{public}d", reqNode->reqId, reqNode->msg->msgId);
216     ListNode *sendNode = reqNode->msgBlocks.next;
217     uint32_t currentIndex = 0;
218     bool sendFd = true;
219     while (sendNode != NULL && sendNode != &reqNode->msgBlocks) {
220         AppSpawnMsgBlock *sendBlock = (AppSpawnMsgBlock *)ListEntry(sendNode, AppSpawnMsgBlock, node);
221         int ret = WriteMessage(socketId, sendBlock->buffer, sendBlock->currentIndex,
222             sendFd ? reqNode->fds : NULL,
223             sendFd ? &reqNode->fdCount : NULL);
224         currentIndex += sendBlock->currentIndex;
225         APPSPAWN_LOGV("Write msg ret: %{public}d msgId: %{public}u %{public}u %{public}u",
226             ret, reqNode->msg->msgId, reqNode->msg->msgLen, currentIndex);
227         if (ret == 0) {
228             sendFd = false;
229             sendNode = sendNode->next;
230             continue;
231         }
232         APPSPAWN_LOGE("Send msg fail reqId: %{public}u msgId: %{public}d ret: %{public}d",
233             reqNode->reqId, reqNode->msg->msgId, ret);
234         return ret;
235     }
236     return 0;
237 }
238 
TryCreateSocket(AppSpawnReqMsgMgr * reqMgr)239 static void TryCreateSocket(AppSpawnReqMsgMgr *reqMgr)
240 {
241     uint32_t retryCount = 1;
242     while (retryCount <= reqMgr->maxRetryCount) {
243         if (reqMgr->socketId < 0) {
244             reqMgr->socketId = CreateClientSocket(reqMgr->type, reqMgr->timeout);
245         }
246         if (reqMgr->socketId < 0) {
247             APPSPAWN_LOGV("Failed to create socket, try again");
248             usleep(RETRY_TIME);
249             retryCount++;
250             continue;
251         }
252         break;
253     }
254 }
255 
ClientSendMsg(AppSpawnReqMsgMgr * reqMgr,AppSpawnReqMsgNode * reqNode,AppSpawnResult * result)256 static int ClientSendMsg(AppSpawnReqMsgMgr *reqMgr, AppSpawnReqMsgNode *reqNode, AppSpawnResult *result)
257 {
258     uint32_t retryCount = 1;
259     int isColdRun = reqNode->isAsan;
260     while (retryCount <= reqMgr->maxRetryCount) {
261         if (reqMgr->socketId < 0) { // try create socket
262             TryCreateSocket(reqMgr);
263             if (reqMgr->socketId < 0) {
264                 usleep(RETRY_TIME);
265                 retryCount++;
266                 continue;
267             }
268         }
269         if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) {
270             UpdateSocketTimeout(ASAN_TIMEOUT, reqMgr->socketId);
271         }
272 
273         if (reqNode->msg->msgId == 0) {
274             reqNode->msg->msgId = reqMgr->msgNextId++;
275         }
276         int ret = HandleMsgSend(reqMgr, reqMgr->socketId, reqNode);
277         if (ret == 0) {
278             ret = ReadMessage(reqMgr->socketId, reqNode->msg->msgId,
279                 reqMgr->recvBlock.buffer, reqMgr->recvBlock.blockSize, result);
280         }
281         if (ret == 0) {
282             if (isColdRun && reqMgr->timeout < ASAN_TIMEOUT) {
283                 UpdateSocketTimeout(reqMgr->timeout, reqMgr->socketId);
284             }
285             return 0;
286         }
287         // retry
288         CloseClientSocket(reqMgr->socketId);
289         reqMgr->socketId = -1;
290         reqMgr->msgNextId = 1;
291         reqNode->msg->msgId = 0;
292         usleep(RETRY_TIME);
293         retryCount++;
294     }
295     return APPSPAWN_TIMEOUT;
296 }
297 
AppSpawnClientInit(const char * serviceName,AppSpawnClientHandle * handle)298 int AppSpawnClientInit(const char *serviceName, AppSpawnClientHandle *handle)
299 {
300     APPSPAWN_CHECK(serviceName != NULL, return APPSPAWN_ARG_INVALID, "Invalid service name");
301     APPSPAWN_CHECK(handle != NULL, return APPSPAWN_ARG_INVALID, "Invalid handle for %{public}s", serviceName);
302     APPSPAWN_LOGV("AppSpawnClientInit serviceName %{public}s", serviceName);
303     AppSpawnClientType type = CLIENT_FOR_APPSPAWN;
304     if (strcmp(serviceName, CJAPPSPAWN_SERVER_NAME) == 0) {
305         type = CLIENT_FOR_CJAPPSPAWN;
306     } else if (strcmp(serviceName, NWEBSPAWN_SERVER_NAME) == 0 || strstr(serviceName, NWEBSPAWN_SOCKET_NAME) != NULL) {
307         type = CLIENT_FOR_NWEBSPAWN;
308     } else if (strcmp(serviceName, NATIVESPAWN_SERVER_NAME) == 0 ||
309         strstr(serviceName, NATIVESPAWN_SOCKET_NAME) != NULL) {
310         type = CLIENT_FOR_NATIVESPAWN;
311     }
312     int ret = InitClientInstance(type);
313     APPSPAWN_CHECK(ret == 0, return APPSPAWN_SYSTEM_ERROR, "Failed to create reqMgr");
314     *handle = (AppSpawnClientHandle)g_clientInstance[type];
315     return 0;
316 }
317 
AppSpawnClientDestroy(AppSpawnClientHandle handle)318 int AppSpawnClientDestroy(AppSpawnClientHandle handle)
319 {
320     AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
321     APPSPAWN_CHECK(reqMgr != NULL, return APPSPAWN_SYSTEM_ERROR, "Invalid reqMgr");
322     pthread_mutex_lock(&g_mutex);
323     if (reqMgr->type < sizeof(g_clientInstance) / sizeof(g_clientInstance[0])) {
324         g_clientInstance[reqMgr->type] = NULL;
325     }
326     pthread_mutex_unlock(&g_mutex);
327     pthread_mutex_destroy(&reqMgr->mutex);
328     if (reqMgr->socketId >= 0) {
329         CloseClientSocket(reqMgr->socketId);
330         reqMgr->socketId = -1;
331     }
332     free(reqMgr);
333     return 0;
334 }
335 
AppSpawnClientSendMsg(AppSpawnClientHandle handle,AppSpawnReqMsgHandle reqHandle,AppSpawnResult * result)336 int AppSpawnClientSendMsg(AppSpawnClientHandle handle, AppSpawnReqMsgHandle reqHandle, AppSpawnResult *result)
337 {
338     APPSPAWN_CHECK(result != NULL, AppSpawnReqMsgFree(reqHandle);
339         return APPSPAWN_ARG_INVALID, "Invalid result");
340     result->result = APPSPAWN_ARG_INVALID;
341     result->pid = 0;
342     AppSpawnReqMsgMgr *reqMgr = (AppSpawnReqMsgMgr *)handle;
343     APPSPAWN_CHECK(reqMgr != NULL, AppSpawnReqMsgFree(reqHandle);
344         return APPSPAWN_ARG_INVALID, "Invalid reqMgr");
345     AppSpawnReqMsgNode *reqNode = (AppSpawnReqMsgNode *)reqHandle;
346     APPSPAWN_CHECK(reqNode != NULL && reqNode->msg != NULL, AppSpawnReqMsgFree(reqHandle);
347         return APPSPAWN_ARG_INVALID, "Invalid msgReq");
348 
349     APPSPAWN_LOGI("AppSpawnClientSendMsg reqId: %{public}u msgLen: %{public}u %{public}s",
350         reqNode->reqId, reqNode->msg->msgLen, reqNode->msg->processName);
351     pthread_mutex_lock(&reqMgr->mutex);
352     int ret = ClientSendMsg(reqMgr, reqNode, result);
353     if (ret != 0) {
354         result->result = ret;
355     }
356     pthread_mutex_unlock(&reqMgr->mutex);
357     APPSPAWN_LOGI("AppSpawnClientSendMsg reqId: %{public}u end result: 0x%{public}x pid: %{public}d",
358         reqNode->reqId, result->result, result->pid);
359     AppSpawnReqMsgFree(reqHandle);
360     return ret;
361 }
362 
AppSpawnClientSendUserLockStatus(uint32_t userId,bool isLocked)363 int AppSpawnClientSendUserLockStatus(uint32_t userId, bool isLocked)
364 {
365     char lockstatus[USER_LOCK_STATUS_SIZE] = {0};
366     int ret = snprintf_s(lockstatus, USER_LOCK_STATUS_SIZE, USER_LOCK_STATUS_SIZE - 1, "%u:%d", userId, isLocked);
367     APPSPAWN_CHECK(ret > 0, return ret, "Failed to build lockstatus req msg, ret = %{public}d", ret);
368     APPSPAWN_LOGI("Send lockstatus msg to appspawn %{public}s", lockstatus);
369 
370     AppSpawnReqMsgHandle reqHandle;
371     ret = AppSpawnReqMsgCreate(MSG_LOCK_STATUS, "storage_manager", &reqHandle);
372     APPSPAWN_CHECK(ret == 0, return ret, "Failed to create appspawn req msg, ret = %{public}d", ret);
373 
374     ret = AppSpawnReqMsgAddStringInfo(reqHandle, "lockstatus", lockstatus);
375     APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle);
376         return ret, "Failed to add lockstatus message, ret=%{public}d", ret);
377 
378     AppSpawnClientHandle clientHandle;
379     ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle);
380     APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle);
381         return ret, "Appspawn client failed to init, ret=%{public}d", ret);
382 
383     AppSpawnResult result = {0};
384     ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result);
385     AppSpawnClientDestroy(clientHandle);
386     APPSPAWN_CHECK(ret == 0, return ret, "Send msg to appspawn failed, ret=%{public}d", ret);
387 
388     if (result.result != 0) {
389         APPSPAWN_LOGE("Appspawn failed to handle message, result=%{public}d", result.result);
390         return result.result;
391     }
392     APPSPAWN_LOGI("Send lockstatus msg to appspawn success");
393     return 0;
394 }