• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "nativetoken.h"
16 
17 #ifdef WITH_SELINUX
18 #include <policycoreutils.h>
19 #endif // WITH_SELINUX
20 
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/stat.h>
27 #include <unistd.h>
28 #include "accesstoken_klog.h"
29 #include "hisysevent_common.h"
30 #include "nativetoken_hisysevent.h"
31 #include "nativetoken_json_oper.h"
32 #include "nativetoken_kit.h"
33 #include "securec.h"
34 
35 NativeTokenList *g_tokenListHead;
36 int32_t g_isNativeTokenInited = 0;
37 const uint64_t g_nativeFdTag = 0xD005A01;
38 
39 #define BREAK_IF_TRUE(cond) \
40     if (cond) { \
41         break; \
42     }
43 
GetFileBuff(const char * cfg,char ** retBuff)44 uint32_t GetFileBuff(const char *cfg, char **retBuff)
45 {
46     struct stat fileStat;
47 
48     char filePath[PATH_MAX_LEN + 1] = {0};
49     if (realpath(cfg, filePath) == NULL) {
50         if (errno == ENOENT) {
51             /* file doesn't exist */
52             *retBuff = NULL;
53             return ATRET_SUCCESS;
54         }
55         LOGC("Invalid filePath, errno=%d.", errno);
56         return GET_FILE_BUFF_FAILED;
57     }
58 
59     if (stat(filePath, &fileStat) != 0) {
60         LOGC("Failed to stat file, errno=%d.", errno);
61         return GET_FILE_BUFF_FAILED;
62     }
63 
64     if (fileStat.st_size == 0) {
65         LOGI("Empty file");
66         *retBuff = NULL;
67         return ATRET_SUCCESS;
68     }
69 
70     if (fileStat.st_size > MAX_JSON_FILE_LEN) {
71         LOGC("Invalid size.");
72         return GET_FILE_BUFF_FAILED;
73     }
74 
75     size_t fileSize = (unsigned)fileStat.st_size;
76 
77     FILE *cfgFd = fopen(filePath, "r");
78     if (cfgFd == NULL) {
79         LOGC("Failed to fopen file, errno=%d.", errno);
80         return GET_FILE_BUFF_FAILED;
81     }
82 
83     char *buff = (char *)malloc((size_t)(fileSize + 1));
84     if (buff == NULL) {
85         LOGC("Failed to alloc memory for buffer.");
86         (void)fclose(cfgFd);
87         return GET_FILE_BUFF_FAILED;
88     }
89     size_t readSize = fread(buff, fileSize, 1, cfgFd);
90     if (readSize != 1) {
91         LOGC("Failed to fread, readSize=%zu, errno=%d.", readSize, errno);
92         free(buff);
93         buff = NULL;
94         (void)fclose(cfgFd);
95         return GET_FILE_BUFF_FAILED;
96     }
97     buff[fileSize] = '\0';
98     *retBuff = buff;
99     (void)fclose(cfgFd);
100     return ATRET_SUCCESS;
101 }
102 
StrAttrSet(StrArrayAttr * attr,uint32_t maxStrLen,int32_t maxStrNum,const char * strKey)103 static void StrAttrSet(StrArrayAttr *attr, uint32_t maxStrLen, int32_t maxStrNum, const char *strKey)
104 {
105     attr->maxStrLen = maxStrLen;
106     attr->maxStrNum = maxStrNum;
107     attr->strKey = strKey;
108 }
109 
GetNativeTokenFromJson(cJSON * cjsonItem,NativeTokenList * tokenNode)110 static uint32_t GetNativeTokenFromJson(cJSON *cjsonItem, NativeTokenList *tokenNode)
111 {
112     uint32_t ret;
113     StrArrayAttr attr;
114 
115     ret = GetProcessNameFromJson(cjsonItem, tokenNode);
116     if (ret != ATRET_SUCCESS) {
117         LOGC("Failed to GetProcessNameFromJson.");
118         return ATRET_FAILED;
119     }
120     ret = GetTokenIdFromJson(cjsonItem, tokenNode);
121     if (ret != ATRET_SUCCESS) {
122         LOGC("Failed to GetTokenIdFromJson.");
123         return ATRET_FAILED;
124     }
125     ret = GetAplFromJson(cjsonItem, tokenNode);
126     if (ret != ATRET_SUCCESS) {
127         LOGC("Failed to GetAplFromJson.");
128         return ATRET_FAILED;
129     }
130 
131     StrAttrSet(&attr, MAX_DCAP_LEN, MAX_DCAPS_NUM, DCAPS_KEY_NAME);
132     ret = GetInfoArrFromJson(cjsonItem, &tokenNode->dcaps, &(tokenNode->dcapsNum), &attr);
133     if (ret != ATRET_SUCCESS) {
134         LOGC("Failed to GetInfoArrFromJson for dcaps.");
135         return ATRET_FAILED;
136     }
137 
138     StrAttrSet(&attr, MAX_PERM_LEN, MAX_PERM_NUM, PERMS_KEY_NAME);
139     ret = GetInfoArrFromJson(cjsonItem, &tokenNode->perms, &(tokenNode->permsNum), &attr);
140     if (ret != ATRET_SUCCESS) {
141         FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
142         LOGC("Failed to GetInfoArrFromJsonfor perms.");
143         return ATRET_FAILED;
144     }
145 
146     StrAttrSet(&attr, MAX_PERM_LEN, MAX_PERM_NUM, ACLS_KEY_NAME);
147     ret = GetInfoArrFromJson(cjsonItem, &tokenNode->acls, &(tokenNode->aclsNum), &attr);
148     if (ret != ATRET_SUCCESS) {
149         FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
150         FreeStrArray(&tokenNode->perms, tokenNode->permsNum - 1);
151         LOGC("Failed to GetInfoArrFromJsonfor acls.");
152         return ATRET_FAILED;
153     }
154     return ATRET_SUCCESS;
155 }
156 
FreeTokenNode(NativeTokenList ** node)157 static void FreeTokenNode(NativeTokenList **node)
158 {
159     if (node == NULL || *node == NULL) {
160         return;
161     }
162     FreeStrArray(&(*node)->dcaps, (*node)->dcapsNum - 1);
163     FreeStrArray(&(*node)->perms, (*node)->permsNum - 1);
164     FreeStrArray(&(*node)->perms, (*node)->permsNum - 1);
165     free(*node);
166     *node = NULL;
167 }
168 
RemoveNodeFromList(NativeTokenList ** node)169 static void RemoveNodeFromList(NativeTokenList **node)
170 {
171     if (node == NULL || *node == NULL || g_tokenListHead == NULL) {
172         return;
173     }
174     NativeTokenList *tmp = g_tokenListHead;
175     while (tmp != NULL) {
176         if (tmp->next == *node) {
177             tmp->next = (*node)->next;
178             FreeTokenNode(node);
179             return;
180         }
181         tmp = tmp->next;
182     }
183 }
184 
FreeTokenList(void)185 static void FreeTokenList(void)
186 {
187     if (g_tokenListHead == NULL) {
188         return;
189     }
190     NativeTokenList *tmp = g_tokenListHead->next;
191     while (tmp != NULL) {
192         NativeTokenList *toFreeNode = tmp;
193         tmp = tmp->next;
194         FreeTokenNode(&toFreeNode);
195     }
196     g_tokenListHead->next = NULL;
197 }
198 
GetTokenList(const cJSON * object)199 static uint32_t GetTokenList(const cJSON *object)
200 {
201     NativeTokenList *tmp = NULL;
202 
203     if (object == NULL) {
204         LOGC("Oobject is null.");
205         return GET_TOKEN_LIST_FAILED;
206     }
207     int32_t arraySize = cJSON_GetArraySize(object);
208     if (arraySize <= 0) {
209         LOGC("Empty array.");
210         return GET_TOKEN_LIST_FAILED;
211     }
212 
213     for (int32_t i = 0; i < arraySize; i++) {
214         tmp = (NativeTokenList *)malloc(sizeof(NativeTokenList));
215         if (tmp == NULL) {
216             LOGC("Failed to alloc memory for node.");
217             FreeTokenList();
218             return GET_TOKEN_LIST_FAILED;
219         }
220         cJSON *cjsonItem = cJSON_GetArrayItem(object, i);
221         if (cjsonItem == NULL) {
222             free(tmp);
223             FreeTokenList();
224             LOGC("Failed to cJSON_GetArrayItem.");
225             return GET_TOKEN_LIST_FAILED;
226         }
227         if (GetNativeTokenFromJson(cjsonItem, tmp) != ATRET_SUCCESS) {
228             free(tmp);
229             FreeTokenList();
230             LOGC("Failed to GetNativeTokenFromJson.");
231             return GET_TOKEN_LIST_FAILED;
232         }
233 
234         tmp->next = g_tokenListHead->next;
235         g_tokenListHead->next = tmp;
236     }
237     return ATRET_SUCCESS;
238 }
239 
ParseTokenInfo(void)240 static uint32_t ParseTokenInfo(void)
241 {
242     char *fileBuff = NULL;
243     cJSON *record = NULL;
244     uint32_t ret;
245 
246     ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
247     if (ret != ATRET_SUCCESS) {
248         LOGC("Failed to read nativetoken.json to buffer, ret=%d.", ret);
249         return ret;
250     }
251     if (fileBuff == NULL) {
252         return ATRET_SUCCESS;
253     }
254     record = cJSON_Parse(fileBuff);
255     free(fileBuff);
256     fileBuff = NULL;
257 
258     ret = GetTokenList(record);
259     cJSON_Delete(record);
260 
261     return ret;
262 }
263 
ClearOrCreateCfgFile(void)264 static uint32_t ClearOrCreateCfgFile(void)
265 {
266     int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
267     if (fd < 0) {
268         LOGC("Failed to open file, errno=%d.", errno);
269         return CLEAR_CREATE_FILE_FAILED;
270     }
271     fdsan_exchange_owner_tag(fd, 0, g_nativeFdTag);
272 
273 #ifdef WITH_SELINUX
274     Restorecon(TOKEN_ID_CFG_FILE_PATH);
275 #endif // WITH_SELINUX
276 
277     (void)fdsan_close_with_tag(fd, g_nativeFdTag);
278     fd = -1;
279 
280     struct stat buf;
281     if (stat(TOKEN_ID_CFG_DIR_PATH, &buf) != 0) {
282         LOGC("Failed to stat file, errno=%d.", errno);
283         return CLEAR_CREATE_FILE_FAILED;
284     }
285     if (chown(TOKEN_ID_CFG_FILE_PATH, buf.st_uid, buf.st_gid) != 0) {
286         LOGC("Failed to chown file, errno=%d.", errno);
287         return CLEAR_CREATE_FILE_FAILED;
288     }
289 
290     return ATRET_SUCCESS;
291 }
292 
AtlibInit(void)293 uint32_t AtlibInit(void)
294 {
295     g_tokenListHead = (NativeTokenList *)malloc(sizeof(NativeTokenList));
296     if (g_tokenListHead == NULL) {
297         LOGC("Faile to alloc memory for g_tokenListHead.");
298         return MALLOC_FAILED;
299     }
300     g_tokenListHead->next = NULL;
301     int32_t isClearOrCreate = 0;
302 
303     uint32_t ret = ParseTokenInfo();
304     if (ret != ATRET_SUCCESS) {
305         ReportNativeTokenExceptionEvent(NATIVE_TOKEN_INIT, (int32_t)ret, GetThreadErrorMsg());
306         ClearThreadErrorMsg();
307         if (g_tokenListHead->next != NULL) {
308             FreeTokenList();
309         }
310         ret = ClearOrCreateCfgFile();
311         if (ret != ATRET_SUCCESS) {
312             LOGC("Failed to ClearOrCreateCfgFile.");
313             free(g_tokenListHead);
314             g_tokenListHead = NULL;
315             return ret;
316         }
317         isClearOrCreate = 1;
318     }
319 
320     if (g_tokenListHead->next == NULL) {
321         if (isClearOrCreate == 0) {
322             ret = ClearOrCreateCfgFile();
323             if (ret != ATRET_SUCCESS) {
324                 LOGC("Failed to ClearOrCreateCfgFile.");
325                 free(g_tokenListHead);
326                 g_tokenListHead = NULL;
327                 return ret;
328             }
329         }
330     }
331     g_isNativeTokenInited = 1;
332 
333     return ATRET_SUCCESS;
334 }
335 
GetRandomTokenId(uint32_t * randNum)336 static uint32_t GetRandomTokenId(uint32_t *randNum)
337 {
338     uint32_t random;
339     ssize_t len;
340     int32_t fd = open("/dev/urandom", O_RDONLY);
341     if (fd < 0) {
342         LOGC("Failed to open urandom, errno=%d.", errno);
343         return ATRET_FAILED;
344     }
345     fdsan_exchange_owner_tag(fd, 0, g_nativeFdTag);
346     len = read(fd, &random, sizeof(random));
347     (void)fdsan_close_with_tag(fd, g_nativeFdTag);
348 
349     if (len != sizeof(random)) {
350         LOGC("Faild to read, len(%" PRIdPTR "", len);
351         return ATRET_FAILED;
352     }
353     *randNum = random;
354     return ATRET_SUCCESS;
355 }
356 
IsTokenUniqueIdExist(uint32_t tokenUniqueId)357 static int32_t IsTokenUniqueIdExist(uint32_t tokenUniqueId)
358 {
359     NativeTokenList *tokenNode = g_tokenListHead->next;
360     while (tokenNode != NULL) {
361         AtInnerInfo *existToken = (AtInnerInfo *)&(tokenNode->tokenId);
362         if (tokenUniqueId == existToken->tokenUniqueId) {
363             return 1;
364         }
365         tokenNode = tokenNode->next;
366     }
367     return 0;
368 }
369 
CreateNativeTokenId(const char * processName)370 static NativeAtId CreateNativeTokenId(const char *processName)
371 {
372     uint32_t rand;
373     NativeAtId tokenId;
374     AtInnerInfo *innerId = (AtInnerInfo *)(&tokenId);
375     int32_t retry = MAX_RETRY_TIMES;
376 
377     while (retry > 0) {
378         if (GetRandomTokenId(&rand) != ATRET_SUCCESS) {
379             LOGC("Failed to GetRandomTokenId.");
380             return INVALID_TOKEN_ID;
381         }
382         if (IsTokenUniqueIdExist(rand & (TOKEN_RANDOM_MASK)) == 0) {
383             break;
384         }
385         retry--;
386     }
387     if (retry == 0) {
388         LOGC("Failed to get unique tokenId.");
389         return INVALID_TOKEN_ID;
390     }
391 
392     innerId->reserved = 0;
393     innerId->tokenUniqueId = rand & (TOKEN_RANDOM_MASK);
394     innerId->version = 1;
395 
396     if (strcmp(processName, HDC_PROCESS_NAME) == 0) {
397         innerId->type = TOKEN_SHELL_TYPE;
398     } else {
399         innerId->type = TOKEN_NATIVE_TYPE;
400     }
401 
402     return tokenId;
403 }
404 
GetAplLevel(const char * aplStr)405 static int32_t GetAplLevel(const char *aplStr)
406 {
407     if (aplStr == NULL) {
408         return 0;
409     }
410     if (strcmp(aplStr, "system_core") == 0) {
411         return SYSTEM_CORE; // system_core means apl level is 3
412     }
413     if (strcmp(aplStr, "system_basic") == 0) {
414         return SYSTEM_BASIC; // system_basic means apl level is 2
415     }
416     if (strcmp(aplStr, "normal") == 0) {
417         return NORMAL;
418     }
419     LOGC("Invalid aplStr(%s).", aplStr);
420     return 0;
421 }
422 
WriteToFile(const cJSON * root)423 static uint32_t WriteToFile(const cJSON *root)
424 {
425     char *jsonStr = NULL;
426     jsonStr = cJSON_PrintUnformatted(root);
427     if (jsonStr == NULL) {
428         LOGC("Failed to cJSON_PrintUnformatted.");
429         return ATRET_FAILED;
430     }
431     uint32_t ret = ATRET_SUCCESS;
432 
433     do {
434         int32_t fd = open(TOKEN_ID_CFG_FILE_PATH, O_RDWR | O_CREAT | O_TRUNC,
435                           S_IRUSR | S_IWUSR | S_IRGRP);
436         if (fd < 0) {
437             LOGC("Failed to open file, errno(%d).", errno);
438             ret = ATRET_FAILED;
439             break;
440         }
441         fdsan_exchange_owner_tag(fd, 0, g_nativeFdTag);
442         size_t strLen = strlen(jsonStr);
443         ssize_t writtenLen = write(fd, (void *)jsonStr, (size_t)strLen);
444         if (fsync(fd) != 0) {
445             LOGE("Failed to fsync, errno=%d.", errno);
446         }
447         (void)fdsan_close_with_tag(fd, g_nativeFdTag);
448         if (writtenLen < 0 || (size_t)writtenLen != strLen) {
449             LOGC("Failed to write, writtenLen=%zu.", writtenLen);
450             ret = ATRET_FAILED;
451             break;
452         }
453     } while (0);
454 
455     cJSON_free(jsonStr);
456     return ret;
457 }
458 
SaveTokenIdToCfg(const NativeTokenList * curr)459 static uint32_t SaveTokenIdToCfg(const NativeTokenList *curr)
460 {
461     char *fileBuff = NULL;
462     cJSON *record = NULL;
463     uint32_t ret;
464 
465     ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuff);
466     if (ret != ATRET_SUCCESS) {
467         LOGC("Failed to GetFileBuff, ret=%d.", ret);
468         return ret;
469     }
470 
471     if (fileBuff == NULL) {
472         record = cJSON_CreateArray();
473     } else {
474         record = cJSON_Parse(fileBuff);
475         free(fileBuff);
476         fileBuff = NULL;
477     }
478 
479     if (record == NULL) {
480         LOGC("Failed to get record.");
481         return SAVE_CONTENT_TO_CFG_FAILED;
482     }
483 
484     cJSON *node = CreateNativeTokenJsonObject(curr);
485     if (node == NULL) {
486         LOGC("Failed to CreateNativeTokenJsonObject.");
487         cJSON_Delete(record);
488         return SAVE_CONTENT_TO_CFG_FAILED;
489     }
490     if (!cJSON_AddItemToArray(record, node)) {
491         LOGC("Failed to cJSON_AddItemToArray.");
492         cJSON_Delete(node);
493         cJSON_Delete(record);
494         return SAVE_CONTENT_TO_CFG_FAILED;
495     }
496 
497     if (WriteToFile(record) != ATRET_SUCCESS) {
498         LOGC("Failed to WriteToFile.");
499         cJSON_Delete(record);
500         return SAVE_CONTENT_TO_CFG_FAILED;
501     }
502     cJSON_Delete(record);
503     return ATRET_SUCCESS;
504 }
505 
CheckStrArray(const char ** strArray,int32_t strNum,int32_t maxNum,uint32_t maxInfoLen)506 static uint32_t CheckStrArray(const char **strArray, int32_t strNum, int32_t maxNum, uint32_t maxInfoLen)
507 {
508     if ((strArray == NULL) && (strNum != 0)) {
509         LOGC("StrArray is null but strNum != 0.");
510         return ATRET_FAILED;
511     }
512     if ((strNum > maxNum) || (strNum < 0)) {
513         LOGC("Invalid strNum(%d).", strNum);
514         return ATRET_FAILED;
515     }
516     for (int32_t i = 0; i < strNum; i++) {
517         if (strArray[i] == NULL) {
518             LOGC("StrArray[%d] is null.", i);
519             return ATRET_FAILED;
520         }
521         size_t len = strlen(strArray[i]);
522         if ((len > maxInfoLen) || (len == 0)) {
523             LOGC("Invalid strArray[%d] length(%zu).", i, len);
524             return ATRET_FAILED;
525         }
526     }
527     return ATRET_SUCCESS;
528 }
529 
CheckProcessName(const char * processName)530 static uint32_t CheckProcessName(const char *processName)
531 {
532     if (processName == NULL) {
533         LOGC("ProcessName is null.");
534         return ATRET_FAILED;
535     }
536 
537     size_t len = strlen(processName);
538     if (len > MAX_PROCESS_NAME_LEN || len == 0) {
539         LOGC("Invalid processName, length(%zu).", len);
540         return ATRET_FAILED;
541     }
542     return ATRET_SUCCESS;
543 }
544 
CheckProcessInfo(NativeTokenInfoParams * tokenInfo,int32_t * aplRet)545 static uint32_t CheckProcessInfo(NativeTokenInfoParams *tokenInfo, int32_t *aplRet)
546 {
547     if (CheckProcessName(tokenInfo->processName) != ATRET_SUCCESS) {
548         LOGC("Invalid processName.");
549         return PROCESS_NAME_INVALID;
550     }
551 
552     uint32_t retDcap = CheckStrArray(tokenInfo->dcaps, tokenInfo->dcapsNum, MAX_DCAPS_NUM, MAX_DCAP_LEN);
553     if (retDcap != ATRET_SUCCESS) {
554         LOGC("Invalid dcaps.");
555         return DCAPS_INVALID;
556     }
557     uint32_t retPerm = CheckStrArray(tokenInfo->perms, tokenInfo->permsNum, MAX_PERM_NUM, MAX_PERM_LEN);
558     if (retPerm != ATRET_SUCCESS) {
559         LOGC("Invalid perms.");
560         return PERMS_INVALID;
561     }
562 
563     uint32_t retAcl = CheckStrArray(tokenInfo->acls, tokenInfo->aclsNum, MAX_PERM_NUM, MAX_PERM_LEN);
564     if (retAcl != ATRET_SUCCESS) {
565         LOGC("Invalid acls.");
566         return ACLS_INVALID;
567     }
568 
569     if (tokenInfo->aclsNum > tokenInfo->permsNum) {
570         LOGC("Invalid aclsNum(%d) or permsNum(%d).", tokenInfo->aclsNum, tokenInfo->permsNum);
571         return ACL_GREATER_THAN_PERMS;
572     }
573     int32_t apl = GetAplLevel(tokenInfo->aplStr);
574     if (apl == 0) {
575         LOGC("Invalid aplStr(%s).", tokenInfo->aplStr);
576         return APL_INVALID;
577     }
578     *aplRet = apl;
579     return ATRET_SUCCESS;
580 }
581 
CreateStrArray(int32_t num,const char ** strArr,char *** strArrRes)582 static uint32_t CreateStrArray(int32_t num, const char **strArr, char ***strArrRes)
583 {
584     if (num > MAX_PERM_NUM) {
585         LOGC("Oversize array, size=%d.", num);
586         return ATRET_FAILED;
587     }
588     if (num == 0) {
589         *strArrRes = NULL;
590         return ATRET_SUCCESS;
591     }
592     *strArrRes = (char **)malloc(num * sizeof(char *));
593     if (*strArrRes == NULL) {
594         LOGC("Failed to alloc memory for strArray.");
595         return ATRET_FAILED;
596     }
597     for (int32_t i = 0; i < num; i++) {
598         size_t length = strlen(strArr[i]);
599         (*strArrRes)[i] = (char *)malloc(sizeof(char) * length + 1);
600         if ((*strArrRes)[i] == NULL ||
601             (strcpy_s((*strArrRes)[i], length + 1, strArr[i]) != EOK)) {
602             LOGC("Failed to copy strArr[%d].", i);
603             FreeStrArray(strArrRes, i);
604             return ATRET_FAILED;
605         }
606         (*strArrRes)[i][length] = '\0';
607     }
608     return ATRET_SUCCESS;
609 }
610 
AddNewTokenToListAndFile(const NativeTokenInfoParams * tokenInfo,int32_t aplIn,NativeAtId * tokenId)611 static uint32_t AddNewTokenToListAndFile(const NativeTokenInfoParams *tokenInfo,
612     int32_t aplIn, NativeAtId *tokenId)
613 {
614     NativeTokenList *tokenNode;
615     NativeAtId id;
616 
617     id = CreateNativeTokenId(tokenInfo->processName);
618     if (id == INVALID_TOKEN_ID) {
619         LOGC("Failed to get new native tokenId.");
620         return CREATE_NATIVETOKEN_ID_FAILED;
621     }
622 
623     tokenNode = (NativeTokenList *)malloc(sizeof(NativeTokenList));
624     if (tokenNode == NULL) {
625         LOGC("Failed to alloc memory for tokenNode.");
626         return MALLOC_FAILED;
627     }
628     tokenNode->tokenId = id;
629     tokenNode->apl = aplIn;
630     if (strcpy_s(tokenNode->processName, MAX_PROCESS_NAME_LEN + 1, tokenInfo->processName) != EOK) {
631         LOGC("Failed to copy process name.");
632         free(tokenNode);
633         return STRCPY_FAILED;
634     }
635     tokenNode->dcapsNum = tokenInfo->dcapsNum;
636     tokenNode->permsNum = tokenInfo->permsNum;
637     tokenNode->aclsNum = tokenInfo->aclsNum;
638 
639     if (CreateStrArray(tokenInfo->dcapsNum, tokenInfo->dcaps, &tokenNode->dcaps) != ATRET_SUCCESS) {
640         LOGC("Failed to CreateStrArray for dcaps.");
641         free(tokenNode);
642         return CREATE_ARRAY_FAILED;
643     }
644     if (CreateStrArray(tokenInfo->permsNum, tokenInfo->perms, &tokenNode->perms) != ATRET_SUCCESS) {
645         LOGC("Failed to CreateStrArray for perms.");
646         FreeStrArray(&tokenNode->dcaps, tokenInfo->dcapsNum - 1);
647         free(tokenNode);
648         return CREATE_ARRAY_FAILED;
649     }
650     if (CreateStrArray(tokenInfo->aclsNum, tokenInfo->acls, &tokenNode->acls) != ATRET_SUCCESS) {
651         LOGC("Failed to CreateStrArray for acls.");
652         FreeStrArray(&tokenNode->dcaps, tokenInfo->dcapsNum - 1);
653         FreeStrArray(&tokenNode->perms, tokenInfo->permsNum - 1);
654         free(tokenNode);
655         return CREATE_ARRAY_FAILED;
656     }
657 
658     tokenNode->next = g_tokenListHead->next;
659     g_tokenListHead->next = tokenNode;
660 
661     *tokenId = id;
662 
663     return SaveTokenIdToCfg(tokenNode);
664 }
665 
CompareTokenInfo(const NativeTokenList * tokenNode,const char ** dcapsIn,int32_t dcapNumIn,int32_t aplIn)666 static int32_t CompareTokenInfo(const NativeTokenList *tokenNode,
667                                 const char **dcapsIn, int32_t dcapNumIn, int32_t aplIn)
668 {
669     if (tokenNode->apl != aplIn) {
670         return 1;
671     }
672     if (tokenNode->dcapsNum != dcapNumIn) {
673         return 1;
674     }
675     for (int32_t i = 0; i < dcapNumIn; i++) {
676         if (strcmp(tokenNode->dcaps[i], dcapsIn[i]) != 0) {
677             return 1;
678         }
679     }
680     return 0;
681 }
682 
ComparePermsInfo(const NativeTokenList * tokenNode,const char ** permsIn,int32_t permsNumIn)683 static int32_t ComparePermsInfo(const NativeTokenList *tokenNode,
684                                 const char **permsIn, int32_t permsNumIn)
685 {
686     if (tokenNode->permsNum != permsNumIn) {
687         return 1;
688     }
689     for (int32_t i = 0; i < permsNumIn; i++) {
690         if (strcmp(tokenNode->perms[i], permsIn[i]) != 0) {
691             return 1;
692         }
693     }
694     return 0;
695 }
696 
UpdateStrArrayInList(char ** strArr[],int32_t * strNum,const char ** strArrNew,int32_t strNumNew)697 static uint32_t UpdateStrArrayInList(char **strArr[], int32_t *strNum,
698     const char **strArrNew, int32_t strNumNew)
699 {
700     if (strNum == NULL) {
701         LOGC("StrNum is null.");
702         return ATRET_FAILED;
703     }
704 
705     FreeStrArray(strArr, *strNum - 1);
706 
707     *strNum = strNumNew;
708 
709     return CreateStrArray(strNumNew, strArrNew, strArr);
710 }
711 
UpdateTokenInfoInList(NativeTokenList * tokenNode,const NativeTokenInfoParams * tokenInfo)712 static uint32_t UpdateTokenInfoInList(NativeTokenList *tokenNode,
713                                       const NativeTokenInfoParams *tokenInfo)
714 {
715     tokenNode->apl = GetAplLevel(tokenInfo->aplStr);
716 
717     uint32_t ret = UpdateStrArrayInList(&tokenNode->dcaps, &(tokenNode->dcapsNum),
718         tokenInfo->dcaps, tokenInfo->dcapsNum);
719     if (ret != ATRET_SUCCESS) {
720         LOGC("Failed to updateStrArray for dcaps.");
721         return CREATE_ARRAY_FAILED;
722     }
723     ret = UpdateStrArrayInList(&tokenNode->perms, &(tokenNode->permsNum),
724         tokenInfo->perms, tokenInfo->permsNum);
725     if (ret != ATRET_SUCCESS) {
726         LOGC("Failed to updateStrArray for perms.");
727         FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
728         return CREATE_ARRAY_FAILED;
729     }
730     ret = UpdateStrArrayInList(&tokenNode->acls, &(tokenNode->aclsNum),
731         tokenInfo->acls, tokenInfo->aclsNum);
732     if (ret != ATRET_SUCCESS) {
733         LOGC("Failed to updateStrArray for acls.");
734         FreeStrArray(&tokenNode->dcaps, tokenNode->dcapsNum - 1);
735         FreeStrArray(&tokenNode->perms, tokenNode->permsNum - 1);
736         return CREATE_ARRAY_FAILED;
737     }
738     return ret;
739 }
740 
UpdateInfoInCfgFile(const NativeTokenList * tokenNode)741 static uint32_t UpdateInfoInCfgFile(const NativeTokenList *tokenNode)
742 {
743     cJSON *record = NULL;
744     char *fileBuffer = NULL;
745     uint32_t ret;
746     ret = GetFileBuff(TOKEN_ID_CFG_FILE_PATH, &fileBuffer);
747     if (ret != ATRET_SUCCESS) {
748         LOGC("Failed to GetFileBuff, ret=%d.", ret);
749         return ret;
750     }
751 
752     if (fileBuffer == NULL) {
753         record = cJSON_CreateArray();
754     } else {
755         record = cJSON_Parse(fileBuffer);
756         free(fileBuffer);
757         fileBuffer = NULL;
758     }
759 
760     if (record == NULL) {
761         LOGC("Failed to get record.");
762         return SAVE_CONTENT_TO_CFG_FAILED;
763     }
764 
765     ret = UpdateGoalItemFromRecord(tokenNode, record);
766     if (ret != ATRET_SUCCESS) {
767         LOGC("Failed to UpdateGoalItemFromRecord.");
768         cJSON_Delete(record);
769         return SAVE_CONTENT_TO_CFG_FAILED;
770     }
771 
772     if (WriteToFile(record) != ATRET_SUCCESS) {
773         LOGC("Failed to WriteToFile.");
774         cJSON_Delete(record);
775         return SAVE_CONTENT_TO_CFG_FAILED;
776     }
777     cJSON_Delete(record);
778     return ATRET_SUCCESS;
779 }
780 
781 
LockNativeTokenFile(int32_t * lockFileFd)782 static uint32_t LockNativeTokenFile(int32_t *lockFileFd)
783 {
784     int32_t fd = open(TOKEN_ID_CFG_FILE_LOCK_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP);
785     if (fd < 0) {
786         LOGC("Failed to open native token file, errno=%d.", errno);
787         return LOCK_FILE_FAILED;
788     }
789     fdsan_exchange_owner_tag(fd, 0, g_nativeFdTag);
790 #ifdef WITH_SELINUX
791     Restorecon(TOKEN_ID_CFG_FILE_LOCK_PATH);
792 #endif // WITH_SELINUX
793     struct flock lock;
794     lock.l_type = F_WRLCK;
795     lock.l_whence = SEEK_SET;
796     lock.l_start = 0;
797     lock.l_len = 0; // lock entire file
798     int32_t ret = -1;
799     for (int i = 0; i < MAX_RETRY_LOCK_TIMES; i++) {
800         ret = fcntl(fd, F_SETLK, &lock);
801         if (ret == -1) {
802             LOGE("Failed to lock the file, try %d time, errno is %d.", i, errno);
803             usleep(SLEEP_TIME);
804         } else {
805             break;
806         }
807     }
808     if (ret == -1) {
809         LOGC("Failed to lock the file, errno=%d.", errno);
810         (void)fdsan_close_with_tag(fd, g_nativeFdTag);
811         return LOCK_FILE_FAILED;
812     }
813     *lockFileFd = fd;
814     return ATRET_SUCCESS;
815 }
816 
UnlockNativeTokenFile(int32_t lockFileFd)817 static void UnlockNativeTokenFile(int32_t lockFileFd)
818 {
819     if (lockFileFd < 0) {
820         LOGE("Invalid fd.");
821         return;
822     }
823     struct flock lock;
824     lock.l_type = F_UNLCK;
825     lock.l_whence = SEEK_SET;
826     lock.l_start = 0;
827     lock.l_len = 0;
828 
829     if (fcntl(lockFileFd, F_SETLK, &lock) == -1) {
830         LOGE("Failed to unlock file, errno=%d.", errno);
831     }
832     (void)fdsan_close_with_tag(lockFileFd, g_nativeFdTag);
833 }
834 
UpdateNewTokenToListAndFile(NativeTokenInfoParams * tokenInfo,NativeTokenList * tokenNode,int32_t apl)835 static uint32_t UpdateNewTokenToListAndFile(NativeTokenInfoParams *tokenInfo, NativeTokenList *tokenNode, int32_t apl)
836 {
837     uint32_t ret = ATRET_SUCCESS;
838     int32_t needTokenUpdate = CompareTokenInfo(tokenNode, tokenInfo->dcaps, tokenInfo->dcapsNum, apl);
839     int32_t needPermUpdate = ComparePermsInfo(tokenNode, tokenInfo->perms, tokenInfo->permsNum);
840     if ((needTokenUpdate != 0) || (needPermUpdate != 0)) {
841         ret = UpdateTokenInfoInList(tokenNode, tokenInfo);
842         if (ret != ATRET_SUCCESS) {
843             LOGC("Failed to UpdateTokenInfoInList, ret=%u.", ret);
844             RemoveNodeFromList(&tokenNode);
845             ReportNativeTokenExceptionEvent(UPDATE_NODE, (int32_t)ret, GetThreadErrorMsg());
846             return ret;
847         }
848         ret = UpdateInfoInCfgFile(tokenNode);
849         if (ret != ATRET_SUCCESS) {
850             LOGC("Failed to UpdateInfoInCfgFile, ret=%u.", ret);
851         }
852     }
853     return ret;
854 }
855 
GetAccessTokenId(NativeTokenInfoParams * tokenInfo)856 uint64_t GetAccessTokenId(NativeTokenInfoParams *tokenInfo)
857 {
858     NativeAtId tokenId = 0;
859     uint64_t result = 0;
860     int32_t apl;
861     NativeAtIdEx *atPoint = (NativeAtIdEx *)(&result);
862     int32_t fd = -1;
863     int32_t sceneCode = -1;
864     uint32_t ret = ATRET_SUCCESS;
865     ClearThreadErrorMsg();
866     do {
867         ret = LockNativeTokenFile(&fd);
868         sceneCode = NATIVE_TOKEN_INIT;
869         BREAK_IF_TRUE(ret != ATRET_SUCCESS);
870 
871         if (g_isNativeTokenInited == 0) {
872             ret = AtlibInit();
873             sceneCode = NATIVE_TOKEN_INIT;
874             BREAK_IF_TRUE(ret != ATRET_SUCCESS);
875         }
876         ret = CheckProcessInfo(tokenInfo, &apl);
877         sceneCode = CHECK_PROCESS_INFO;
878         BREAK_IF_TRUE(ret != ATRET_SUCCESS);
879 
880         NativeTokenList *tokenNode = g_tokenListHead->next;
881         while (tokenNode != NULL) {
882             if (strcmp(tokenNode->processName, tokenInfo->processName) == 0) {
883                 tokenId = tokenNode->tokenId;
884                 break;
885             }
886             tokenNode = tokenNode->next;
887         }
888 
889         if (tokenNode == NULL) {
890             ret = AddNewTokenToListAndFile(tokenInfo, apl, &tokenId);
891             sceneCode = ADD_NODE;
892             BREAK_IF_TRUE(ret != ATRET_SUCCESS);
893         } else {
894             ret = UpdateNewTokenToListAndFile(tokenInfo, tokenNode, apl);
895             sceneCode = UPDATE_NODE;
896             BREAK_IF_TRUE(ret != ATRET_SUCCESS);
897         }
898     } while (0);
899     UnlockNativeTokenFile(fd);
900     if (ret != ATRET_SUCCESS) {
901         ReportNativeTokenExceptionEvent(sceneCode, (int32_t)ret, GetThreadErrorMsg());
902         return INVALID_TOKEN_ID;
903     }
904     atPoint->tokenId = tokenId;
905     atPoint->tokenAttr = 0;
906     return result;
907 }
908 
909