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 }