1/* 2 * Copyright (c) 2021-2022 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#include "init_param.h" 16 17#include <errno.h> 18#include <stddef.h> 19#include <string.h> 20#include <sys/socket.h> 21#include <unistd.h> 22 23#include "init_log.h" 24#include "init_utils.h" 25#include "param_atomic.h" 26#include "param_manager.h" 27#include "param_message.h" 28#include "param_security.h" 29 30#define INVALID_SOCKET (-1) 31static const uint32_t RECV_BUFFER_MAX = 5 * 1024; 32static ATOMIC_UINT32 g_requestId; 33static int g_clientFd = INVALID_SOCKET; 34static pthread_mutex_t g_clientMutex = PTHREAD_MUTEX_INITIALIZER; 35 36__attribute__((constructor)) static void ParameterInit(void) 37{ 38 ATOMIC_INIT(&g_requestId, 1); 39 EnableInitLog(INIT_INFO); 40 41 PARAM_WORKSPACE_OPS ops = {0}; 42 ops.updaterMode = 0; 43 ops.logFunc = InitLog; 44#ifdef PARAM_SUPPORT_SELINUX 45 ops.setfilecon = NULL; 46#endif 47 InitParamWorkSpace(1, &ops); 48 49 // modify log level 50 char logLevel[2] = {0}; // 2 is set param "persist.init.debug.loglevel" value length. 51 uint32_t len = sizeof(logLevel); 52 int ret = SystemReadParam(INIT_DEBUG_LEVEL, logLevel, &len); 53 if (ret == 0) { 54 errno = 0; 55 int level = atoi(logLevel); 56 if (errno != 0) { 57 return; 58 } 59 SetInitLogLevel((InitLogLevel)level); 60 } 61} 62 63__attribute__((destructor)) static void ParameterDeinit(void) 64{ 65 if (g_clientFd != INVALID_SOCKET) { 66 close(g_clientFd); 67 g_clientFd = INVALID_SOCKET; 68 } 69 pthread_mutex_destroy(&g_clientMutex); 70} 71 72static int ProcessRecvMsg(const ParamMessage *recvMsg) 73{ 74 PARAM_LOGV("ProcessRecvMsg type: %u msgId: %u name %s", recvMsg->type, recvMsg->id.msgId, recvMsg->key); 75 int result = PARAM_CODE_INVALID_PARAM; 76 switch (recvMsg->type) { 77 case MSG_SET_PARAM: 78 case MSG_SAVE_PARAM: 79 result = ((ParamResponseMessage *)recvMsg)->result; 80 break; 81 case MSG_NOTIFY_PARAM: { 82 uint32_t offset = 0; 83 ParamMsgContent *valueContent = GetNextContent(recvMsg, &offset); 84 PARAM_CHECK(valueContent != NULL, return PARAM_CODE_TIMEOUT, "Invalid msg"); 85 result = 0; 86 break; 87 } 88 default: 89 break; 90 } 91 return result; 92} 93 94static int ReadMessage(int fd, char *buffer, uint32_t timeout) 95{ 96 int ret = 0; 97 uint32_t diff = 0; 98 struct timespec startTime = {0}; 99 (void)clock_gettime(CLOCK_MONOTONIC, &startTime); 100 do { 101 ssize_t recvLen = recv(fd, (char *)buffer, RECV_BUFFER_MAX, 0); 102 if (recvLen <= 0) { 103 PARAM_LOGE("ReadMessage failed! errno %d", errno); 104 struct timespec finishTime = {0}; 105 (void)clock_gettime(CLOCK_MONOTONIC, &finishTime); 106 diff = IntervalTime(&finishTime, &startTime); 107 if (diff >= timeout) { 108 ret = PARAM_CODE_TIMEOUT; 109 break; 110 } 111 if (errno == EAGAIN || errno == EINTR) { 112 usleep(10*1000); // 10*1000 wait 10ms 113 continue; 114 } 115 } 116 117 if ((size_t)recvLen > sizeof(ParamMessage)) { 118 PARAM_LOGV("recv message len is %d", recvLen); 119 break; 120 } 121 } while (1); 122 123 if (ret != 0) { 124 PARAM_LOGE("ReadMessage errno %d diff %u timeout %d ret %d", errno, diff, timeout, ret); 125 } 126 return ret; 127} 128 129static int GetClientSocket(int timeout) 130{ 131 struct timeval time = {0}; 132 time.tv_sec = timeout; 133 time.tv_usec = 0; 134 int clientFd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); 135 PARAM_CHECK(clientFd >= 0, return INVALID_SOCKET, "Failed to create socket"); 136 int ret = ConnectServer(clientFd, CLIENT_PIPE_NAME); 137 if (ret == 0) { 138 setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval)); 139 setsockopt(clientFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time, sizeof(struct timeval)); 140 } else { 141 close(clientFd); 142 clientFd = INVALID_SOCKET; 143 } 144 return clientFd; 145} 146 147static int StartRequest(int clientFd, ParamMessage *request, int timeout) 148{ 149 errno = 0; 150 ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0); 151 if (errno == EINVAL || errno == EACCES) { 152 PARAM_LOGE("send Message failed!"); 153 return PARAM_CODE_IPC_ERROR; 154 } 155 PARAM_CHECK(sendLen >= 0, return PARAM_CODE_IPC_ERROR, "Failed to send message err: %d", errno); 156 PARAM_LOGV("sendMessage sendLen fd %d %zd", clientFd, sendLen); 157 if (timeout <= 0) { 158 return 0; 159 } 160 int ret = ReadMessage(clientFd, (char *)request, timeout); 161 if (ret == 0) { 162 ret = ProcessRecvMsg(request); 163 } 164 return ret; 165} 166 167static int SystemSetParameter_(const char *name, const char *value, int timeout) 168{ 169 PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value"); 170 int ret = CheckParamName(name, 0); 171 PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name); 172 ret = CheckParamValue(NULL, name, value, GetParamValueType(name)); 173 PARAM_CHECK(ret == 0, return ret, "Illegal param value %s", value); 174 175 size_t msgSize = sizeof(ParamMsgContent); 176 msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize; 177 178 ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize); 179 PARAM_CHECK(request != NULL, return PARAM_CODE_ERROR, "Failed to create Param Message"); 180 uint32_t offset = 0; 181 ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); 182 PARAM_CHECK(ret == 0, free(request); 183 return PARAM_CODE_ERROR, "Failed to fill value"); 184 request->msgSize = offset + sizeof(ParamMessage); 185 request->id.msgId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); 186 187 pthread_mutex_lock(&g_clientMutex); 188 int retryCount = 0; 189 while (retryCount < 2) { // max retry 2 190 if (g_clientFd == INVALID_SOCKET) { 191 g_clientFd = GetClientSocket(DEFAULT_PARAM_SET_TIMEOUT); 192 } 193 194 if (g_clientFd < 0) { 195 ret = PARAM_CODE_FAIL_CONNECT; 196 PARAM_LOGE("connect param server failed!"); 197 break; 198 } 199 ret = StartRequest(g_clientFd, request, timeout); 200 if (ret == PARAM_CODE_IPC_ERROR) { 201 close(g_clientFd); 202 g_clientFd = INVALID_SOCKET; 203 retryCount++; 204 } else { 205 break; 206 } 207 } 208 PARAM_LOGI("SystemSetParameter name %s msgid:%d ret: %d ", name, request->id.msgId, ret); 209 pthread_mutex_unlock(&g_clientMutex); 210 free(request); 211 return ret; 212} 213 214int SystemSetParameter(const char *name, const char *value) 215{ 216 int ret = SystemSetParameter_(name, value, DEFAULT_PARAM_SET_TIMEOUT); 217 BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSetParameter failed! name is :%s, the errNum is:%d", name, ret); 218 return ret; 219} 220 221int SystemSetParameterNoWait(const char *name, const char *value) 222{ 223 int ret = SystemSetParameter_(name, value, 0); 224 BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSetParameterNoWait failed! name is:%s, the errNum is:%d", name, ret); 225 return ret; 226} 227 228int SystemSaveParameters(void) 229{ 230 const char *name = "persist.all"; 231 size_t msgSize = RECV_BUFFER_MAX; 232 uint32_t offset = 0; 233 ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SAVE_PARAM, name, msgSize); 234 PARAM_CHECK(request != NULL, return -1, "SystemSaveParameters failed! name is:%s, the errNum is:-1", name); 235 int ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1); 236 PARAM_CHECK(ret == 0, free(request); 237 return -1, "SystemSaveParameters failed! the errNum is:-1"); 238 int fd = GetClientSocket(DEFAULT_PARAM_WAIT_TIMEOUT); 239 PARAM_CHECK(fd >= 0, free(request); 240 return fd, "SystemSaveParameters failed! the errNum is:%d", ret); 241 request->msgSize = offset + sizeof(ParamMessage); 242 request->id.msgId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); 243 ret = StartRequest(fd, request, DEFAULT_PARAM_WAIT_TIMEOUT); 244 close(fd); 245 free(request); 246 BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemSaveParameters failed! the errNum is:%d", ret); 247 return ret; 248} 249 250int SystemWaitParameter(const char *name, const char *value, int32_t timeout) 251{ 252 PARAM_CHECK(name != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); 253 int ret = CheckParamName(name, 0); 254 PARAM_CHECK(ret == 0, return ret, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); 255 ret = CheckParamPermission(GetParamSecurityLabel(), name, DAC_READ); 256 PARAM_CHECK(ret == 0, return ret, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); 257 if (timeout <= 0) { 258 timeout = DEFAULT_PARAM_WAIT_TIMEOUT; 259 } 260 uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + sizeof(uint32_t); 261 msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize; 262 uint32_t offset = 0; 263 ParamMessage *request = NULL; 264 if (value != NULL && strlen(value) > 0) { 265 msgSize += PARAM_ALIGN(strlen(value) + 1); 266 request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize); 267 PARAM_CHECK(request != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); 268 ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value)); 269 } else { 270 msgSize += PARAM_ALIGN(1); 271 request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize); 272 PARAM_CHECK(request != NULL, return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); 273 ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1); 274 } 275 PARAM_CHECK(ret == 0, free(request); 276 return -1, "SystemWaitParameter failed! name is:%s, the errNum is:-1", name); 277 ParamMsgContent *content = (ParamMsgContent *)(request->data + offset); 278 content->type = PARAM_WAIT_TIMEOUT; 279 content->contentSize = sizeof(uint32_t); 280 *((uint32_t *)(content->content)) = timeout; 281 offset += sizeof(ParamMsgContent) + sizeof(uint32_t); 282 283 request->msgSize = offset + sizeof(ParamMessage); 284 request->id.waitId = ATOMIC_SYNC_ADD_AND_FETCH(&g_requestId, 1, MEMORY_ORDER_RELAXED); 285#ifdef STARTUP_INIT_TEST 286 timeout = 1; 287#endif 288 int fd = GetClientSocket(timeout); 289 PARAM_CHECK(fd >= 0, free(request); 290 return fd, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); 291 ret = StartRequest(fd, request, timeout); 292 close(fd); 293 free(request); 294 PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret); 295 BEGET_CHECK_ONLY_ELOG(ret == 0, "SystemWaitParameter failed! name is:%s, the errNum is:%d", name, ret); 296 return ret; 297} 298 299int SystemCheckParamExist(const char *name) 300{ 301 return SysCheckParamExist(name); 302} 303 304int WatchParamCheck(const char *keyprefix) 305{ 306 PARAM_CHECK(keyprefix != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid keyprefix"); 307 int ret = CheckParamName(keyprefix, 0); 308 PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", keyprefix); 309 ret = CheckParamPermission(GetParamSecurityLabel(), keyprefix, DAC_WATCH); 310 PARAM_CHECK(ret == 0, return ret, "Forbid to watcher parameter %s", keyprefix); 311 return 0; 312} 313 314void ResetParamSecurityLabel(void) 315{ 316#ifdef RESET_CHILD_FOR_VERIFY 317 ParamWorkSpace *paramSpace = GetParamWorkSpace(); 318 PARAM_CHECK(paramSpace != NULL, return, "Invalid paramSpace"); 319#if !(defined __LITEOS_A__ || defined __LITEOS_M__) 320 paramSpace->securityLabel.cred.pid = getpid(); 321 paramSpace->securityLabel.cred.uid = geteuid(); 322 paramSpace->securityLabel.cred.gid = getegid(); 323 paramSpace->flags |= WORKSPACE_FLAGS_NEED_ACCESS; 324#endif 325#endif 326 PARAM_LOGI("ResetParamSecurityLabel g_clientFd: %d ", g_clientFd); 327 pthread_mutex_lock(&g_clientMutex); 328 if (g_clientFd != INVALID_SOCKET) { 329 close(g_clientFd); 330 g_clientFd = INVALID_SOCKET; 331 } 332 pthread_mutex_unlock(&g_clientMutex); 333} 334