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