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 }