• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "param_request.h"
16 
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <stddef.h>
20 #include <string.h>
21 #include <sys/socket.h>
22 #include <unistd.h>
23 
24 #include "init_utils.h"
25 #include "param_manager.h"
26 #include "param_message.h"
27 #include "param_security.h"
28 
29 #define INVALID_SOCKET (-1)
30 #define INIT_PROCESS_PID 1
31 
32 static const uint32_t RECV_BUFFER_MAX = 5 * 1024;
33 
34 static atomic_uint g_requestId = ATOMIC_VAR_INIT(1);
35 static ClientWorkSpace g_clientSpace = { {}, -1, {} };
36 
37 __attribute__((constructor)) static void ClientInit(void);
38 __attribute__((destructor)) static void ClientDeinit(void);
39 
InitParamClient(void)40 static int InitParamClient(void)
41 {
42     if (getpid() == INIT_PROCESS_PID) {
43         PARAM_LOGI("Init process, do not init client");
44         return 0;
45     }
46     if (PARAM_TEST_FLAG(g_clientSpace.paramSpace.flags, WORKSPACE_FLAGS_INIT)) {
47         return 0;
48     }
49     PARAM_LOGV("InitParamClient");
50     pthread_mutex_init(&g_clientSpace.mutex, NULL);
51     g_clientSpace.clientFd = INVALID_SOCKET;
52     return InitParamWorkSpace(&g_clientSpace.paramSpace, 1);
53 }
54 
ClientInit(void)55 void ClientInit(void)
56 {
57     PARAM_LOGV("ClientInit");
58     (void)InitParamClient();
59 }
60 
ClientDeinit(void)61 void ClientDeinit(void)
62 {
63 }
64 
GetClientParamSecurityOps(void)65 static ParamSecurityOps *GetClientParamSecurityOps(void)
66 {
67     return &g_clientSpace.paramSpace.paramSecurityOps;
68 }
69 
FillLabelContent(const ParamMessage * request,uint32_t * start,uint32_t length)70 static int FillLabelContent(const ParamMessage *request, uint32_t *start, uint32_t length)
71 {
72     uint32_t bufferSize = request->msgSize - sizeof(ParamMessage);
73     uint32_t offset = *start;
74     PARAM_CHECK((offset + sizeof(ParamMsgContent) + length) <= bufferSize,
75         return -1, "Invalid msgSize %u offset %u", request->msgSize, offset);
76     ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
77     content->type = PARAM_LABEL;
78     content->contentSize = 0;
79     ParamSecurityOps *ops = GetClientParamSecurityOps();
80     if (length != 0 && ops != NULL && ops->securityEncodeLabel != NULL) {
81         int ret = ops->securityEncodeLabel(g_clientSpace.paramSpace.securityLabel, content->content, &length);
82         PARAM_CHECK(ret == 0, return -1, "Failed to get label length");
83         content->contentSize = length;
84     }
85     offset += sizeof(ParamMsgContent) + PARAM_ALIGN(content->contentSize);
86     *start = offset;
87     return 0;
88 }
89 
ProcessRecvMsg(const ParamMessage * recvMsg)90 static int ProcessRecvMsg(const ParamMessage *recvMsg)
91 {
92     PARAM_LOGV("ProcessRecvMsg type: %u msgId: %u name %s", recvMsg->type, recvMsg->id.msgId, recvMsg->key);
93     int result = PARAM_CODE_INVALID_PARAM;
94     switch (recvMsg->type) {
95         case MSG_SET_PARAM:
96             result = ((ParamResponseMessage *)recvMsg)->result;
97             break;
98         case MSG_NOTIFY_PARAM: {
99             uint32_t offset = 0;
100             ParamMsgContent *valueContent = GetNextContent(recvMsg, &offset);
101             PARAM_CHECK(valueContent != NULL, return PARAM_CODE_TIMEOUT, "Invalid msg");
102             result = 0;
103             break;
104         }
105         default:
106             break;
107     }
108     return result;
109 }
110 
StartRequest(int * fd,ParamMessage * request,int timeout)111 static int StartRequest(int *fd, ParamMessage *request, int timeout)
112 {
113     int ret = 0;
114     struct timeval time;
115 #ifndef STARTUP_INIT_TEST
116     time.tv_sec = timeout;
117 #else
118     time.tv_sec = 1;
119 #endif
120     time.tv_usec = 0;
121     do {
122         int clientFd = *fd;
123         if (clientFd == INVALID_SOCKET) {
124             clientFd = socket(AF_UNIX, SOCK_STREAM, 0);
125             PARAM_CHECK(clientFd >= 0, return PARAM_CODE_FAIL_CONNECT, "Failed to create socket");
126             ret = ConntectServer(clientFd, CLIENT_PIPE_NAME);
127             PARAM_CHECK(ret == 0, close(clientFd);
128                 return PARAM_CODE_FAIL_CONNECT, "Failed to connect server");
129             setsockopt(clientFd, SOL_SOCKET, SO_SNDTIMEO, (char *)&time, sizeof(struct timeval));
130             setsockopt(clientFd, SOL_SOCKET, SO_RCVTIMEO, (char *)&time, sizeof(struct timeval));
131             *fd = clientFd;
132         }
133         ssize_t recvLen = 0;
134         ssize_t sendLen = send(clientFd, (char *)request, request->msgSize, 0);
135         if (sendLen > 0) {
136             recvLen = recv(clientFd, (char *)request, RECV_BUFFER_MAX, 0);
137             if (recvLen > 0) {
138                 break;
139             }
140         }
141         ret = errno;
142         close(clientFd);
143         *fd = INVALID_SOCKET;
144         if (errno == EAGAIN || recvLen <= 0) {
145             ret = PARAM_CODE_TIMEOUT;
146             break;
147         }
148         PARAM_LOGE("Send or recv msg fail errno %d %zd %zd", errno, sendLen, recvLen);
149     } while (1);
150 
151     if (ret == 0) { // check result
152         ret = ProcessRecvMsg(request);
153     }
154     return ret;
155 }
156 
NeedCheckParamPermission(const char * name)157 static int NeedCheckParamPermission(const char *name)
158 {
159     static char *ctrlParam[] = {
160         "ohos.ctl.start",
161         "ohos.ctl.stop",
162         "ohos.startup.powerctrl"
163     };
164     for (size_t i = 0; i < ARRAY_LENGTH(ctrlParam); i++) {
165         if (strcmp(name, ctrlParam[i]) == 0) {
166             return 0;
167         }
168     }
169     ParamSecurityLabel *securityLabel = g_clientSpace.paramSpace.securityLabel;
170     if (securityLabel != NULL &&
171         ((securityLabel->flags & LABEL_CHECK_FOR_ALL_PROCESS) == LABEL_CHECK_FOR_ALL_PROCESS) &&
172         ((securityLabel->flags & LABEL_ALL_PERMISSION) != LABEL_ALL_PERMISSION)) {
173         return 1;
174     }
175     return 0;
176 }
177 
SystemSetParameter(const char * name,const char * value)178 int SystemSetParameter(const char *name, const char *value)
179 {
180     InitParamClient();
181     PARAM_CHECK(name != NULL && value != NULL, return -1, "Invalid name or value");
182     int ret = CheckParamName(name, 0);
183     PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
184     uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + PARAM_ALIGN(strlen(value) + 1);
185     uint32_t labelLen = 0;
186     ParamSecurityOps *ops = GetClientParamSecurityOps();
187     if (NeedCheckParamPermission(name) == 1) {
188         ret = CheckParamPermission(&g_clientSpace.paramSpace, g_clientSpace.paramSpace.securityLabel, name, DAC_WRITE);
189         PARAM_CHECK(ret == 0, return ret, "Forbit to set parameter %s", name);
190     } else if (!LABEL_IS_ALL_PERMITTED(g_clientSpace.paramSpace.securityLabel)) { // check local can check permissions
191         PARAM_CHECK(ops != NULL && ops->securityEncodeLabel != NULL, return -1, "Invalid securityEncodeLabel");
192         ret = ops->securityEncodeLabel(g_clientSpace.paramSpace.securityLabel, NULL, &labelLen);
193         PARAM_CHECK(ret == 0, return -1, "Failed to get label length");
194     }
195     msgSize += sizeof(ParamMsgContent) + labelLen;
196     msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize;
197 
198     ParamMessage *request = (ParamMessage *)CreateParamMessage(MSG_SET_PARAM, name, msgSize);
199     PARAM_CHECK(request != NULL, return -1, "Failed to malloc for connect");
200     uint32_t offset = 0;
201     ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
202     PARAM_CHECK(ret == 0, free(request);
203         return -1, "Failed to fill value");
204     ret = FillLabelContent(request, &offset, labelLen);
205     PARAM_CHECK(ret == 0, free(request);
206         return -1, "Failed to fill label");
207     request->msgSize = offset + sizeof(ParamMessage);
208     request->id.msgId = atomic_fetch_add(&g_requestId, 1);
209 
210     pthread_mutex_lock(&g_clientSpace.mutex);
211     ret = StartRequest(&g_clientSpace.clientFd, request, DEFAULT_PARAM_SET_TIMEOUT);
212     pthread_mutex_unlock(&g_clientSpace.mutex);
213     free(request);
214     return ret;
215 }
216 
SystemWaitParameter(const char * name,const char * value,int32_t timeout)217 int SystemWaitParameter(const char *name, const char *value, int32_t timeout)
218 {
219     InitParamClient();
220     PARAM_CHECK(name != NULL, return -1, "Invalid name");
221     int ret = CheckParamName(name, 0);
222     PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", name);
223     ParamHandle handle = 0;
224     ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, &handle);
225     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
226         PARAM_CHECK(ret == 0, return ret, "Forbid to wait parameter %s", name);
227     }
228     if (timeout <= 0) {
229         timeout = DEFAULT_PARAM_WAIT_TIMEOUT;
230     }
231     uint32_t msgSize = sizeof(ParamMessage) + sizeof(ParamMsgContent) + sizeof(ParamMsgContent) + sizeof(uint32_t);
232     msgSize = (msgSize < RECV_BUFFER_MAX) ? RECV_BUFFER_MAX : msgSize;
233     uint32_t offset = 0;
234     ParamMessage *request = NULL;
235     if (value != NULL && strlen(value) > 0) {
236         msgSize += PARAM_ALIGN(strlen(value) + 1);
237         request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
238         PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
239         ret = FillParamMsgContent(request, &offset, PARAM_VALUE, value, strlen(value));
240     } else {
241         msgSize += PARAM_ALIGN(1);
242         request = (ParamMessage *)CreateParamMessage(MSG_WAIT_PARAM, name, msgSize);
243         PARAM_CHECK(request != NULL, return -1, "Failed to malloc for wait");
244         ret = FillParamMsgContent(request, &offset, PARAM_VALUE, "*", 1);
245     }
246     PARAM_CHECK(ret == 0, free(request);
247         return -1, "Failed to fill value");
248     ParamMsgContent *content = (ParamMsgContent *)(request->data + offset);
249     content->type = PARAM_WAIT_TIMEOUT;
250     content->contentSize = sizeof(uint32_t);
251     *((uint32_t *)(content->content)) = timeout;
252     offset += sizeof(ParamMsgContent) + sizeof(uint32_t);
253 
254     request->msgSize = offset + sizeof(ParamMessage);
255     request->id.waitId = atomic_fetch_add(&g_requestId, 1);
256     int fd = INVALID_SOCKET;
257     ret = StartRequest(&fd, request, timeout);
258     if (fd != INVALID_SOCKET) {
259         close(fd);
260     }
261     free(request);
262     PARAM_LOGI("SystemWaitParameter %s value %s result %d ", name, value, ret);
263     return ret;
264 }
265 
SystemGetParameter(const char * name,char * value,unsigned int * len)266 int SystemGetParameter(const char *name, char *value, unsigned int *len)
267 {
268     InitParamClient();
269     PARAM_CHECK(name != NULL && len != NULL, return -1, "The name or value is null");
270     ParamHandle handle = 0;
271     int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, &handle);
272     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
273         PARAM_CHECK(ret == 0, return ret, "Forbid to get parameter %s", name);
274     }
275     return ReadParamValue(&g_clientSpace.paramSpace, handle, value, len);
276 }
277 
SystemFindParameter(const char * name,ParamHandle * handle)278 int SystemFindParameter(const char *name, ParamHandle *handle)
279 {
280     InitParamClient();
281     PARAM_CHECK(name != NULL && handle != NULL, return -1, "The name or handle is null");
282     int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, handle);
283     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
284         PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name);
285     }
286     return ret;
287 }
288 
SysCheckParamExist(const char * name)289 int SysCheckParamExist(const char *name)
290 {
291     InitParamClient();
292     PARAM_CHECK(name != NULL, return -1, "The name or handle is null");
293     ParamHandle handle;
294     int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, name, DAC_READ, &handle);
295     PARAM_LOGI("SysCheckParamExist %s result %d", name, ret);
296     if (ret == PARAM_CODE_NODE_EXIST) {
297         return 0;
298     }
299     PARAM_CHECK(ret == 0, return ret, "Forbid to access parameter %s", name);
300     return ret;
301 }
302 
SystemGetParameterCommitId(ParamHandle handle,uint32_t * commitId)303 int SystemGetParameterCommitId(ParamHandle handle, uint32_t *commitId)
304 {
305     PARAM_CHECK(handle != 0 || commitId != NULL, return -1, "The handle is null");
306     return ReadParamCommitId(&g_clientSpace.paramSpace, handle, commitId);
307 }
308 
SystemGetParameterName(ParamHandle handle,char * name,unsigned int len)309 int SystemGetParameterName(ParamHandle handle, char *name, unsigned int len)
310 {
311     PARAM_CHECK(name != NULL && handle != 0, return -1, "The name is null");
312     return ReadParamName(&g_clientSpace.paramSpace, handle, name, len);
313 }
314 
SystemGetParameterValue(ParamHandle handle,char * value,unsigned int * len)315 int SystemGetParameterValue(ParamHandle handle, char *value, unsigned int *len)
316 {
317     PARAM_CHECK(len != NULL && handle != 0, return -1, "The value is null");
318     return ReadParamValue(&g_clientSpace.paramSpace, handle, value, len);
319 }
320 
SystemTraversalParameter(const char * prefix,void (* traversalParameter)(ParamHandle handle,void * cookie),void * cookie)321 int SystemTraversalParameter(const char *prefix,
322     void (*traversalParameter)(ParamHandle handle, void *cookie), void *cookie)
323 {
324     InitParamClient();
325     PARAM_CHECK(traversalParameter != NULL, return -1, "The param is null");
326     ParamHandle handle = 0;
327     // check default dac
328     const char *tmp = (prefix == NULL || strlen(prefix) == 0) ? "#" : prefix;
329     int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, tmp, DAC_READ, &handle);
330     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
331         PARAM_CHECK(ret == 0, return ret, "Forbid to traversal parameters");
332     }
333     return TraversalParam(&g_clientSpace.paramSpace, tmp, traversalParameter, cookie);
334 }
335 
SystemDumpParameters(int verbose)336 void SystemDumpParameters(int verbose)
337 {
338     InitParamClient();
339     // check default dac
340     ParamHandle handle = 0;
341     int ret = ReadParamWithCheck(&g_clientSpace.paramSpace, "#", DAC_READ, &handle);
342     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
343         PARAM_CHECK(ret == 0, return, "Forbid to dump parameters");
344     }
345     DumpParameters(&g_clientSpace.paramSpace, verbose);
346 }
347 
WatchParamCheck(const char * keyprefix)348 int WatchParamCheck(const char *keyprefix)
349 {
350     InitParamClient();
351     PARAM_CHECK(keyprefix != NULL, return PARAM_CODE_INVALID_PARAM, "Invalid keyprefix");
352     int ret = CheckParamName(keyprefix, 0);
353     PARAM_CHECK(ret == 0, return ret, "Illegal param name %s", keyprefix);
354     ParamHandle handle = 0;
355     ret = ReadParamWithCheck(&g_clientSpace.paramSpace, keyprefix, DAC_WATCH, &handle);
356     if (ret != PARAM_CODE_NOT_FOUND && ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
357         PARAM_CHECK(ret == 0, return ret, "Forbid to watch parameter %s", keyprefix);
358     }
359     return 0;
360 }
361 
GetParamSecurityAuditData(const char * name,int type,ParamAuditData * auditData)362 int GetParamSecurityAuditData(const char *name, int type, ParamAuditData *auditData)
363 {
364     uint32_t labelIndex = 0;
365     FindTrieNode(&g_clientSpace.paramSpace.paramSpace, name, strlen(name), &labelIndex);
366     ParamSecruityNode *node = (ParamSecruityNode *)GetTrieNode(&g_clientSpace.paramSpace.paramSpace, labelIndex);
367     PARAM_CHECK(node != NULL, return DAC_RESULT_FORBIDED, "Can not get security label %d", labelIndex);
368 
369     auditData->name = name;
370     auditData->dacData.uid = node->uid;
371     auditData->dacData.gid = node->gid;
372     auditData->dacData.mode = node->mode;
373     if (node->length > 0) {
374         auditData->label = strdup(node->data);
375     }
376     return 0;
377 }
378 
379 #if (defined STARTUP_INIT_TEST || defined PARAM_TEST)
GetClientParamWorkSpace(void)380 ParamWorkSpace *GetClientParamWorkSpace(void)
381 {
382     return &g_clientSpace.paramSpace;
383 }
384 #endif