• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 Huawei Technologies Co., Ltd.
3  * Licensed under the Mulan PSL v2.
4  * You can use this software according to the terms and conditions of the Mulan PSL v2.
5  * You may obtain a copy of Mulan PSL v2 at:
6  *     http://license.coscl.org.cn/MulanPSL2
7  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8  * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9  * PURPOSE.
10  * See the Mulan PSL v2 for more details.
11  */
12 
13 #include "fs_work_agent.h"
14 #include <dirent.h>
15 #include <fcntl.h>
16 #include <limits.h>
17 #include <mntent.h>
18 #include <securec.h>
19 #include <sys/ioctl.h>
20 #include <sys/resource.h>
21 #include <sys/stat.h>
22 #include <sys/statfs.h>
23 #include <sys/types.h>
24 #include <time.h>
25 #include "tc_ns_client.h"
26 #include "tee_agent.h"
27 #include "tee_log.h"
28 
29 #ifdef LOG_TAG
30 #undef LOG_TAG
31 #endif
32 #define LOG_TAG       "teecd_agent"
33 #define USER_PATH_LEN 10
34 
35 /* record the current g_userId and g_storageId */
36 static uint32_t g_userId;
37 static uint32_t g_storageId;
SetCurrentUserId(uint32_t id)38 static void SetCurrentUserId(uint32_t id)
39 {
40     g_userId = id;
41 }
GetCurrentUserId(void)42 static uint32_t GetCurrentUserId(void)
43 {
44     return g_userId;
45 }
46 
SetCurrentStorageId(uint32_t id)47 static void SetCurrentStorageId(uint32_t id)
48 {
49     g_storageId = id;
50 }
GetCurrentStorageId(void)51 static uint32_t GetCurrentStorageId(void)
52 {
53     return g_storageId;
54 }
55 
56 /* open file list head */
57 static struct OpenedFile *g_firstFile = NULL;
58 
59 /* add to tail */
AddOpenFile(FILE * pFile)60 static int32_t AddOpenFile(FILE *pFile)
61 {
62     struct OpenedFile *newFile = malloc(sizeof(struct OpenedFile));
63     if (newFile == NULL) {
64         tloge("malloc OpenedFile failed\n");
65         return -1;
66     }
67     newFile->file = pFile;
68 
69     if (g_firstFile == NULL) {
70         g_firstFile   = newFile;
71         newFile->next = newFile;
72         newFile->prev = newFile;
73     } else {
74         if (g_firstFile->prev == NULL) {
75             tloge("the tail is null\n");
76             free(newFile);
77             return -1;
78         }
79         g_firstFile->prev->next = newFile;
80         newFile->prev           = g_firstFile->prev;
81         newFile->next           = g_firstFile;
82         g_firstFile->prev       = newFile;
83     }
84     return 0;
85 }
86 
DelOpenFile(struct OpenedFile * file)87 static void DelOpenFile(struct OpenedFile *file)
88 {
89     struct OpenedFile *next = NULL;
90 
91     if (file == NULL) {
92         return;
93     }
94     next = file->next;
95 
96     if (file == next) { /* only 1 node */
97         g_firstFile = NULL;
98     } else {
99         if (file->next == NULL || file->prev == NULL) {
100             tloge("the next or the prev is null\n");
101             return;
102         }
103         if (file == g_firstFile) {
104             g_firstFile = file->next;
105         }
106         next->prev       = file->prev;
107         file->prev->next = next;
108     }
109 }
110 
FindOpenFile(int32_t fd,struct OpenedFile ** file)111 static int32_t FindOpenFile(int32_t fd, struct OpenedFile **file)
112 {
113     struct OpenedFile *p = g_firstFile;
114     int32_t findFlag     = 0;
115 
116     if (p == NULL) {
117         return findFlag;
118     }
119 
120     do {
121         if (p->file != NULL) {
122             if (fileno(p->file) == fd) {
123                 findFlag = 1;
124                 break;
125             }
126         }
127         p = p->next;
128     } while (p != g_firstFile && p != NULL);
129 
130     if (findFlag == 0) {
131         p = NULL;
132     }
133     if (file != NULL) {
134         *file = p;
135     }
136     return findFlag;
137 }
138 
139 /*
140  * path: file or dir to change own
141  * is_file: 0(dir);1(file)
142  */
ChownSecStorage(const char * path,bool is_file)143 static void ChownSecStorage(const char *path, bool is_file)
144 {
145     if (path == NULL) {
146         return;
147     }
148     /* create dirs with 700 mode, create files with 600 mode */
149     int32_t ret;
150     if (is_file) {
151         ret = chmod(path, S_IRUSR | S_IWUSR);
152     } else {
153         ret = chmod(path, S_IRUSR | S_IWUSR | S_IXUSR);
154     }
155     if (ret < 0) {
156         tloge("chmod failed: %d\n", errno);
157     }
158 }
159 
CheckPathLen(const char * path,size_t pathLen)160 static int32_t CheckPathLen(const char *path, size_t pathLen)
161 {
162     uint32_t i = 0;
163 
164     while (i < pathLen && path[i] != '\0') {
165         i++;
166     }
167     if (i >= pathLen) {
168         tloge("path is too long\n");
169         return -1;
170     }
171     return 0;
172 }
173 
174 /*
175  * path:file path name.
176  * e.g. sec_storage_data/app1/sub1/fileA.txt
177  * then CreateDir will make dir sec_storage_data, app1 and sub1.
178  */
CreateDir(const char * path,size_t pathLen)179 static int32_t CreateDir(const char *path, size_t pathLen)
180 {
181     int32_t ret;
182 
183     ret = CheckPathLen(path, pathLen);
184     if (ret != 0) {
185         return -1;
186     }
187 
188     char *pathTemp = strdup(path);
189     char *position  = pathTemp;
190 
191     if (pathTemp == NULL) {
192         tloge("strdup error\n");
193         return -1;
194     }
195 
196     if (strncmp(pathTemp, "/", strlen("/")) == 0) {
197         position++;
198     } else if (strncmp(pathTemp, "./", strlen("./")) == 0) {
199         position += strlen("./");
200     }
201 
202     for (; *position != '\0'; ++position) {
203         if (*position == '/') {
204             *position = '\0';
205 
206             if (access(pathTemp, F_OK) == 0) {
207                 *position = '/';
208                 continue;
209             }
210 
211             if (mkdir(pathTemp, ROOT_DIR_PERM) != 0) {
212                 tloge("mkdir fail err %d \n", errno);
213                 free(pathTemp);
214                 return -1;
215             }
216 
217             ChownSecStorage(pathTemp, false);
218             *position = '/';
219         }
220     }
221 
222     free(pathTemp);
223     return 0;
224 }
225 
CheckFileNameAndPath(const char * name,const char * path)226 static int32_t CheckFileNameAndPath(const char *name, const char *path)
227 {
228     if (name == NULL || path == NULL) {
229         return -1;
230     }
231 
232     if (strstr(name, FILE_NAME_INVALID_STR) != NULL) {
233         tloge("Invalid file name\n");
234         return -1;
235     }
236 
237     return 0;
238 }
239 
GetPathStorage(char * path,size_t pathLen,const char * env)240 static int32_t GetPathStorage(char *path, size_t pathLen, const char *env)
241 {
242     errno_t rc;
243     char *defaultPath = NULL;
244 
245     if (strncmp(env, "SFS_PARTITION_TRANSIENT", strlen("SFS_PARTITION_TRANSIENT")) == 0) {
246         defaultPath = USER_DATA_DIR;
247     } else if (strncmp(env, "SFS_PARTITION_PERSISTENT", strlen("SFS_PARTITION_PERSISTENT")) == 0) {
248         defaultPath = ROOT_DIR;
249     } else {
250         return -1;
251     }
252 
253     rc = strncpy_s(path, pathLen, defaultPath, strlen(defaultPath) + 1);
254     if (rc != EOK) {
255         tloge("strncpy_s failed %d\n", rc);
256         return -1;
257     }
258     return 0;
259 }
260 
GetTransientDir(char * path,size_t pathLen)261 static int32_t GetTransientDir(char* path, size_t pathLen)
262 {
263     return GetPathStorage(path, pathLen, "SFS_PARTITION_TRANSIENT");
264 }
265 
GetPersistentDir(char * path,size_t pathLen)266 static int32_t GetPersistentDir(char* path, size_t pathLen)
267 {
268     return GetPathStorage(path, pathLen, "SFS_PARTITION_PERSISTENT");
269 }
270 
271 #define USER_PATH_SIZE 10
JoinFileNameTransient(const char * name,char * path,size_t pathLen)272 static int32_t JoinFileNameTransient(const char *name, char *path, size_t pathLen)
273 {
274     errno_t rc;
275     int32_t ret;
276     uint32_t userId = GetCurrentUserId();
277 
278     ret = GetTransientDir(path, pathLen);
279     if (ret != 0) {
280         return ret;
281     }
282 
283     if (userId != 0) {
284         char userPath[USER_PATH_SIZE] = { 0 };
285         rc = snprintf_s(userPath, sizeof(userPath), sizeof(userPath) - 1, "%u/", userId);
286         if (rc == -1) {
287             tloge("snprintf_s failed %d\n", rc);
288             return -1;
289         }
290 
291         rc = strncat_s(path, pathLen, SFS_PARTITION_USER_SYMLINK, strlen(SFS_PARTITION_USER_SYMLINK));
292         if (rc != EOK) {
293             tloge("strncat_s failed %d\n", rc);
294             return -1;
295         }
296 
297         rc = strncat_s(path, pathLen, userPath, strlen(userPath));
298         if (rc != EOK) {
299             tloge("strncat_s failed %d\n", rc);
300             return -1;
301         }
302 
303         if (strlen(name) <= strlen(SFS_PARTITION_TRANSIENT)) {
304             tloge("name length is too small\n");
305             return -1;
306         }
307         rc = strncat_s(path, pathLen, name + strlen(SFS_PARTITION_TRANSIENT),
308                        (strlen(name) - strlen(SFS_PARTITION_TRANSIENT)));
309         if (rc != EOK) {
310             tloge("strncat_s failed %d\n", rc);
311             return -1;
312         }
313     } else {
314         rc = strncat_s(path, pathLen, name, strlen(name));
315         if (rc != EOK) {
316             tloge("strncat_s failed %d\n", rc);
317             return -1;
318         }
319     }
320 
321     return 0;
322 }
323 
GetDefaultDir(char * path,size_t pathLen)324 static int32_t GetDefaultDir(char *path, size_t pathLen)
325 {
326     errno_t rc;
327     int32_t ret;
328 
329     ret = GetPersistentDir(path, pathLen);
330     if (ret != 0) {
331         return ret;
332     }
333 
334     rc = strncat_s(path, pathLen, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT));
335     if (rc != EOK) {
336         tloge("strncat_s failed %d\n", rc);
337         return -1;
338     }
339     return 0;
340 }
341 
DoJoinFileName(const char * name,char * path,size_t pathLen)342 static int32_t DoJoinFileName(const char *name, char *path, size_t pathLen)
343 {
344     errno_t rc;
345     int32_t ret;
346 
347     if (name == strstr(name, SFS_PARTITION_TRANSIENT_PERSO) || name == strstr(name, SFS_PARTITION_TRANSIENT_PRIVATE)) {
348         ret = GetTransientDir(path, pathLen);
349     } else if (name == strstr(name, SFS_PARTITION_PERSISTENT)) {
350         ret = GetPersistentDir(path, pathLen);
351     } else {
352         ret = GetDefaultDir(path, pathLen);
353     }
354 
355     if (ret != 0) {
356         tloge("get dir failed %d\n", ret);
357         return -1;
358     }
359 
360     rc = strncat_s(path, pathLen, name, strlen(name));
361     if (rc != EOK) {
362         tloge("strncat_s failed %d\n", rc);
363         return -1;
364     }
365 
366     return 0;
367 }
368 
JoinFileNameForStorageCE(const char * name,char * path,size_t pathLen)369 static int32_t JoinFileNameForStorageCE(const char *name, char *path, size_t pathLen)
370 {
371     errno_t rc;
372     char temp[FILE_NAME_MAX_BUF] = { '\0' };
373     char *nameTemp               = temp;
374     char *nameWithoutUserId      = NULL;
375     char *idString               = NULL;
376 
377     rc = memcpy_s(nameTemp, FILE_NAME_MAX_BUF, name, strlen(name));
378     if (rc != EOK) {
379         tloge("copy failed");
380         return -1;
381     }
382 
383     idString = strtok_r(nameTemp, "/", &nameWithoutUserId);
384     if (idString == NULL) {
385         tloge("the name %s does not match th rule as userid/xxx\n", name);
386         return -1;
387     }
388 
389     rc = strncpy_s(path, pathLen, SEC_STORAGE_DATA_CE, sizeof(SEC_STORAGE_DATA_CE));
390     if (rc != EOK) {
391         tloge("strncpy_s failed %d\n", rc);
392         return -1;
393     }
394 
395     rc = strncat_s(path, pathLen, idString, strlen(idString));
396     if (rc != EOK) {
397         tloge("strncat_s failed %d\n", rc);
398         return -1;
399     }
400 
401     rc = strncat_s(path, pathLen, SEC_STORAGE_DATA_CE_SUFFIX_DIR, sizeof(SEC_STORAGE_DATA_CE_SUFFIX_DIR));
402     if (rc != EOK) {
403         tloge("strncat_s failed %d\n", rc);
404         return -1;
405     }
406 
407     rc = strncat_s(path, pathLen, nameWithoutUserId, strlen(nameWithoutUserId));
408     if (rc != EOK) {
409         tloge("strncat_s failed %d\n", rc);
410         return -1;
411     }
412 
413     return 0;
414 }
415 
JoinFileName(const char * name,char * path,size_t pathLen)416 static int32_t JoinFileName(const char *name, char *path, size_t pathLen)
417 {
418     int32_t ret = -1;
419     uint32_t storageId = GetCurrentStorageId();
420 
421     if (CheckFileNameAndPath(name, path) != 0) {
422         return ret;
423     }
424 
425     if (storageId == TEE_OBJECT_STORAGE_CE) {
426         ret = JoinFileNameForStorageCE(name, path, pathLen);
427     } else {
428         /*
429         * If the path name does not start with sec_storage or sec_storage_data,
430         * add sec_storage str for the path
431         */
432         if (name == strstr(name, SFS_PARTITION_TRANSIENT)) {
433             ret = JoinFileNameTransient(name, path, pathLen);
434         } else {
435             ret = DoJoinFileName(name, path, pathLen);
436         }
437     }
438 
439     tlogv("joined path done\n");
440     return ret;
441 }
442 
IsDataDir(const char * path,bool isUsers)443 static bool IsDataDir(const char *path, bool isUsers)
444 {
445     char secDataDir[FILE_NAME_MAX_BUF] = { 0 };
446     int32_t ret;
447     errno_t rc;
448 
449     ret = GetTransientDir(secDataDir, FILE_NAME_MAX_BUF);
450     if (ret != 0)
451         return false;
452     if (isUsers) {
453         rc = strncat_s(secDataDir, FILE_NAME_MAX_BUF, SFS_PARTITION_USER_SYMLINK, strlen(SFS_PARTITION_USER_SYMLINK));
454     } else {
455         rc = strncat_s(secDataDir, FILE_NAME_MAX_BUF, SFS_PARTITION_TRANSIENT, strlen(SFS_PARTITION_TRANSIENT));
456     }
457     if (rc != EOK)
458         return false;
459     if (path == strstr(path, secDataDir))
460         return true;
461     return false;
462 }
463 
IsRootDir(const char * path)464 static bool IsRootDir(const char *path)
465 {
466     char secRootDir[FILE_NAME_MAX_BUF] = { 0 };
467     int32_t ret;
468     errno_t rc;
469 
470     ret = GetPersistentDir(secRootDir, FILE_NAME_MAX_BUF);
471     if (ret != 0)
472         return false;
473     rc = strncat_s(secRootDir, FILE_NAME_MAX_BUF, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT));
474     if (rc != EOK)
475         return false;
476     if (path == strstr(path, secRootDir))
477         return true;
478     return false;
479 }
480 
IsValidFilePath(const char * path)481 static bool IsValidFilePath(const char *path)
482 {
483     if (IsDataDir(path, false) || IsDataDir(path, true) || IsRootDir(path) ||
484         (path == strstr(path, SEC_STORAGE_DATA_CE))) {
485         return true;
486     }
487     tloge("path is invalid\n");
488     return false;
489 }
490 
GetRealFilePath(const char * originPath,char * trustPath,size_t tPathLen)491 static uint32_t GetRealFilePath(const char *originPath, char *trustPath, size_t tPathLen)
492 {
493     char *retPath = realpath(originPath, trustPath);
494     if (retPath == NULL) {
495         /* the file may be not exist, will create after */
496         if ((errno != ENOENT) && (errno != EACCES)) {
497             tloge("get realpath failed: %d\n", errno);
498             return (uint32_t)errno;
499         }
500         /* check origin path */
501         if (!IsValidFilePath(originPath)) {
502             tloge("origin path is invalid\n");
503             return ENFILE;
504         }
505         errno_t rc = strncpy_s(trustPath, tPathLen, originPath, strlen(originPath));
506         if (rc != EOK) {
507             tloge("strncpy_s failed %d\n", rc);
508             return EPERM;
509         }
510     } else {
511         /* check real path */
512         if (!IsValidFilePath(trustPath)) {
513             tloge("path is invalid\n");
514             return ENFILE;
515         }
516     }
517     return 0;
518 }
519 
520 static int32_t UnlinkRecursive(const char *name);
UnlinkRecursiveDir(const char * name)521 static int32_t UnlinkRecursiveDir(const char *name)
522 {
523     bool fail         = false;
524     char dn[PATH_MAX] = { 0 };
525     errno_t rc;
526 
527     /* a directory, so open handle */
528     DIR *dir = opendir(name);
529     if (dir == NULL) {
530         tloge("dir open failed\n");
531         return -1;
532     }
533 
534     /* recurse over components */
535     errno = 0;
536 
537     struct dirent *de = readdir(dir);
538 
539     while (de != NULL) {
540         if (strncmp(de->d_name, "..", sizeof("..")) == 0 || strncmp(de->d_name, ".", sizeof(".")) == 0) {
541             de = readdir(dir);
542             continue;
543         }
544         rc = snprintf_s(dn, sizeof(dn), sizeof(dn) - 1, "%s/%s", name, de->d_name);
545         if (rc == -1) {
546             tloge("snprintf_s failed %d\n", rc);
547             fail = true;
548             break;
549         }
550 
551         if (UnlinkRecursive(dn) < 0) {
552             tloge("loop UnlinkRecursive() failed, there are read-only file\n");
553             fail = true;
554             break;
555         }
556         errno = 0;
557         de    = readdir(dir);
558     }
559 
560     /* in case readdir or UnlinkRecursive failed */
561     if (fail || errno < 0) {
562         int32_t save = errno;
563         closedir(dir);
564         errno = save;
565         tloge("fail is %d, errno is %d\n", fail, errno);
566         return -1;
567     }
568 
569     /* close directory handle */
570     if (closedir(dir) < 0) {
571         tloge("closedir failed, errno is %d\n", errno);
572         return -1;
573     }
574 
575     /* delete target directory */
576     if (rmdir(name) < 0) {
577         tloge("rmdir failed, errno is %d\n", errno);
578         return -1;
579     }
580     return 0;
581 }
582 
UnlinkRecursive(const char * name)583 static int32_t UnlinkRecursive(const char *name)
584 {
585     struct stat st;
586 
587     /* is it a file or directory? */
588     if (lstat(name, &st) < 0) {
589         tloge("lstat failed, errno is %x\n", errno);
590         return -1;
591     }
592 
593     /* a file, so unlink it */
594     if (!S_ISDIR(st.st_mode)) {
595         if (unlink(name) < 0) {
596             tloge("unlink failed, errno is %d\n", errno);
597             return -1;
598         }
599         return 0;
600     }
601 
602     return UnlinkRecursiveDir(name);
603 }
604 
IsFileExist(const char * name)605 static int32_t IsFileExist(const char *name)
606 {
607     struct stat statbuf;
608 
609     if (name == NULL) {
610         return 0;
611     }
612     if (stat(name, &statbuf) != 0) {
613         if (errno == ENOENT) { /* file not exist */
614             tloge("file stat failed\n");
615             return 0;
616         }
617         return 1;
618     }
619 
620     return 1;
621 }
622 
DoOpenFile(const char * path,struct SecStorageType * transControl)623 static uint32_t DoOpenFile(const char *path, struct SecStorageType *transControl)
624 {
625     char trustPath[PATH_MAX] = { 0 };
626 
627     uint32_t rRet = GetRealFilePath(path, trustPath, sizeof(trustPath));
628     if (rRet != 0) {
629         tloge("get real path failed. err=%u\n", rRet);
630         return rRet;
631     }
632 
633     FILE *pFile = fopen(trustPath, transControl->args.open.mode);
634     if (pFile == NULL) {
635         tloge("open file with flag %s failed: %d\n", transControl->args.open.mode, errno);
636         return (uint32_t)errno;
637     }
638     ChownSecStorage(trustPath, true);
639     int32_t ret = AddOpenFile(pFile);
640     if (ret != 0) {
641         tloge("add OpenedFile failed\n");
642         (void)fclose(pFile);
643         return ENOMEM;
644     }
645     transControl->ret = fileno(pFile); /* return fileno */
646     return 0;
647 }
648 
CheckPartitionReady(const char * mntDir)649 static int32_t CheckPartitionReady(const char *mntDir)
650 {
651     struct mntent *mentry = NULL;
652     int32_t findFlag      = -1;
653 
654     FILE *fp = setmntent("/proc/mounts", "r");
655     if (fp == NULL) {
656         tloge("Failed to open /proc/mounts.\n");
657         return -1;
658     }
659     mentry = getmntent(fp);
660     while (mentry != NULL) {
661         if (mentry->mnt_dir != NULL) {
662             if (strlen(mentry->mnt_dir) == strlen(mntDir) &&
663                 strncmp(mentry->mnt_dir, mntDir, strlen(mntDir)) == 0) {
664                 findFlag = 1;
665                 break;
666             }
667         }
668         mentry = getmntent(fp);
669     }
670     endmntent(fp);
671     return findFlag;
672 }
673 
OpenWork(struct SecStorageType * transControl)674 static void OpenWork(struct SecStorageType *transControl)
675 {
676     uint32_t error;
677     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
678 
679     SetCurrentUserId(transControl->userId);
680     SetCurrentStorageId(transControl->storageId);
681 
682     tlogv("sec storage : open\n");
683 
684     if (JoinFileName((char *)(transControl->args.open.name), nameBuff, sizeof(nameBuff)) != 0) {
685         transControl->ret = -1;
686         return;
687     }
688 
689     if (strstr((char *)nameBuff, SFS_PARTITION_PERSISTENT) != NULL) {
690         if (CheckPartitionReady("/sec_storage") <= 0) {
691             tloge("check /sec_storage partition_ready failed ----------->\n");
692             transControl->ret = -1;
693             return;
694         }
695     }
696 
697     if (transControl->cmd == SEC_CREATE) {
698         /* create an exist file, remove it at first */
699         errno_t rc = strncpy_s(transControl->args.open.mode,
700             sizeof(transControl->args.open.mode), "w+", sizeof("w+"));
701         if (rc != EOK) {
702             tloge("strncpy_s failed %d\n", rc);
703             error = ENOENT;
704             goto ERROR;
705         }
706     } else {
707         if (IsFileExist(nameBuff) == 0) {
708             /* open a nonexist file, return fail */
709             tloge("file is not exist, open failed\n");
710             error = ENOENT;
711             goto ERROR;
712         }
713     }
714 
715     /* mkdir -p for new create files */
716     if (CreateDir(nameBuff, sizeof(nameBuff)) != 0) {
717         error = (uint32_t)errno;
718         goto ERROR;
719     }
720 
721     error = DoOpenFile(nameBuff, transControl);
722     if (error != 0) {
723         goto ERROR;
724     }
725 
726     return;
727 
728 ERROR:
729     transControl->ret   = -1;
730     transControl->error = error;
731     return;
732 }
733 
CloseWork(struct SecStorageType * transControl)734 static void CloseWork(struct SecStorageType *transControl)
735 {
736     struct OpenedFile *selFile = NULL;
737 
738     tlogv("sec storage : close\n");
739 
740     if (FindOpenFile(transControl->args.close.fd, &selFile) != 0) {
741         int32_t ret = fclose(selFile->file);
742         if (ret == 0) {
743             tlogv("close file %d success\n", transControl->args.close.fd);
744             DelOpenFile(selFile);
745             free(selFile);
746             selFile = NULL;
747             (void)selFile;
748         } else {
749             tloge("close file %d failed: %d\n", transControl->args.close.fd, errno);
750             transControl->error = (uint32_t)errno;
751         }
752         transControl->ret = ret;
753     } else {
754         tloge("can't find opened file(fileno = %d)\n", transControl->args.close.fd);
755         transControl->ret   = -1;
756         transControl->error = EBADF;
757     }
758 }
759 
ReadWork(struct SecStorageType * transControl)760 static void ReadWork(struct SecStorageType *transControl)
761 {
762     struct OpenedFile *selFile = NULL;
763 
764     tlogv("sec storage : read count = %u\n", transControl->args.read.count);
765 
766     if (FindOpenFile(transControl->args.read.fd, &selFile) != 0) {
767         size_t count = fread((void *)(transControl->args.read.buffer), 1, transControl->args.read.count, selFile->file);
768         transControl->ret = (int32_t)count;
769 
770         if (count < transControl->args.read.count) {
771             if (feof(selFile->file)) {
772                 transControl->ret2 = 0;
773                 tlogv("read end of file\n");
774             } else {
775                 transControl->ret2  = -1;
776                 transControl->error = (uint32_t)errno;
777                 tloge("read file failed: %d\n", errno);
778             }
779         } else {
780             transControl->ret2 = 0;
781             tlogv("read file success, content len=%zu\n", count);
782         }
783     } else {
784         transControl->ret   = 0;
785         transControl->ret2  = -1;
786         transControl->error = EBADF;
787         tloge("can't find opened file(fileno = %d)\n", transControl->args.read.fd);
788     }
789 }
790 
WriteWork(struct SecStorageType * transControl)791 static void WriteWork(struct SecStorageType *transControl)
792 {
793     struct OpenedFile *selFile = NULL;
794 
795     tlogv("sec storage : write count = %u\n", transControl->args.write.count);
796 
797     if (FindOpenFile(transControl->args.write.fd, &selFile) != 0) {
798         size_t count = fwrite((void *)(transControl->args.write.buffer), 1,
799                               transControl->args.write.count, selFile->file);
800         if (count < transControl->args.write.count) {
801             tloge("write file failed: %d\n", errno);
802             transControl->ret   = (int32_t)count;
803             transControl->error = (uint32_t)errno;
804             return;
805         }
806 
807         if (transControl->ret2 == SEC_WRITE_SSA) {
808             if (fflush(selFile->file) != 0) {
809                 tloge("fflush file failed: %d\n", errno);
810                 transControl->ret   = 0;
811                 transControl->error = (uint32_t)errno;
812             } else {
813                 transControl->ret = (int32_t)count;
814             }
815         } else {
816             transControl->ret   = (int32_t)count;
817             transControl->error = 0;
818         }
819     } else {
820         tloge("can't find opened file(fileno = %d)\n", transControl->args.write.fd);
821         transControl->ret   = 0;
822         transControl->error = EBADF;
823     }
824 }
825 
SeekWork(struct SecStorageType * transControl)826 static void SeekWork(struct SecStorageType *transControl)
827 {
828     struct OpenedFile *selFile = NULL;
829 
830     tlogv("sec storage : seek offset=%d, whence=%u\n", transControl->args.seek.offset, transControl->args.seek.whence);
831 
832     if (FindOpenFile(transControl->args.seek.fd, &selFile) != 0) {
833         int32_t ret = fseek(selFile->file, transControl->args.seek.offset, (int32_t)transControl->args.seek.whence);
834         if (ret) {
835             tloge("seek file failed: %d\n", errno);
836             transControl->error = (uint32_t)errno;
837         } else {
838             tlogv("seek file success\n");
839         }
840         transControl->ret = ret;
841     } else {
842         tloge("can't find opened file(fileno = %d)\n", transControl->args.seek.fd);
843         transControl->ret   = -1;
844         transControl->error = EBADF;
845     }
846 }
847 
RemoveWork(struct SecStorageType * transControl)848 static void RemoveWork(struct SecStorageType *transControl)
849 {
850     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
851 
852     tlogv("sec storage : remove\n");
853 
854     SetCurrentUserId(transControl->userId);
855     SetCurrentStorageId(transControl->storageId);
856 
857     if (JoinFileName((char *)(transControl->args.remove.name), nameBuff, sizeof(nameBuff)) == 0) {
858         int32_t ret = UnlinkRecursive(nameBuff);
859         if (ret != 0) {
860             tloge("remove file failed: %d\n", errno);
861             transControl->error = (uint32_t)errno;
862         } else {
863             tlogv("remove file success\n");
864         }
865         transControl->ret = ret;
866     } else {
867         transControl->ret = -1;
868     }
869 }
870 
TruncateWork(struct SecStorageType * transControl)871 static void TruncateWork(struct SecStorageType *transControl)
872 {
873     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
874 
875     tlogv("sec storage : truncate, len=%u\n", transControl->args.truncate.len);
876 
877     SetCurrentUserId(transControl->userId);
878     SetCurrentStorageId(transControl->storageId);
879 
880     if (JoinFileName((char *)(transControl->args.truncate.name), nameBuff, sizeof(nameBuff)) == 0) {
881         int32_t ret = truncate(nameBuff, (long)transControl->args.truncate.len);
882         if (ret != 0) {
883             tloge("truncate file failed: %d\n", errno);
884             transControl->error = (uint32_t)errno;
885         } else {
886             tlogv("truncate file success\n");
887         }
888         transControl->ret = ret;
889     } else {
890         transControl->ret = -1;
891     }
892 }
893 
RenameWork(struct SecStorageType * transControl)894 static void RenameWork(struct SecStorageType *transControl)
895 {
896     char nameBuff[FILE_NAME_MAX_BUF]  = { 0 };
897     char nameBuff2[FILE_NAME_MAX_BUF] = { 0 };
898 
899     SetCurrentUserId(transControl->userId);
900     SetCurrentStorageId(transControl->storageId);
901 
902     int32_t joinRet1 = JoinFileName((char *)(transControl->args.rename.buffer), nameBuff, sizeof(nameBuff));
903     int32_t joinRet2 = JoinFileName((char *)(transControl->args.rename.buffer) + transControl->args.rename.oldNameLen,
904                                     nameBuff2, sizeof(nameBuff2));
905     if (joinRet1 == 0 && joinRet2 == 0) {
906         int32_t ret = rename(nameBuff, nameBuff2);
907         if (ret != 0) {
908             tloge("rename file failed: %d\n", errno);
909             transControl->error = (uint32_t)errno;
910         } else {
911             tlogv("rename file success\n");
912         }
913         transControl->ret = ret;
914     } else {
915         transControl->ret = -1;
916     }
917 }
918 
919 #define MAXBSIZE 65536
920 
DoCopy(int32_t fromFd,int32_t toFd)921 static int32_t DoCopy(int32_t fromFd, int32_t toFd)
922 {
923     int32_t ret;
924     ssize_t rcount;
925     ssize_t wcount;
926 
927     char *buf = (char *)malloc(MAXBSIZE * sizeof(char));
928     if (buf == NULL) {
929         tloge("malloc buf failed\n");
930         return -1;
931     }
932 
933     rcount = read(fromFd, buf, MAXBSIZE);
934     while (rcount > 0) {
935         wcount = write(toFd, buf, (size_t)rcount);
936         if (rcount != wcount || wcount == -1) {
937             tloge("write file failed: %d\n", errno);
938             ret = -1;
939             goto OUT;
940         }
941         rcount = read(fromFd, buf, MAXBSIZE);
942     }
943 
944     if (rcount < 0) {
945         tloge("read file failed: %d\n", errno);
946         ret = -1;
947         goto OUT;
948     }
949 
950     /* fsync memory from kernel to disk */
951     ret = fsync(toFd);
952     if (ret != 0) {
953         tloge("CopyFile:fsync file failed: %d\n", errno);
954         goto OUT;
955     }
956 
957 OUT:
958     free(buf);
959     return ret;
960 }
961 
CopyFile(const char * fromPath,const char * toPath)962 static int32_t CopyFile(const char *fromPath, const char *toPath)
963 {
964     struct stat fromStat;
965     char realFromPath[PATH_MAX] = { 0 };
966     char realToPath[PATH_MAX]   = { 0 };
967 
968     uint32_t rRet = GetRealFilePath(fromPath, realFromPath, sizeof(realFromPath));
969     if (rRet != 0) {
970         tloge("get real from path failed. err=%u\n", rRet);
971         return -1;
972     }
973 
974     rRet = GetRealFilePath(toPath, realToPath, sizeof(realToPath));
975     if (rRet != 0) {
976         tloge("get real to path failed. err=%u\n", rRet);
977         return -1;
978     }
979 
980     int32_t fromFd = open(realFromPath, O_RDONLY, 0);
981     if (fromFd == -1) {
982         tloge("open file failed: %d\n", errno);
983         return -1;
984     }
985 
986     int32_t ret = fstat(fromFd, &fromStat);
987     if (ret == -1) {
988         tloge("stat file failed: %d\n", errno);
989         close(fromFd);
990         return ret;
991     }
992 
993     int32_t toFd = open(realToPath, O_WRONLY | O_TRUNC | O_CREAT, fromStat.st_mode);
994     if (toFd == -1) {
995         tloge("stat file failed: %d\n", errno);
996         close(fromFd);
997         return -1;
998     }
999 
1000     ret = DoCopy(fromFd, toFd);
1001     if (ret != 0) {
1002         tloge("do copy failed\n");
1003     } else {
1004         ChownSecStorage((char *)realToPath, true);
1005     }
1006 
1007     close(fromFd);
1008     close(toFd);
1009     return ret;
1010 }
1011 
CopyWork(struct SecStorageType * transControl)1012 static void CopyWork(struct SecStorageType *transControl)
1013 {
1014     char fromPath[FILE_NAME_MAX_BUF] = { 0 };
1015     char toPath[FILE_NAME_MAX_BUF]   = { 0 };
1016 
1017     SetCurrentUserId(transControl->userId);
1018     SetCurrentStorageId(transControl->storageId);
1019 
1020     int32_t joinRet1 = JoinFileName((char *)(transControl->args.cp.buffer), fromPath, sizeof(fromPath));
1021     int32_t joinRet2 = JoinFileName((char *)(transControl->args.cp.buffer) + transControl->args.cp.fromPathLen, toPath,
1022                                     sizeof(toPath));
1023     if (joinRet1 == 0 && joinRet2 == 0) {
1024         int32_t ret = CopyFile(fromPath, toPath);
1025         if (ret != 0) {
1026             tloge("copy file failed: %d\n", errno);
1027             transControl->error = (uint32_t)errno;
1028         } else {
1029             tlogv("copy file success\n");
1030         }
1031         transControl->ret = ret;
1032     } else {
1033         transControl->ret = -1;
1034     }
1035 }
1036 
FileInfoWork(struct SecStorageType * transControl)1037 static void FileInfoWork(struct SecStorageType *transControl)
1038 {
1039     struct OpenedFile *selFile = NULL;
1040     struct stat statBuff;
1041 
1042     tlogv("sec storage : file info\n");
1043 
1044     transControl->args.info.fileLen = transControl->args.info.curPos = 0;
1045 
1046     if (FindOpenFile(transControl->args.info.fd, &selFile) != 0) {
1047         int32_t ret = fstat(transControl->args.info.fd, &statBuff);
1048         if (ret == 0) {
1049             transControl->args.info.fileLen = (uint32_t)statBuff.st_size;
1050             transControl->args.info.curPos  = (uint32_t)ftell(selFile->file);
1051         } else {
1052             tloge("fstat file failed: %d\n", errno);
1053             transControl->error = (uint32_t)errno;
1054         }
1055         transControl->ret = ret;
1056     } else {
1057         transControl->ret   = -1;
1058         transControl->error = EBADF;
1059     }
1060 }
1061 
FileAccessWork(struct SecStorageType * transControl)1062 static void FileAccessWork(struct SecStorageType *transControl)
1063 {
1064     int32_t ret;
1065 
1066     tlogv("sec storage : file access\n");
1067 
1068     if (transControl->cmd == SEC_ACCESS) {
1069         char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1070         SetCurrentUserId(transControl->userId);
1071         SetCurrentStorageId(transControl->storageId);
1072 
1073         if (JoinFileName((char *)(transControl->args.access.name), nameBuff, sizeof(nameBuff)) == 0) {
1074             ret = access(nameBuff, transControl->args.access.mode);
1075             if (ret < 0) {
1076                 tloge("access file mode %d failed: %d\n", transControl->args.access.mode, errno);
1077             }
1078             transControl->ret   = ret;
1079             transControl->error = (uint32_t)errno;
1080         } else {
1081             transControl->ret = -1;
1082         }
1083     } else {
1084         ret = access((char *)(transControl->args.access.name), transControl->args.access.mode);
1085         if (ret < 0) {
1086             tloge("access2 file mode %d failed: %d\n", transControl->args.access.mode, errno);
1087         }
1088         transControl->ret   = ret;
1089         transControl->error = (uint32_t)errno;
1090     }
1091 }
1092 
FsyncWork(struct SecStorageType * transControl)1093 static void FsyncWork(struct SecStorageType *transControl)
1094 {
1095     struct OpenedFile *selFile = NULL;
1096 
1097     tlogv("sec storage : file fsync\n");
1098 
1099     /* opened file */
1100     if (transControl->args.fsync.fd != 0 && FindOpenFile(transControl->args.fsync.fd, &selFile) != 0) {
1101         /* first,flush memory from user to kernel */
1102         int32_t ret = fflush(selFile->file);
1103         if (ret != 0) {
1104             tloge("fsync:fflush file failed: %d\n", errno);
1105             transControl->ret   = -1;
1106             transControl->error = (uint32_t)errno;
1107             return;
1108         }
1109 
1110         /* second,fsync memory from kernel to disk */
1111         int32_t fd  = fileno(selFile->file);
1112         ret = fsync(fd);
1113         if (ret != 0) {
1114             tloge("fsync:fsync file failed: %d\n", errno);
1115             transControl->ret   = -1;
1116             transControl->error = (uint32_t)errno;
1117             return;
1118         }
1119 
1120         transControl->ret = 0;
1121         tlogv("fsync file %d success\n", transControl->args.fsync.fd);
1122     } else {
1123         tloge("can't find opened file(fileno = %d)\n", transControl->args.fsync.fd);
1124         transControl->ret   = -1;
1125         transControl->error = EBADF;
1126     }
1127 }
1128 
1129 #define KBYTE 1024
DiskUsageWork(struct SecStorageType * transControl)1130 static void DiskUsageWork(struct SecStorageType *transControl)
1131 {
1132     struct statfs st;
1133     uint32_t dataRemain;
1134     uint32_t secStorageRemain;
1135     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1136 
1137     tlogv("sec storage : disk usage\n");
1138     if (GetTransientDir(nameBuff, FILE_NAME_MAX_BUF) != 0)
1139         goto ERROR;
1140     if (statfs((const char*)nameBuff, &st) < 0) {
1141         tloge("statfs /secStorageData failed, err=%d\n", errno);
1142         goto ERROR;
1143     }
1144     dataRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1145 
1146     if (GetPersistentDir(nameBuff, FILE_NAME_MAX_BUF) != 0) {
1147         tloge("get persistent dir error\n");
1148         goto ERROR;
1149     }
1150     if (strncat_s(nameBuff, FILE_NAME_MAX_BUF, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT)) != EOK) {
1151         tloge("strncat_s error\n");
1152         goto ERROR;
1153     }
1154     if (statfs((const char*)nameBuff, &st) < 0) {
1155         tloge("statfs /secStorage failed, err=%d\n", errno);
1156         goto ERROR;
1157     }
1158     secStorageRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1159 
1160     transControl->ret                       = 0;
1161     transControl->args.diskUsage.data       = dataRemain;
1162     transControl->args.diskUsage.secStorage = secStorageRemain;
1163     return;
1164 
1165 ERROR:
1166     transControl->ret   = -1;
1167     transControl->error = (uint32_t)errno;
1168 }
1169 
DeleteAllWork(struct SecStorageType * transControl)1170 static void DeleteAllWork(struct SecStorageType *transControl)
1171 {
1172     int32_t ret;
1173     char path[FILE_NAME_MAX_BUF] = { 0 };
1174     char *pathIn                 = (char *)(transControl->args.deleteAll.path);
1175     SetCurrentUserId(transControl->userId);
1176 
1177     tlogv("sec storage : delete path, userid:%d\n", transControl->userId);
1178 
1179     ret = DoJoinFileName(pathIn, path, sizeof(path));
1180     if (ret != EOK) {
1181         tloge("join name failed %d\n", ret);
1182         transControl->ret = -1;
1183         return;
1184     }
1185 
1186     tlogv("sec storage : joint delete path\n");
1187 
1188     ret = UnlinkRecursive(path);
1189     if (ret != 0) {
1190         tloge("delete file failed: %d\n", errno);
1191         transControl->error = (uint32_t)errno;
1192     } else {
1193         tloge("delete file success\n");
1194     }
1195     transControl->ret = ret;
1196 }
1197 
1198 typedef void (*FsWorkFunc)(struct SecStorageType *transControl);
1199 
1200 struct FsWorkTbl {
1201     enum FsCmdType cmd;
1202     FsWorkFunc fn;
1203 };
1204 
1205 static const struct FsWorkTbl g_fsWorkTbl[] = {
1206     { SEC_OPEN, OpenWork },           { SEC_CLOSE, CloseWork },
1207     { SEC_READ, ReadWork },           { SEC_WRITE, WriteWork },
1208     { SEC_SEEK, SeekWork },           { SEC_REMOVE, RemoveWork },
1209     { SEC_TRUNCATE, TruncateWork },   { SEC_RENAME, RenameWork },
1210     { SEC_CREATE, OpenWork },         { SEC_INFO, FileInfoWork },
1211     { SEC_ACCESS, FileAccessWork },   { SEC_ACCESS2, FileAccessWork },
1212     { SEC_FSYNC, FsyncWork },         { SEC_CP, CopyWork },
1213     { SEC_DISKUSAGE, DiskUsageWork }, { SEC_DELETE_ALL, DeleteAllWork },
1214 };
1215 
FsWorkThread(void * control)1216 void *FsWorkThread(void *control)
1217 {
1218     struct SecStorageType *transControl = NULL;
1219     int32_t fsFd;
1220 
1221     if (control == NULL) {
1222         return NULL;
1223     }
1224     transControl = control;
1225 
1226     fsFd = GetFsFd();
1227     if (fsFd == -1) {
1228         tloge("fs is not open\n");
1229         return NULL;
1230     }
1231 
1232     transControl->magic = AGENT_FS_ID;
1233     while (1) {
1234         tlogv("++ fs agent loop ++\n");
1235         int32_t ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_WAIT_EVENT, AGENT_FS_ID);
1236         if (ret != 0) {
1237             tloge("fs agent  wait event failed, errno = %d\n", errno);
1238             break;
1239         }
1240 
1241         tlogv("fs agent wake up and working!!\n");
1242 
1243         if ((transControl->cmd < SEC_MAX) && (g_fsWorkTbl[transControl->cmd].fn != NULL)) {
1244             g_fsWorkTbl[transControl->cmd].fn(transControl);
1245         } else {
1246             tloge("fs agent error cmd:transControl->cmd=%x\n", transControl->cmd);
1247         }
1248 
1249         __asm__ volatile("isb");
1250         __asm__ volatile("dsb sy");
1251 
1252         transControl->magic = AGENT_FS_ID;
1253 
1254         __asm__ volatile("isb");
1255         __asm__ volatile("dsb sy");
1256 
1257         ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, AGENT_FS_ID);
1258         if (ret != 0) {
1259             tloge("fs agent send reponse failed\n");
1260             break;
1261         }
1262         tlogv("-- fs agent loop --\n");
1263     }
1264 
1265     return NULL;
1266 }
1267 
SetFileNumLimit(void)1268 void SetFileNumLimit(void)
1269 {
1270     struct rlimit rlim, rlimNew;
1271 
1272     int32_t rRet = getrlimit(RLIMIT_NOFILE, &rlim);
1273     if (rRet == 0) {
1274         rlimNew.rlim_cur = rlimNew.rlim_max = FILE_NUM_LIMIT_MAX;
1275         if (setrlimit(RLIMIT_NOFILE, &rlimNew) != 0) {
1276             rlimNew.rlim_cur = rlimNew.rlim_max = rlim.rlim_max;
1277             (void)setrlimit(RLIMIT_NOFILE, &rlimNew);
1278         }
1279     } else {
1280         tloge("getrlimit error is 0x%x, errno is %x", rRet, errno);
1281     }
1282 }
1283