1 /*
2  * Copyright (c) 2020-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 "sa_store.h"
16 #include <ohos_errno.h>
17 #include <securec.h>
18 #include "common.h"
19 #include "memory_adapter.h"
20 #ifdef MINI_SAMGR_LITE_RPC
21 #include "samgr_server.h"
22 #endif
23 
24 #define GROW_STEP 4
25 #define MAX_SA_NUM 300
26 static void FreeTreeNode(SAStore *saStore, ListNode *node);
27 static void SASTORA_ClearServiceByHandle(SAStore *saStore, uint32 handle);
FindServiceByName(ListNode * curNode,const char * service)28 static inline ListNode *FindServiceByName(ListNode *curNode, const char *service)
29 {
30     while (curNode != NULL) {
31         if (strncmp(curNode->info.name, service, MAX_NAME_LEN) == 0) {
32             break;
33         }
34         curNode = curNode->next;
35     }
36     return curNode;
37 }
38 
FindFeatureByName(FeatureNode * curNode,const char * feature)39 static inline FeatureNode *FindFeatureByName(FeatureNode *curNode, const char *feature)
40 {
41     while (curNode != NULL) {
42         if ((feature == NULL && curNode->isDefault) ||
43             (feature != NULL && strncmp(curNode->name, feature, MAX_NAME_LEN) == 0)) {
44             break;
45         }
46         curNode = curNode->next;
47     }
48     return curNode;
49 }
50 
SASTORA_Save(SAStore * saStore,const char * service,const char * feature,const SvcIdentity * identity)51 int SASTORA_Save(SAStore *saStore, const char *service, const char *feature, const SvcIdentity *identity)
52 {
53     if (saStore == NULL || service == NULL || identity == NULL) {
54         return EC_INVALID;
55     }
56 #ifdef MINI_SAMGR_LITE_RPC
57     SaNode *saNode = GetSaNodeBySaName(service, feature);
58     if (saNode != NULL) {
59         saNode->token = identity->token;
60     }
61 #endif
62     ListNode *curNode = FindServiceByName(saStore->root, service);
63     FeatureNode *fNode = (curNode == NULL) ? NULL : curNode->info.head;
64     fNode = FindFeatureByName(fNode, feature);
65     if (fNode != NULL) {
66         return EC_SUCCESS;
67     }
68 
69     if (saStore->saSize >= MAX_SA_NUM) {
70         return EC_NOSPACE;
71     }
72 
73     fNode = SAMGR_Malloc(sizeof(FeatureNode));
74     if (fNode == NULL) {
75         return EC_NOMEMORY;
76     }
77 
78     fNode->token = identity->token;
79     fNode->isDefault = feature == NULL;
80     fNode->name[0] = 0;
81     if (feature != NULL) {
82         if (strcpy_s(fNode->name, MAX_NAME_LEN, feature) != EOK) {
83             SAMGR_Free(fNode);
84             return EC_INVALID;
85         }
86     }
87 
88     if (curNode == NULL) {
89         curNode = SAMGR_Malloc(sizeof(ListNode));
90         if (curNode == NULL) {
91             SAMGR_Free(fNode);
92             return EC_NOMEMORY;
93         }
94         if (strcpy_s(curNode->info.name, MAX_NAME_LEN, service) != EOK) {
95             SAMGR_Free(fNode);
96             SAMGR_Free(curNode);
97             return EC_INVALID;
98         }
99         curNode->info.handle = identity->handle;
100         curNode->info.cookie = identity->cookie;
101         curNode->info.head = NULL;
102         curNode->next = saStore->root;
103         saStore->root = curNode;
104     }
105     fNode->next = curNode->info.head;
106     curNode->info.head = fNode;
107     saStore->saSize++;
108     return EC_SUCCESS;
109 }
110 
SASTORA_SaveHandleByPid(SAStore * saStore,PidHandle handle)111 int SASTORA_SaveHandleByPid(SAStore *saStore, PidHandle handle)
112 {
113     PidHandle saved = {.handle = INVALID_INDEX};
114     int index = SASTORA_FindHandleByPid(saStore, handle.pid, &saved);
115     if (saved.handle == handle.handle) {
116         return EC_SUCCESS;
117     }
118     if (index != INVALID_INDEX) {
119         saStore->maps[index] = handle;
120         return EC_SUCCESS;
121     }
122 
123     if (saStore->mapSize <= saStore->mapTop) {
124         PidHandle *newMap = (PidHandle *)SAMGR_Malloc(sizeof(PidHandle) * (saStore->mapSize + GROW_STEP));
125         if (newMap == NULL) {
126             return EC_NOMEMORY;
127         }
128 
129         if (saStore->maps != NULL) {
130             (void)memcpy_s(newMap, sizeof(PidHandle) * (saStore->mapSize + GROW_STEP),
131                            saStore->maps, sizeof(PidHandle) * saStore->mapSize);
132         }
133         PidHandle *oldMap = saStore->maps;
134         saStore->maps = newMap;
135         saStore->mapSize += GROW_STEP;
136         SAMGR_Free(oldMap);
137     }
138     int i;
139     for (i = saStore->mapTop - 1; i >= 0; --i) {
140         if (saStore->maps[i].pid < handle.pid) {
141             break;
142         }
143         saStore->maps[i + 1] = saStore->maps[i];
144     }
145     saStore->maps[i + 1] = handle;
146     ++(saStore->mapTop);
147     return EC_SUCCESS;
148 }
149 
SASTORA_FindHandleByPid(SAStore * saStore,pid_t callingPid,PidHandle * handle)150 int SASTORA_FindHandleByPid(SAStore *saStore, pid_t callingPid, PidHandle *handle)
151 {
152     if (saStore == NULL || saStore->maps == NULL || handle == NULL) {
153         return INVALID_INDEX;
154     }
155     int16 high = saStore->mapTop - 1;
156     int16 low = 0;
157     while (low <= high) {
158         // binary search need div 2
159         int16 mid = (high + low) / 2;
160         if (saStore->maps[mid].pid == callingPid) {
161             *handle = saStore->maps[mid];
162             return mid;
163         }
164         if (saStore->maps[mid].pid < callingPid) {
165             low = mid + 1;
166             continue;
167         }
168         high = mid - 1;
169     }
170     return INVALID_INDEX;
171 }
172 
SASTORA_FindHandleByUidPid(SAStore * saStore,uid_t callingUid,pid_t callingPid,PidHandle * handle)173 int SASTORA_FindHandleByUidPid(SAStore *saStore, uid_t callingUid, pid_t callingPid, PidHandle *handle)
174 {
175     if (saStore == NULL || saStore->maps == NULL || handle == NULL) {
176         return INVALID_INDEX;
177     }
178     int16 high = saStore->mapTop - 1;
179     int16 low = 0;
180     while (low <= high) {
181         // binary search need div 2
182         int16 mid = (high + low) / 2;
183         if (saStore->maps[mid].pid == callingPid && saStore->maps[mid].uid == callingUid) {
184             *handle = saStore->maps[mid];
185             return mid;
186         }
187         if (saStore->maps[mid].pid < callingPid) {
188             low = mid + 1;
189             continue;
190         }
191         high = mid - 1;
192     }
193     return INVALID_INDEX;
194 }
195 
SASTORA_FindPidHandleByIpcHandle(const SAStore * saStore,uint32 handle)196 PidHandle SASTORA_FindPidHandleByIpcHandle(const SAStore *saStore, uint32 handle)
197 {
198     PidHandle pidHandle = {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX, INVALID_INDEX};
199     if (saStore == NULL || saStore->maps == NULL) {
200         return pidHandle;
201     }
202     int i;
203     for (i = 0; i < saStore->mapTop; i++) {
204         if (saStore->maps[i].handle == handle) {
205             return saStore->maps[i];
206         }
207     }
208     return pidHandle;
209 }
210 
SASTORA_Find(SAStore * saStore,const char * service,const char * feature)211 SvcIdentity SASTORA_Find(SAStore *saStore, const char *service, const char *feature)
212 {
213     SvcIdentity identity = {(uint32)INVALID_INDEX, (uint32)INVALID_INDEX, (uint32)INVALID_INDEX};
214     ListNode *curNode = FindServiceByName(saStore->root, service);
215     if (curNode == NULL) {
216         return identity;
217     }
218 
219     identity.handle = curNode->info.handle;
220     identity.cookie = curNode->info.cookie;
221     FeatureNode *featureNode = FindFeatureByName(curNode->info.head, feature);
222     if (featureNode != NULL) {
223         identity.token = featureNode->token;
224     }
225     return identity;
226 }
227 
SASTORA_ClearByPid(SAStore * saStore,pid_t pid)228 int SASTORA_ClearByPid(SAStore *saStore, pid_t pid)
229 {
230     PidHandle pidHandle;
231     int index = SASTORA_FindHandleByPid(saStore, pid, &pidHandle);
232     if (index == INVALID_INDEX) {
233         return EC_INVALID;
234     }
235 
236     SASTORA_ClearServiceByHandle(saStore, pidHandle.handle);
237     if (saStore->mapTop <= (index + 1)) {
238         saStore->mapTop--;
239         return EC_SUCCESS;
240     }
241 
242     errno_t err = memmove_s(&saStore->maps[index], sizeof(PidHandle) * (saStore->mapTop - index),
243                             &saStore->maps[index + 1], sizeof(PidHandle) * (saStore->mapTop - index - 1));
244     if (err != EOK) {
245         return EC_FAILURE;
246     }
247     saStore->mapTop--;
248     return EC_SUCCESS;
249 }
250 
SASTORA_ClearServiceByHandle(SAStore * saStore,uint32 handle)251 static void SASTORA_ClearServiceByHandle(SAStore *saStore, uint32 handle)
252 {
253     ListNode *node = saStore->root;
254     ListNode *prev = NULL;
255     while (node != NULL) {
256         if (node->info.handle == handle) {
257             ListNode *freeNode = node;
258             if (prev != NULL) {
259                 prev->next = node->next;
260                 node = node->next;
261             } else {
262                 saStore->root = node->next;
263                 node = node->next;
264             }
265             FreeTreeNode(saStore, freeNode);
266             continue;
267         }
268         prev = node;
269         node = node->next;
270     }
271 }
272 
FreeTreeNode(SAStore * saStore,ListNode * node)273 static void FreeTreeNode(SAStore *saStore, ListNode *node)
274 {
275     while (node->info.head != NULL) {
276         FeatureNode *freeNode = node->info.head;
277         node->info.head = node->info.head->next;
278         SAMGR_Free(freeNode);
279         saStore->saSize--;
280     }
281     SAMGR_Free(node);
282 }