• 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 <sys/vfs.h>
25 #include <time.h>
26 #include "tc_ns_client.h"
27 #include "tee_agent.h"
28 #include "tee_log.h"
29 #include "tee_file.h"
30 #ifdef LOG_TAG
31 #undef LOG_TAG
32 #endif
33 #define LOG_TAG       "teecd_agent"
34 #define USER_PATH_LEN 10
35 
36 #define USEC_PER_SEC    1000000ULL
37 #define USEC_PER_MSEC   1000ULL
38 #define NSEC_PER_USEC   1000ULL
39 #define FSCMD_TIMEOUT_US (1 * USEC_PER_SEC)
40 
41 static int32_t CopyFile(const char *fromPath, const char *toPath);
42 
43 /* record the current g_userId and g_storageId */
44 static uint32_t g_userId;
45 static uint32_t g_storageId;
SetCurrentUserId(uint32_t id)46 static void SetCurrentUserId(uint32_t id)
47 {
48     g_userId = id;
49 }
GetCurrentUserId(void)50 static uint32_t GetCurrentUserId(void)
51 {
52     return g_userId;
53 }
54 
SetCurrentStorageId(uint32_t id)55 static void SetCurrentStorageId(uint32_t id)
56 {
57     g_storageId = id;
58 }
GetCurrentStorageId(void)59 static uint32_t GetCurrentStorageId(void)
60 {
61     return g_storageId;
62 }
63 
64 /* open file list head */
65 static struct OpenedFile *g_firstFile = NULL;
66 
67 /* add to tail */
AddOpenFile(FILE * pFile)68 static int32_t AddOpenFile(FILE *pFile)
69 {
70     struct OpenedFile *newFile = malloc(sizeof(struct OpenedFile));
71     if (newFile == NULL) {
72         tloge("malloc OpenedFile failed\n");
73         return -1;
74     }
75     newFile->file = pFile;
76 
77     if (g_firstFile == NULL) {
78         g_firstFile   = newFile;
79         newFile->next = newFile;
80         newFile->prev = newFile;
81     } else {
82         if (g_firstFile->prev == NULL) {
83             tloge("the tail is null\n");
84             free(newFile);
85             return -1;
86         }
87         g_firstFile->prev->next = newFile;
88         newFile->prev           = g_firstFile->prev;
89         newFile->next           = g_firstFile;
90         g_firstFile->prev       = newFile;
91     }
92     return 0;
93 }
94 
DelOpenFile(struct OpenedFile * file)95 static void DelOpenFile(struct OpenedFile *file)
96 {
97     struct OpenedFile *next = NULL;
98 
99     if (file == NULL) {
100         return;
101     }
102     next = file->next;
103 
104     if (file == next) { /* only 1 node */
105         g_firstFile = NULL;
106     } else {
107         if (file->next == NULL || file->prev == NULL) {
108             tloge("the next or the prev is null\n");
109             return;
110         }
111         if (file == g_firstFile) {
112             g_firstFile = file->next;
113         }
114         next->prev       = file->prev;
115         file->prev->next = next;
116     }
117 }
118 
FindOpenFile(int32_t fd,struct OpenedFile ** file)119 static int32_t FindOpenFile(int32_t fd, struct OpenedFile **file)
120 {
121     struct OpenedFile *p = g_firstFile;
122     int32_t findFlag     = 0;
123 
124     if (p == NULL) {
125         return findFlag;
126     }
127 
128     do {
129         if (p->file != NULL) {
130             if (fileno(p->file) == fd) {
131                 findFlag = 1;
132                 break;
133             }
134         }
135         p = p->next;
136     } while (p != g_firstFile && p != NULL);
137 
138     if (findFlag == 0) {
139         p = NULL;
140     }
141     if (file != NULL) {
142         *file = p;
143     }
144     return findFlag;
145 }
146 
147 /*
148  * path: file or dir to change own
149  * is_file: 0(dir);1(file)
150  */
ChownSecStorage(const char * path,bool is_file)151 static void ChownSecStorage(const char *path, bool is_file)
152 {
153     if (path == NULL) {
154         return;
155     }
156     /* create dirs with 700 mode, create files with 600 mode */
157     int32_t ret;
158     if (is_file) {
159         ret = chmod(path, SFS_FILE_PERM);
160     } else {
161         ret = chmod(path, SFS_DIR_PERM);
162     }
163     if (ret < 0) {
164         tloge("chmod failed: %" PUBLIC "d\n", errno);
165     }
166 }
167 
CheckPathLen(const char * path,size_t pathLen)168 static int32_t CheckPathLen(const char *path, size_t pathLen)
169 {
170     uint32_t i = 0;
171 
172     while (i < pathLen && path[i] != '\0') {
173         i++;
174     }
175     if (i >= pathLen) {
176         tloge("path is too long\n");
177         return -1;
178     }
179     return 0;
180 }
181 
182 /*
183  * path:file path name.
184  * e.g. sec_storage_data/app1/sub1/fileA.txt
185  * then CreateDir will make dir sec_storage_data, app1 and sub1.
186  */
CreateDir(const char * path,size_t pathLen)187 static int32_t CreateDir(const char *path, size_t pathLen)
188 {
189     int32_t ret;
190 
191     ret = CheckPathLen(path, pathLen);
192     if (ret != 0) {
193         return -1;
194     }
195 
196     char *pathTemp = strdup(path);
197     char *position  = pathTemp;
198 
199     if (pathTemp == NULL) {
200         tloge("strdup error\n");
201         return -1;
202     }
203 
204     if (strncmp(pathTemp, "/", strlen("/")) == 0) {
205         position++;
206     } else if (strncmp(pathTemp, "./", strlen("./")) == 0) {
207         position += strlen("./");
208     }
209 
210     for (; *position != '\0'; ++position) {
211         if (*position == '/') {
212             *position = '\0';
213 
214             if (access(pathTemp, F_OK) == 0) {
215                 /* Temporary solution to incorrect permission on the sfs
216                  * directory, avoiding factory settings restoration
217                  */
218                 (void)chmod(pathTemp, SFS_DIR_PERM);
219 
220                 *position = '/';
221                 continue;
222             }
223 
224             if (mkdir(pathTemp, SFS_DIR_PERM) != 0) {
225                 tloge("mkdir fail err %" PUBLIC "d \n", errno);
226                 free(pathTemp);
227                 return -1;
228             }
229 
230             *position = '/';
231         }
232     }
233 
234     free(pathTemp);
235     return 0;
236 }
237 
CheckFileNameAndPath(const char * name,const char * path)238 static int32_t CheckFileNameAndPath(const char *name, const char *path)
239 {
240     if (name == NULL || path == NULL) {
241         return -1;
242     }
243 
244     if (strstr(name, FILE_NAME_INVALID_STR) != NULL) {
245         tloge("Invalid file name\n");
246         return -1;
247     }
248 
249     return 0;
250 }
251 
252 #ifdef CONFIG_BACKUP_PARTITION
CheckEnvPath(const char * envPath,char * trustPath,size_t trustPathLen)253 static int32_t CheckEnvPath(const char *envPath, char *trustPath, size_t trustPathLen)
254 {
255     struct stat st;
256 
257     if (strnlen(envPath, PATH_MAX) > trustPathLen) {
258         tloge("too long envPath\n");
259         return -1;
260     }
261     char *retPath = realpath(envPath, trustPath);
262     if (retPath == NULL) {
263         tloge("error envpath, errno is %" PUBLIC "d\n", errno);
264         return errno;
265     }
266 
267     if (stat(trustPath, &st) < 0) {
268         tloge("stat failed, errno is %" PUBLIC "x\n", errno);
269         return -1;
270     }
271     if (!S_ISDIR(st.st_mode)) {
272         tloge("error path: is not a dir\n");
273         return -1;
274     }
275     size_t pathLen = strlen(trustPath);
276     if (pathLen >= trustPathLen - 1) {
277         tloge("too long to add / \n");
278         return -1;
279     }
280     trustPath[pathLen] = '/';
281     trustPath[pathLen + 1] = '\0';
282     return 0;
283 }
284 #endif
285 
GetPathStorage(char * path,size_t pathLen,const char * env)286 static int32_t GetPathStorage(char *path, size_t pathLen, const char *env)
287 {
288     errno_t rc;
289     char *defaultPath = NULL;
290 
291     if (strncmp(env, "SFS_PARTITION_TRANSIENT", strlen("SFS_PARTITION_TRANSIENT")) == 0) {
292         defaultPath = USER_DATA_DIR;
293     } else if (strncmp(env, "SFS_PARTITION_PERSISTENT", strlen("SFS_PARTITION_PERSISTENT")) == 0) {
294         defaultPath = ROOT_DIR;
295     } else {
296         return -1;
297     }
298 
299     rc = strncpy_s(path, pathLen, defaultPath, strlen(defaultPath) + 1);
300     if (rc != EOK) {
301         tloge("strncpy_s failed %" PUBLIC "d\n", rc);
302         return -1;
303     }
304     return 0;
305 }
306 
GetTransientDir(char * path,size_t pathLen)307 static int32_t GetTransientDir(char* path, size_t pathLen)
308 {
309     return GetPathStorage(path, pathLen, "SFS_PARTITION_TRANSIENT");
310 }
311 
GetPersistentDir(char * path,size_t pathLen)312 static int32_t GetPersistentDir(char* path, size_t pathLen)
313 {
314     return GetPathStorage(path, pathLen, "SFS_PARTITION_PERSISTENT");
315 }
316 
317 #define USER_PATH_SIZE 10
JoinFileNameTransient(const char * name,char * path,size_t pathLen)318 static int32_t JoinFileNameTransient(const char *name, char *path, size_t pathLen)
319 {
320     errno_t rc;
321     int32_t ret;
322     uint32_t userId = GetCurrentUserId();
323 
324     ret = GetTransientDir(path, pathLen);
325     if (ret != 0) {
326         return ret;
327     }
328 
329     if (userId != 0) {
330         char userPath[USER_PATH_SIZE] = { 0 };
331         rc = snprintf_s(userPath, sizeof(userPath), sizeof(userPath) - 1, "%u/", userId);
332         if (rc == -1) {
333             tloge("snprintf_s failed %" PUBLIC "d\n", rc);
334             return -1;
335         }
336 
337         rc = strncat_s(path, pathLen, SFS_PARTITION_USER_SYMLINK, strlen(SFS_PARTITION_USER_SYMLINK));
338         if (rc != EOK) {
339             tloge("strncat_s failed %" PUBLIC "d\n", rc);
340             return -1;
341         }
342 
343         rc = strncat_s(path, pathLen, userPath, strlen(userPath));
344         if (rc != EOK) {
345             tloge("strncat_s failed %" PUBLIC "d\n", rc);
346             return -1;
347         }
348 
349         if (strlen(name) <= strlen(SFS_PARTITION_TRANSIENT)) {
350             tloge("name length is too small\n");
351             return -1;
352         }
353         rc = strncat_s(path, pathLen, name + strlen(SFS_PARTITION_TRANSIENT),
354                        (strlen(name) - strlen(SFS_PARTITION_TRANSIENT)));
355         if (rc != EOK) {
356             tloge("strncat_s failed %" PUBLIC "d\n", rc);
357             return -1;
358         }
359     } else {
360         rc = strncat_s(path, pathLen, name, strlen(name));
361         if (rc != EOK) {
362             tloge("strncat_s failed %" PUBLIC "d\n", rc);
363             return -1;
364         }
365     }
366 
367     return 0;
368 }
369 
GetDefaultDir(char * path,size_t pathLen)370 static int32_t GetDefaultDir(char *path, size_t pathLen)
371 {
372     errno_t rc;
373     int32_t ret;
374 
375     ret = GetPersistentDir(path, pathLen);
376     if (ret != 0) {
377         return ret;
378     }
379 
380     rc = strncat_s(path, pathLen, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT));
381     if (rc != EOK) {
382         tloge("strncat_s failed %" PUBLIC "d\n", rc);
383         return -1;
384     }
385     return 0;
386 }
387 
388 #ifdef CONFIG_BACKUP_PARTITION
389 #define BACKUP_PARTITION_ENV             "BACKUP_PARTITION"
GetBackupPath(char * path,size_t pathLen)390 static int GetBackupPath(char *path, size_t pathLen)
391 {
392     const char *envPath = getenv(BACKUP_PARTITION_ENV);
393     if (envPath == NULL) {
394         tloge("databack envPath is NULL.\n");
395         return -1;
396     }
397 
398     return CheckEnvPath(envPath, path, pathLen);
399 }
400 
IsBackupDir(const char * path)401 static bool IsBackupDir(const char *path)
402 {
403     char secBackupDir[FILE_NAME_MAX_BUF] = { 0 };
404     int32_t ret;
405 
406     ret = GetBackupPath(secBackupDir, FILE_NAME_MAX_BUF);
407     if (ret != 0)
408         return false;
409     if (path == strstr(path, secBackupDir))
410         return true;
411     return false;
412 }
413 
DoJoinBackupFileName(const char * name,char * path,size_t pathLen)414 static int32_t DoJoinBackupFileName(const char *name, char *path, size_t pathLen)
415 {
416     int32_t ret;
417     errno_t rc;
418     ret = GetBackupPath(path, pathLen);
419     if (ret != 0)
420         return ret;
421 
422     if (name != strstr(name, SFS_PARTITION_TRANSIENT) && name != strstr(name, SFS_PARTITION_PERSISTENT)) {
423         rc = strncat_s(path, pathLen, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT));
424         if (rc != EOK) {
425             tloge("strncat_s backup file default prefix failed %" PUBLIC "d\n", rc);
426             return -1;
427         }
428     }
429 
430     rc = strncat_s(path, pathLen, name, strlen(name));
431     if (rc != EOK) {
432         tloge("strncat_s backup file name failed %" PUBLIC "d\n", rc);
433         return -1;
434     }
435     return 0;
436 }
437 #endif
438 
DoJoinFileName(const char * name,char * path,size_t pathLen)439 static int32_t DoJoinFileName(const char *name, char *path, size_t pathLen)
440 {
441     errno_t rc;
442     int32_t ret;
443 
444     if (name == strstr(name, SFS_PARTITION_TRANSIENT_PERSO) || name == strstr(name, SFS_PARTITION_TRANSIENT_PRIVATE)) {
445         ret = GetTransientDir(path, pathLen);
446     } else if (name == strstr(name, SFS_PARTITION_PERSISTENT)) {
447         ret = GetPersistentDir(path, pathLen);
448     } else {
449         ret = GetDefaultDir(path, pathLen);
450     }
451 
452     if (ret != 0) {
453         tloge("get dir failed %" PUBLIC "d\n", ret);
454         return -1;
455     }
456 
457     rc = strncat_s(path, pathLen, name, strlen(name));
458     if (rc != EOK) {
459         tloge("strncat_s failed %" PUBLIC "d\n", rc);
460         return -1;
461     }
462 
463     return 0;
464 }
465 
JoinFileNameForStorageCE(const char * name,char * path,size_t pathLen)466 static int32_t JoinFileNameForStorageCE(const char *name, char *path, size_t pathLen)
467 {
468     errno_t rc;
469     char temp[FILE_NAME_MAX_BUF] = { '\0' };
470     char *nameTemp               = temp;
471     char *nameWithoutUserId      = NULL;
472     char *idString               = NULL;
473 
474     rc = memcpy_s(nameTemp, FILE_NAME_MAX_BUF, name, strlen(name));
475     if (rc != EOK) {
476         tloge("copy failed");
477         return -1;
478     }
479 
480     idString = strtok_r(nameTemp, "/", &nameWithoutUserId);
481     if (idString == NULL) {
482         tloge("the name %" PUBLIC "s does not match th rule as userid/xxx\n", name);
483         return -1;
484     }
485 
486     rc = strncpy_s(path, pathLen, SEC_STORAGE_DATA_CE, sizeof(SEC_STORAGE_DATA_CE));
487     if (rc != EOK) {
488         tloge("strncpy_s failed %" PUBLIC "d\n", rc);
489         return -1;
490     }
491 
492     rc = strncat_s(path, pathLen, idString, strlen(idString));
493     if (rc != EOK) {
494         tloge("strncat_s failed %" PUBLIC "d\n", rc);
495         return -1;
496     }
497 
498     rc = strncat_s(path, pathLen, SEC_STORAGE_DATA_CE_SUFFIX_DIR, sizeof(SEC_STORAGE_DATA_CE_SUFFIX_DIR));
499     if (rc != EOK) {
500         tloge("strncat_s failed %" PUBLIC "d\n", rc);
501         return -1;
502     }
503 
504     rc = strncat_s(path, pathLen, nameWithoutUserId, strlen(nameWithoutUserId));
505     if (rc != EOK) {
506         tloge("strncat_s failed %" PUBLIC "d\n", rc);
507         return -1;
508     }
509 
510     return 0;
511 }
512 
JoinFileName(const char * name,bool isBackup,char * path,size_t pathLen)513 static int32_t JoinFileName(const char *name, bool isBackup, char *path, size_t pathLen)
514 {
515     int32_t ret = -1;
516     uint32_t storageId = GetCurrentStorageId();
517 
518     if (CheckFileNameAndPath(name, path) != 0) {
519         return ret;
520     }
521 
522     if (storageId == TEE_OBJECT_STORAGE_CE) {
523         ret = JoinFileNameForStorageCE(name, path, pathLen);
524     } else {
525 #ifdef CONFIG_BACKUP_PARTITION
526         if (isBackup)
527             return DoJoinBackupFileName(name, path, pathLen);
528 #endif
529         /*
530         * If the path name does not start with sec_storage or sec_storage_data,
531         * add sec_storage str for the path
532         */
533         if (name == strstr(name, SFS_PARTITION_TRANSIENT)) {
534             ret = JoinFileNameTransient(name, path, pathLen);
535         } else {
536             ret = DoJoinFileName(name, path, pathLen);
537         }
538     }
539 
540     tlogv("joined path done\n");
541     (void)isBackup;
542     return ret;
543 }
544 
IsDataDir(const char * path,bool isUsers)545 static bool IsDataDir(const char *path, bool isUsers)
546 {
547     char secDataDir[FILE_NAME_MAX_BUF] = { 0 };
548     int32_t ret;
549     errno_t rc;
550 
551     ret = GetTransientDir(secDataDir, FILE_NAME_MAX_BUF);
552     if (ret != 0) {
553         return false;
554     }
555     if (isUsers) {
556         rc = strncat_s(secDataDir, FILE_NAME_MAX_BUF, SFS_PARTITION_USER_SYMLINK, strlen(SFS_PARTITION_USER_SYMLINK));
557     } else {
558         rc = strncat_s(secDataDir, FILE_NAME_MAX_BUF, SFS_PARTITION_TRANSIENT, strlen(SFS_PARTITION_TRANSIENT));
559     }
560     if (rc != EOK) {
561         return false;
562     }
563     if (path == strstr(path, secDataDir)) {
564         return true;
565     }
566     return false;
567 }
568 
IsRootDir(const char * path)569 static bool IsRootDir(const char *path)
570 {
571     char secRootDir[FILE_NAME_MAX_BUF] = { 0 };
572     int32_t ret;
573     errno_t rc;
574 
575     ret = GetPersistentDir(secRootDir, FILE_NAME_MAX_BUF);
576     if (ret != 0) {
577         return false;
578     }
579     rc = strncat_s(secRootDir, FILE_NAME_MAX_BUF, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT));
580     if (rc != EOK) {
581         return false;
582     }
583     if (path == strstr(path, secRootDir)) {
584         return true;
585     }
586 
587     return false;
588 }
589 
IsValidFilePath(const char * path)590 static bool IsValidFilePath(const char *path)
591 {
592     if (IsDataDir(path, false) || IsDataDir(path, true) || IsRootDir(path) ||
593 #ifdef CONFIG_BACKUP_PARTITION
594         IsBackupDir(path) ||
595 #endif
596         (path == strstr(path, SEC_STORAGE_DATA_CE))) {
597         return true;
598     }
599     tloge("path is invalid\n");
600     return false;
601 }
602 
GetRealFilePath(const char * originPath,char * trustPath,size_t tPathLen)603 static uint32_t GetRealFilePath(const char *originPath, char *trustPath, size_t tPathLen)
604 {
605     char *retPath = realpath(originPath, trustPath);
606     if (retPath == NULL) {
607         /* the file may be not exist, will create after */
608         if ((errno != ENOENT) && (errno != EACCES)) {
609             tloge("get realpath failed: %" PUBLIC "d\n", errno);
610             return (uint32_t)errno;
611         }
612         /* check origin path */
613         if (!IsValidFilePath(originPath)) {
614             tloge("origin path is invalid\n");
615             return ENFILE;
616         }
617         errno_t rc = strncpy_s(trustPath, tPathLen, originPath, strlen(originPath));
618         if (rc != EOK) {
619             tloge("strncpy_s failed %" PUBLIC "d\n", rc);
620             return EPERM;
621         }
622     } else {
623         /* check real path */
624         if (!IsValidFilePath(trustPath)) {
625             tloge("path is invalid\n");
626             return ENFILE;
627         }
628     }
629     return 0;
630 }
631 
632 static int32_t UnlinkRecursive(const char *name);
UnlinkRecursiveDir(const char * name)633 static int32_t UnlinkRecursiveDir(const char *name)
634 {
635     bool fail         = false;
636     char dn[PATH_MAX] = { 0 };
637     errno_t rc;
638 
639     /* a directory, so open handle */
640     DIR *dir = opendir(name);
641     if (dir == NULL) {
642         tloge("dir open failed\n");
643         return -1;
644     }
645 
646     /* recurse over components */
647     errno = 0;
648 
649     struct dirent *de = readdir(dir);
650 
651     while (de != NULL) {
652         if (strncmp(de->d_name, "..", sizeof("..")) == 0 || strncmp(de->d_name, ".", sizeof(".")) == 0) {
653             de = readdir(dir);
654             continue;
655         }
656         rc = snprintf_s(dn, sizeof(dn), sizeof(dn) - 1, "%s/%s", name, de->d_name);
657         if (rc == -1) {
658             tloge("snprintf_s failed %" PUBLIC "d\n", rc);
659             fail = true;
660             break;
661         }
662 
663         if (UnlinkRecursive(dn) < 0) {
664             tloge("loop UnlinkRecursive() failed, there are read-only file\n");
665             fail = true;
666             break;
667         }
668         errno = 0;
669         de    = readdir(dir);
670     }
671 
672     /* in case readdir or UnlinkRecursive failed */
673     if (fail || errno < 0) {
674         int32_t save = errno;
675         closedir(dir);
676         errno = save;
677         tloge("fail is %" PUBLIC "d, errno is %" PUBLIC "d\n", fail, errno);
678         return -1;
679     }
680 
681     /* close directory handle */
682     if (closedir(dir) < 0) {
683         tloge("closedir failed, errno is %" PUBLIC "d\n", errno);
684         return -1;
685     }
686 
687     /* delete target directory */
688     if (rmdir(name) < 0) {
689         tloge("rmdir failed, errno is %" PUBLIC "d\n", errno);
690         return -1;
691     }
692     return 0;
693 }
694 
UnlinkRecursive(const char * name)695 static int32_t UnlinkRecursive(const char *name)
696 {
697     struct stat st;
698 
699     /* is it a file or directory? */
700     if (lstat(name, &st) < 0) {
701         tloge("lstat failed, errno is %" PUBLIC "x\n", errno);
702         return -1;
703     }
704 
705     /* a file, so unlink it */
706     if (!S_ISDIR(st.st_mode)) {
707         if (unlink(name) < 0) {
708             tloge("unlink failed, errno is %" PUBLIC "d\n", errno);
709             return -1;
710         }
711         return 0;
712     }
713 
714     return UnlinkRecursiveDir(name);
715 }
716 
IsFileExist(const char * name)717 static int32_t IsFileExist(const char *name)
718 {
719     struct stat statbuf;
720 
721     if (name == NULL) {
722         return 0;
723     }
724     if (stat(name, &statbuf) != 0) {
725         if (errno == ENOENT) { /* file not exist */
726             tloge("file stat failed\n");
727             return 0;
728         }
729         return 1;
730     }
731 
732     return 1;
733 }
734 
735 #ifdef CONFIG_BACKUP_PARTITION
736 #define SFS_BACKUP_FILE_SUFFIX  ".bk"
737 
CopyFromOldFile(const char * name,const char * path,size_t pathLen)738 static int32_t CopyFromOldFile(const char *name, const char *path, size_t pathLen)
739 {
740     char oldNameBuff[FILE_NAME_MAX_BUF] = { 0 };
741     int32_t ret = JoinFileName(name, false, oldNameBuff, sizeof(oldNameBuff));
742     if (ret != 0) {
743         if (ret == ENOENT) {
744             tlogw("main partition file dont exist \n");
745             return 0;
746         }
747         return -1;
748     }
749 
750     if (IsFileExist(oldNameBuff) == 0) {
751         return 0;
752     }
753 
754     tlogd("try copy bk file from main partition to backup partition\n");
755     if (strncmp(path, oldNameBuff, strlen(oldNameBuff) + 1) == 0) {
756         tlogd("name of bk file is the same as main file, needn't copy\n");
757         return 0;
758     }
759 
760     if (CreateDir(path, pathLen) != 0) {
761         return -1;
762     }
763 
764     ret = CopyFile((char *)oldNameBuff, path);
765     if (ret != 0) {
766         tloge("copy file failed: %" PUBLIC "d\n", errno);
767         return -1;
768     }
769 
770     ret = UnlinkRecursive((char *)oldNameBuff);
771     /* if old file delete failed, OpenWork failed */
772     if (ret != 0) {
773         tloge("delete old file failed: %" PUBLIC "d\n", errno);
774         (void)UnlinkRecursive(path);
775         return -1;
776     }
777 
778     return 0;
779 }
780 
DeleteBackupFile(char * nameBuff,size_t nameLen)781 static int32_t DeleteBackupFile(char *nameBuff, size_t nameLen)
782 {
783     char oldNameBuff[FILE_NAME_MAX_BUF] = { 0 };
784     errno_t rc = memcpy_s(oldNameBuff, sizeof(oldNameBuff), nameBuff, nameLen);
785     if (rc != EOK) {
786         tloge("memcpy_s failed %" PUBLIC "d \n", rc);
787         return -1;
788     }
789 
790     rc = strcat_s(oldNameBuff, sizeof(oldNameBuff), SFS_BACKUP_FILE_SUFFIX);
791     if (rc != EOK) {
792         tloge("strcat_s failed %" PUBLIC "d \n", rc);
793         return -1;
794     }
795 
796     if (IsFileExist(oldNameBuff) == 0)
797         return 0;
798 
799     tlogd("try unlink exist backfile in main partition\n");
800     if (unlink((char *)oldNameBuff) < 0) {
801         tloge("unlink failed, errno is %" PUBLIC "d\n", errno);
802         return -1;
803     }
804     return 0;
805 }
806 #endif
807 
DoOpenFile(const char * path,struct SecStorageType * transControl)808 static uint32_t DoOpenFile(const char *path, struct SecStorageType *transControl)
809 {
810     char trustPath[PATH_MAX] = { 0 };
811 
812     uint32_t rRet = GetRealFilePath(path, trustPath, sizeof(trustPath));
813     if (rRet != 0) {
814         tloge("get real path failed. err=%" PUBLIC "u\n", rRet);
815         return rRet;
816     }
817 
818     FILE *pFile = fopen(trustPath, transControl->args.open.mode);
819     if (pFile == NULL) {
820         tloge("open file with flag %" PUBLIC "s failed: %" PUBLIC "d\n", transControl->args.open.mode, errno);
821         return (uint32_t)errno;
822     }
823     ChownSecStorage(trustPath, true);
824     int32_t ret = AddOpenFile(pFile);
825     if (ret != 0) {
826         tloge("add OpenedFile failed\n");
827         (void)fclose(pFile);
828         return ENOMEM;
829     }
830     transControl->ret = fileno(pFile); /* return fileno */
831     return 0;
832 }
833 
834 #ifndef CONFIG_SMART_LOCK_PLATFORM
CheckPartitionReady(const char * mntDir)835 static int32_t CheckPartitionReady(const char *mntDir)
836 {
837     int err;
838     struct statfs rootStat, secStorageStat;
839     err = statfs("/", &rootStat);
840     if (err != 0) {
841         tloge("statfs root fail, errno=%" PUBLIC "d\n", errno);
842         return err;
843     }
844 
845     err = statfs(mntDir, &secStorageStat);
846     if (err != 0) {
847         tloge("statfs mntDir[%" PUBLIC "s] fail, errno=%" PUBLIC "d\n", mntDir, errno);
848         return err;
849     }
850     tlogd("statfs root.f_blocks=%" PUBLIC "llx, mntDir.f_blocks=%" PUBLIC "llx\n",
851         (unsigned long long)(rootStat.f_blocks), (unsigned long long)(secStorageStat.f_blocks));
852 
853     return rootStat.f_blocks != secStorageStat.f_blocks;
854 }
855 #endif
856 
GetTimeStampUs(void)857 static inline uint64_t GetTimeStampUs(void)
858 {
859     struct timespec ts = { 0 };
860     (void)clock_gettime(CLOCK_MONOTONIC, &ts);
861     return ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
862 }
863 
CheckOpenWorkValid(struct SecStorageType * transControl,bool isBackup,char * nameBuff,size_t nameLen)864 static int CheckOpenWorkValid(struct SecStorageType *transControl, bool isBackup, char *nameBuff, size_t nameLen)
865 {
866     int ret = 0;
867     if (transControl->cmd == SEC_CREATE) {
868         /* create a exist file, remove it at first */
869         errno_t rc = strncpy_s(transControl->args.open.mode,
870             sizeof(transControl->args.open.mode), "w+", sizeof("w+"));
871         if (rc != EOK) {
872             tloge("strncpy_s failed %" PUBLIC "d\n", rc);
873             ret = ENOENT;
874         }
875     } else {
876 #ifdef CONFIG_BACKUP_PARTITION
877         if (isBackup && CopyFromOldFile((char *)(transControl->args.open.name), nameBuff, nameLen) != 0) {
878             tloge("failed to copy bk file from main partition to backup partition\n");
879             return ENOENT;
880         }
881 #endif
882 
883         if (IsFileExist(nameBuff) == 0) {
884             /* open a nonexist file, return fail */
885             tloge("file is not exist, open failed\n");
886             ret = ENOENT;
887         }
888     }
889     (void)isBackup;
890     (void)nameLen;
891     return ret;
892 }
893 
OpenWork(struct SecStorageType * transControl)894 static void OpenWork(struct SecStorageType *transControl)
895 {
896     uint32_t error;
897     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
898     bool isBackup = false;
899 
900     SetCurrentUserId(transControl->userId);
901     SetCurrentStorageId(transControl->storageId);
902 
903     tlogw("sec storage: cmd=%" PUBLIC "d, file=%" PUBLIC "s\n",
904         transControl->cmd, (char *)(transControl->args.open.name));
905 
906 #ifdef CONFIG_BACKUP_PARTITION
907     isBackup = transControl->isBackup;
908 #endif
909     if (JoinFileName((char *)(transControl->args.open.name), isBackup, nameBuff, sizeof(nameBuff)) != 0) {
910         transControl->ret = -1;
911         return;
912     }
913 #ifdef CONFIG_BACKUP_PARTITION
914     if (transControl->cmd == SEC_CREATE && DeleteBackupFile(nameBuff, sizeof(nameBuff)) != 0) {
915         tloge("create failed, bk file exist and delete it failed\n");
916         transControl->ret = -1;
917         return;
918     }
919 #endif
920 
921 #ifndef CONFIG_SMART_LOCK_PLATFORM
922     if (strstr((char *)nameBuff, SFS_PARTITION_PERSISTENT) != NULL) {
923         if (CheckPartitionReady("/sec_storage") <= 0) {
924             tloge("check /sec_storage partition_ready failed ----------->\n");
925             transControl->ret = -1;
926             return;
927         }
928     }
929 #endif
930 
931     if (CheckOpenWorkValid(transControl, isBackup, nameBuff, sizeof(nameBuff)) != 0) {
932         error = ENOENT;
933         goto ERROR;
934     }
935 
936     /* mkdir -p for new create files */
937     if (CreateDir(nameBuff, sizeof(nameBuff)) != 0) {
938         error = (uint32_t)errno;
939         goto ERROR;
940     }
941 
942     error = DoOpenFile(nameBuff, transControl);
943     if (error != 0) {
944         goto ERROR;
945     }
946 
947     return;
948 
949 ERROR:
950     transControl->ret   = -1;
951     transControl->error = error;
952     return;
953 }
954 
CloseWork(struct SecStorageType * transControl)955 static void CloseWork(struct SecStorageType *transControl)
956 {
957     struct OpenedFile *selFile = NULL;
958 
959     tlogv("sec storage : close\n");
960 
961     if (FindOpenFile(transControl->args.close.fd, &selFile) != 0) {
962         int32_t ret = fclose(selFile->file);
963         if (ret == 0) {
964             tlogv("close file %" PUBLIC "d success\n", transControl->args.close.fd);
965             DelOpenFile(selFile);
966             free(selFile);
967             selFile = NULL;
968             (void)selFile;
969         } else {
970             tloge("close file %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.close.fd, errno);
971             transControl->error = (uint32_t)errno;
972         }
973         transControl->ret = ret;
974     } else {
975         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.close.fd);
976         transControl->ret   = -1;
977         transControl->error = EBADF;
978     }
979 }
980 
ReadWork(struct SecStorageType * transControl)981 static void ReadWork(struct SecStorageType *transControl)
982 {
983     struct OpenedFile *selFile = NULL;
984 
985     tlogv("sec storage : read count = %" PUBLIC "u\n", transControl->args.read.count);
986 
987     if (FindOpenFile(transControl->args.read.fd, &selFile) != 0) {
988         size_t count = fread((void *)(transControl->args.read.buffer), 1, transControl->args.read.count, selFile->file);
989         transControl->ret = (int32_t)count;
990 
991         if (count < transControl->args.read.count) {
992             if (feof(selFile->file)) {
993                 transControl->ret2 = 0;
994                 tlogv("read end of file\n");
995             } else {
996                 transControl->ret2  = -1;
997                 transControl->error = (uint32_t)errno;
998                 tloge("read file failed: %" PUBLIC "d\n", errno);
999             }
1000         } else {
1001             transControl->ret2 = 0;
1002             tlogv("read file success, content len=%" PUBLIC "zu\n", count);
1003         }
1004     } else {
1005         transControl->ret   = 0;
1006         transControl->ret2  = -1;
1007         transControl->error = EBADF;
1008         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.read.fd);
1009     }
1010 }
1011 
WriteWork(struct SecStorageType * transControl)1012 static void WriteWork(struct SecStorageType *transControl)
1013 {
1014     struct OpenedFile *selFile = NULL;
1015 
1016     tlogv("sec storage : write count = %" PUBLIC "u\n", transControl->args.write.count);
1017 
1018     if (FindOpenFile(transControl->args.write.fd, &selFile) != 0) {
1019         size_t count = fwrite((void *)(transControl->args.write.buffer), 1,
1020                               transControl->args.write.count, selFile->file);
1021         if (count < transControl->args.write.count) {
1022             tloge("write file failed: %" PUBLIC "d\n", errno);
1023             transControl->ret   = (int32_t)count;
1024             transControl->error = (uint32_t)errno;
1025             return;
1026         }
1027 
1028         if (transControl->ret2 == SEC_WRITE_SSA) {
1029             if (fflush(selFile->file) != 0) {
1030                 tloge("fflush file failed: %" PUBLIC "d\n", errno);
1031                 transControl->ret   = 0;
1032                 transControl->error = (uint32_t)errno;
1033             } else {
1034                 transControl->ret = (int32_t)count;
1035             }
1036         } else {
1037             transControl->ret   = (int32_t)count;
1038             transControl->error = 0;
1039         }
1040     } else {
1041         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.write.fd);
1042         transControl->ret   = 0;
1043         transControl->error = EBADF;
1044     }
1045 }
1046 
SeekWork(struct SecStorageType * transControl)1047 static void SeekWork(struct SecStorageType *transControl)
1048 {
1049     struct OpenedFile *selFile = NULL;
1050 
1051     tlogv("sec storage : seek offset=%" PUBLIC "d, whence=%" PUBLIC "u\n",
1052         transControl->args.seek.offset, transControl->args.seek.whence);
1053 
1054     if (FindOpenFile(transControl->args.seek.fd, &selFile) != 0) {
1055         int32_t ret = fseek(selFile->file, transControl->args.seek.offset, (int32_t)transControl->args.seek.whence);
1056         if (ret) {
1057             tloge("seek file failed: %" PUBLIC "d\n", errno);
1058             transControl->error = (uint32_t)errno;
1059         } else {
1060             tlogv("seek file success\n");
1061         }
1062         transControl->ret = ret;
1063     } else {
1064         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.seek.fd);
1065         transControl->ret   = -1;
1066         transControl->error = EBADF;
1067     }
1068 }
1069 
RemoveWork(struct SecStorageType * transControl)1070 static void RemoveWork(struct SecStorageType *transControl)
1071 {
1072     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1073     bool isBackup = false;
1074 
1075     tlogw("sec storage: remove=%" PUBLIC "s\n", (char *)(transControl->args.remove.name));
1076 
1077     SetCurrentUserId(transControl->userId);
1078     SetCurrentStorageId(transControl->storageId);
1079 
1080 #ifdef CONFIG_BACKUP_PARTITION
1081     isBackup = transControl->isBackup;
1082 #endif
1083     if (JoinFileName((char *)(transControl->args.remove.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1084         int32_t ret = UnlinkRecursive(nameBuff);
1085         if (ret != 0) {
1086             tloge("remove file failed: %" PUBLIC "d\n", errno);
1087             transControl->error = (uint32_t)errno;
1088         } else {
1089             tlogv("remove file success\n");
1090         }
1091         transControl->ret = ret;
1092     } else {
1093         transControl->ret = -1;
1094     }
1095 }
1096 
TruncateWork(struct SecStorageType * transControl)1097 static void TruncateWork(struct SecStorageType *transControl)
1098 {
1099     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1100     bool isBackup = false;
1101 
1102     tlogv("sec storage : truncate, len=%" PUBLIC "u\n", transControl->args.truncate.len);
1103 
1104     SetCurrentUserId(transControl->userId);
1105     SetCurrentStorageId(transControl->storageId);
1106 #ifdef CONFIG_BACKUP_PARTITION
1107     isBackup = transControl->isBackup;
1108 #endif
1109     if (JoinFileName((char *)(transControl->args.truncate.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1110         int32_t ret = truncate(nameBuff, (long)transControl->args.truncate.len);
1111         if (ret != 0) {
1112             tloge("truncate file failed: %" PUBLIC "d\n", errno);
1113             transControl->error = (uint32_t)errno;
1114         } else {
1115             tlogv("truncate file success\n");
1116         }
1117         transControl->ret = ret;
1118     } else {
1119         transControl->ret = -1;
1120     }
1121 }
1122 
RenameWork(struct SecStorageType * transControl)1123 static void RenameWork(struct SecStorageType *transControl)
1124 {
1125     char nameBuff[FILE_NAME_MAX_BUF]  = { 0 };
1126     char nameBuff2[FILE_NAME_MAX_BUF] = { 0 };
1127     bool oldIsBackup = false;
1128     bool newIsBackup = false;
1129 
1130     SetCurrentUserId(transControl->userId);
1131     SetCurrentStorageId(transControl->storageId);
1132 
1133     tlogw("sec storage: rename, old=%" PUBLIC "s, new=%" PUBLIC "s\n", (char *)(transControl->args.open.name),
1134         (char *)(transControl->args.rename.buffer) + transControl->args.rename.oldNameLen);
1135 
1136 #ifdef CONFIG_BACKUP_PARTITION
1137     oldIsBackup = transControl->isBackup;
1138     newIsBackup = transControl->isBackupExt;
1139 #endif
1140     int32_t joinRet1 = JoinFileName((char *)(transControl->args.rename.buffer), oldIsBackup, nameBuff,
1141         sizeof(nameBuff));
1142     int32_t joinRet2 = JoinFileName((char *)(transControl->args.rename.buffer) + transControl->args.rename.oldNameLen,
1143                                     newIsBackup, nameBuff2, sizeof(nameBuff2));
1144     if (joinRet1 == 0 && joinRet2 == 0) {
1145         int32_t ret = rename(nameBuff, nameBuff2);
1146         if (ret != 0) {
1147             tloge("rename file failed: %" PUBLIC "d\n", errno);
1148             transControl->error = (uint32_t)errno;
1149         } else {
1150             tlogv("rename file success\n");
1151         }
1152         transControl->ret = ret;
1153     } else {
1154         transControl->ret = -1;
1155     }
1156 }
1157 
1158 #define MAXBSIZE 65536
1159 
DoCopy(int32_t fromFd,int32_t toFd)1160 static int32_t DoCopy(int32_t fromFd, int32_t toFd)
1161 {
1162     int32_t ret;
1163     ssize_t rcount;
1164     ssize_t wcount;
1165 
1166     char *buf = (char *)malloc(MAXBSIZE * sizeof(char));
1167     if (buf == NULL) {
1168         tloge("malloc buf failed\n");
1169         return -1;
1170     }
1171 
1172     rcount = read(fromFd, buf, MAXBSIZE);
1173     while (rcount > 0) {
1174         wcount = write(toFd, buf, (size_t)rcount);
1175         if (rcount != wcount || wcount == -1) {
1176             tloge("write file failed: %" PUBLIC "d\n", errno);
1177             ret = -1;
1178             goto OUT;
1179         }
1180         rcount = read(fromFd, buf, MAXBSIZE);
1181     }
1182 
1183     if (rcount < 0) {
1184         tloge("read file failed: %" PUBLIC "d\n", errno);
1185         ret = -1;
1186         goto OUT;
1187     }
1188 
1189     /* fsync memory from kernel to disk */
1190     ret = fsync(toFd);
1191     if (ret != 0) {
1192         tloge("CopyFile:fsync file failed: %" PUBLIC "d\n", errno);
1193         goto OUT;
1194     }
1195 
1196 OUT:
1197     free(buf);
1198     return ret;
1199 }
1200 
CopyFile(const char * fromPath,const char * toPath)1201 static int32_t CopyFile(const char *fromPath, const char *toPath)
1202 {
1203     struct stat fromStat;
1204     char realFromPath[PATH_MAX] = { 0 };
1205     char realToPath[PATH_MAX]   = { 0 };
1206 
1207     uint32_t rRet = GetRealFilePath(fromPath, realFromPath, sizeof(realFromPath));
1208     if (rRet != 0) {
1209         tloge("get real from path failed. err=%" PUBLIC "u\n", rRet);
1210         return -1;
1211     }
1212 
1213     rRet = GetRealFilePath(toPath, realToPath, sizeof(realToPath));
1214     if (rRet != 0) {
1215         tloge("get real to path failed. err=%" PUBLIC "u\n", rRet);
1216         return -1;
1217     }
1218 
1219     int32_t fromFd = tee_open(realFromPath, O_RDONLY, 0);
1220     if (fromFd == -1) {
1221         tloge("open file failed: %" PUBLIC "d\n", errno);
1222         return -1;
1223     }
1224 
1225     int32_t ret = fstat(fromFd, &fromStat);
1226     if (ret == -1) {
1227         tloge("stat file failed: %" PUBLIC "d\n", errno);
1228         tee_close(&fromFd);
1229         return ret;
1230     }
1231 
1232     int32_t toFd = tee_open(realToPath, O_WRONLY | O_TRUNC | O_CREAT, fromStat.st_mode);
1233     if (toFd == -1) {
1234         tloge("stat file failed: %" PUBLIC "d\n", errno);
1235         tee_close(&fromFd);
1236         return -1;
1237     }
1238 
1239     ret = DoCopy(fromFd, toFd);
1240     if (ret != 0) {
1241         tloge("do copy failed\n");
1242     } else {
1243         ChownSecStorage((char *)realToPath, true);
1244     }
1245 
1246     tee_close(&fromFd);
1247     tee_close(&toFd);
1248     return ret;
1249 }
1250 
CopyWork(struct SecStorageType * transControl)1251 static void CopyWork(struct SecStorageType *transControl)
1252 {
1253     char fromPath[FILE_NAME_MAX_BUF] = { 0 };
1254     char toPath[FILE_NAME_MAX_BUF]   = { 0 };
1255     bool fromIsBackup = false;
1256     bool toIsBackup = false;
1257 
1258     SetCurrentUserId(transControl->userId);
1259     SetCurrentStorageId(transControl->storageId);
1260 
1261 #ifdef CONFIG_BACKUP_PARTITION
1262     fromIsBackup = transControl->isBackup;
1263     toIsBackup   = transControl->isBackupExt;
1264 #endif
1265     int32_t joinRet1 = JoinFileName((char *)(transControl->args.cp.buffer), fromIsBackup, fromPath, sizeof(fromPath));
1266     int32_t joinRet2 = JoinFileName((char *)(transControl->args.cp.buffer) + transControl->args.cp.fromPathLen,
1267         toIsBackup, toPath, sizeof(toPath));
1268     if (joinRet1 == 0 && joinRet2 == 0) {
1269 #ifdef CONFIG_BACKUP_PARTITION
1270         if (IsFileExist(toPath) == 0) {
1271             tlogd("copy_to path not exist, mkdir it.\n");
1272             if (CreateDir(toPath, sizeof(toPath)) != 0) {
1273                 transControl->ret = -1;
1274                 return;
1275             }
1276         }
1277 #endif
1278         int32_t ret = CopyFile(fromPath, toPath);
1279         if (ret != 0) {
1280             tloge("copy file failed: %" PUBLIC "d\n", errno);
1281             transControl->error = (uint32_t)errno;
1282         } else {
1283             tlogv("copy file success\n");
1284         }
1285         transControl->ret = ret;
1286     } else {
1287         transControl->ret = -1;
1288     }
1289 }
1290 
FileInfoWork(struct SecStorageType * transControl)1291 static void FileInfoWork(struct SecStorageType *transControl)
1292 {
1293     struct OpenedFile *selFile = NULL;
1294     struct stat statBuff;
1295 
1296     tlogv("sec storage : file info\n");
1297 
1298     transControl->args.info.fileLen = transControl->args.info.curPos = 0;
1299 
1300     if (FindOpenFile(transControl->args.info.fd, &selFile) != 0) {
1301         int32_t ret = fstat(transControl->args.info.fd, &statBuff);
1302         if (ret == 0) {
1303             transControl->args.info.fileLen = (uint32_t)statBuff.st_size;
1304             transControl->args.info.curPos  = (uint32_t)ftell(selFile->file);
1305         } else {
1306             tloge("fstat file failed: %" PUBLIC "d\n", errno);
1307             transControl->error = (uint32_t)errno;
1308         }
1309         transControl->ret = ret;
1310     } else {
1311         transControl->ret   = -1;
1312         transControl->error = EBADF;
1313     }
1314 }
1315 
FileAccessWork(struct SecStorageType * transControl)1316 static void FileAccessWork(struct SecStorageType *transControl)
1317 {
1318     int32_t ret;
1319     bool isBackup = false;
1320 
1321     tlogv("sec storage : file access\n");
1322 
1323     if (transControl->cmd == SEC_ACCESS) {
1324         char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1325         SetCurrentUserId(transControl->userId);
1326         SetCurrentStorageId(transControl->storageId);
1327 
1328 #ifdef CONFIG_BACKUP_PARTITION
1329         isBackup = transControl->isBackup;
1330 #endif
1331         if (JoinFileName((char *)(transControl->args.access.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1332             ret = access(nameBuff, transControl->args.access.mode);
1333             if (ret < 0) {
1334                 tloge("access file mode %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.access.mode, errno);
1335             }
1336             transControl->ret   = ret;
1337             transControl->error = (uint32_t)errno;
1338         } else {
1339             transControl->ret = -1;
1340         }
1341     } else {
1342         ret = access((char *)(transControl->args.access.name), transControl->args.access.mode);
1343         if (ret < 0) {
1344             tloge("access2 file mode %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.access.mode, errno);
1345         }
1346         transControl->ret   = ret;
1347         transControl->error = (uint32_t)errno;
1348     }
1349 }
1350 
FsyncWork(struct SecStorageType * transControl)1351 static void FsyncWork(struct SecStorageType *transControl)
1352 {
1353     struct OpenedFile *selFile = NULL;
1354 
1355     tlogw("sec storage : file fsync\n");
1356 
1357     /* opened file */
1358     if (transControl->args.fsync.fd != 0 && FindOpenFile(transControl->args.fsync.fd, &selFile) != 0) {
1359         /* first,flush memory from user to kernel */
1360         int32_t ret = fflush(selFile->file);
1361         if (ret != 0) {
1362             tloge("fsync:fflush file failed: %" PUBLIC "d\n", errno);
1363             transControl->ret   = -1;
1364             transControl->error = (uint32_t)errno;
1365             return;
1366         }
1367         tlogw("fflush file %" PUBLIC "d success\n", transControl->args.fsync.fd);
1368 
1369         /* second,fsync memory from kernel to disk */
1370         int32_t fd  = fileno(selFile->file);
1371         ret = fsync(fd);
1372         if (ret != 0) {
1373             tloge("fsync:fsync file failed: %" PUBLIC "d\n", errno);
1374             transControl->ret   = -1;
1375             transControl->error = (uint32_t)errno;
1376             return;
1377         }
1378 
1379         transControl->ret = 0;
1380         tlogw("fsync file %" PUBLIC "d success\n", transControl->args.fsync.fd);
1381     } else {
1382         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.fsync.fd);
1383         transControl->ret   = -1;
1384         transControl->error = EBADF;
1385     }
1386 }
1387 
1388 #define KBYTE 1024
DiskUsageWork(struct SecStorageType * transControl)1389 static void DiskUsageWork(struct SecStorageType *transControl)
1390 {
1391     struct statfs st;
1392     uint32_t dataRemain;
1393     uint32_t secStorageRemain;
1394     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1395 
1396     tlogv("sec storage : disk usage\n");
1397     if (GetTransientDir(nameBuff, FILE_NAME_MAX_BUF) != 0)
1398         goto ERROR;
1399     if (statfs((const char*)nameBuff, &st) < 0) {
1400         tloge("statfs /secStorageData failed, err=%" PUBLIC "d\n", errno);
1401         goto ERROR;
1402     }
1403     dataRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1404 
1405     if (GetPersistentDir(nameBuff, FILE_NAME_MAX_BUF) != 0) {
1406         tloge("get persistent dir error\n");
1407         goto ERROR;
1408     }
1409     if (strncat_s(nameBuff, FILE_NAME_MAX_BUF, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT)) != EOK) {
1410         tloge("strncat_s error\n");
1411         goto ERROR;
1412     }
1413     if (statfs((const char*)nameBuff, &st) < 0) {
1414         tloge("statfs /secStorage failed, err=%" PUBLIC "d\n", errno);
1415         goto ERROR;
1416     }
1417     secStorageRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1418 
1419     transControl->ret                       = 0;
1420     transControl->args.diskUsage.data       = dataRemain;
1421     transControl->args.diskUsage.secStorage = secStorageRemain;
1422     return;
1423 
1424 ERROR:
1425     transControl->ret   = -1;
1426     transControl->error = (uint32_t)errno;
1427 }
1428 
DeleteAllWork(struct SecStorageType * transControl)1429 static void DeleteAllWork(struct SecStorageType *transControl)
1430 {
1431     int32_t ret;
1432     char path[FILE_NAME_MAX_BUF] = { 0 };
1433     char *pathIn                 = (char *)(transControl->args.deleteAll.path);
1434     SetCurrentUserId(transControl->userId);
1435 
1436     tlogv("sec storage : delete path, userid:%" PUBLIC "d\n", transControl->userId);
1437 
1438     ret = DoJoinFileName(pathIn, path, sizeof(path));
1439     if (ret != EOK) {
1440         tloge("join name failed %" PUBLIC "d\n", ret);
1441         transControl->ret = -1;
1442         return;
1443     }
1444 
1445     tlogv("sec storage : joint delete path\n");
1446 
1447     ret = UnlinkRecursive(path);
1448     if (ret != 0) {
1449         tloge("delete file failed: %" PUBLIC "d\n", errno);
1450         transControl->error = (uint32_t)errno;
1451     } else {
1452         tloge("delete file success\n");
1453     }
1454     transControl->ret = ret;
1455 }
1456 
1457 typedef void (*FsWorkFunc)(struct SecStorageType *transControl);
1458 
1459 struct FsWorkTbl {
1460     enum FsCmdType cmd;
1461     FsWorkFunc fn;
1462 };
1463 
1464 static const struct FsWorkTbl g_fsWorkTbl[] = {
1465     { SEC_OPEN, OpenWork },           { SEC_CLOSE, CloseWork },
1466     { SEC_READ, ReadWork },           { SEC_WRITE, WriteWork },
1467     { SEC_SEEK, SeekWork },           { SEC_REMOVE, RemoveWork },
1468     { SEC_TRUNCATE, TruncateWork },   { SEC_RENAME, RenameWork },
1469     { SEC_CREATE, OpenWork },         { SEC_INFO, FileInfoWork },
1470     { SEC_ACCESS, FileAccessWork },   { SEC_ACCESS2, FileAccessWork },
1471     { SEC_FSYNC, FsyncWork },         { SEC_CP, CopyWork },
1472     { SEC_DISKUSAGE, DiskUsageWork }, { SEC_DELETE_ALL, DeleteAllWork },
1473 };
1474 
FsWorkEventHandle(struct SecStorageType * transControl,int32_t fsFd)1475 static int FsWorkEventHandle(struct SecStorageType *transControl, int32_t fsFd)
1476 {
1477     int32_t ret;
1478     uint64_t tsStart, tsEnd;
1479 
1480     ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_WAIT_EVENT, AGENT_FS_ID);
1481     if (ret != 0) {
1482         tloge("fs agent wait event failed, errno = %" PUBLIC "d\n", errno);
1483         return ret;
1484     }
1485 
1486     tlogv("fs agent wake up and working!!\n");
1487     tsStart = GetTimeStampUs();
1488 
1489     if ((transControl->cmd < SEC_MAX) && (g_fsWorkTbl[transControl->cmd].fn != NULL)) {
1490         g_fsWorkTbl[transControl->cmd].fn(transControl);
1491     } else {
1492         tloge("fs agent error cmd:transControl->cmd=%" PUBLIC "x\n", transControl->cmd);
1493     }
1494 
1495     tsEnd = GetTimeStampUs();
1496     if (tsEnd - tsStart > FSCMD_TIMEOUT_US) {
1497         tlogw("fs agent timeout, cmd=0x%" PUBLIC "x, cost=%" PUBLIC "llums\n",
1498             transControl->cmd, (tsEnd - tsStart) / USEC_PER_MSEC);
1499     }
1500 
1501     __asm__ volatile("isb");
1502     __asm__ volatile("dsb sy");
1503 
1504     transControl->magic = AGENT_FS_ID;
1505 
1506     __asm__ volatile("isb");
1507     __asm__ volatile("dsb sy");
1508 
1509     ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, AGENT_FS_ID);
1510     if (ret != 0) {
1511         tloge("fs agent send reponse failed\n");
1512         return ret;
1513     }
1514 
1515     return 0;
1516 }
1517 
FsWorkThread(void * control)1518 void *FsWorkThread(void *control)
1519 {
1520     struct SecStorageType *transControl = NULL;
1521     int32_t ret;
1522     int32_t fsFd;
1523 
1524     if (control == NULL) {
1525         return NULL;
1526     }
1527     transControl = control;
1528 
1529     fsFd = GetFsFd();
1530     if (fsFd == -1) {
1531         tloge("fs is not open\n");
1532         return NULL;
1533     }
1534 
1535     transControl->magic = AGENT_FS_ID;
1536 
1537 #ifdef CONFIG_FSWORK_THREAD_ELEVATE_PRIO
1538     if (setpriority(0, 0, FS_AGENT_THREAD_PRIO) != 0) {
1539         tloge("set fs work thread priority fail, err=%" PUBLIC "d\n", errno);
1540     }
1541 #endif
1542 
1543     while (1) {
1544         tlogv("++ fs agent loop ++\n");
1545         ret = FsWorkEventHandle(transControl, fsFd);
1546         if (ret != 0) {
1547             break;
1548         }
1549         tlogv("-- fs agent loop --\n");
1550     }
1551 
1552     return NULL;
1553 }
1554 
SetFileNumLimit(void)1555 void SetFileNumLimit(void)
1556 {
1557     struct rlimit rlim, rlimNew;
1558 
1559     int32_t rRet = getrlimit(RLIMIT_NOFILE, &rlim);
1560     if (rRet == 0) {
1561         rlimNew.rlim_cur = rlimNew.rlim_max = FILE_NUM_LIMIT_MAX;
1562         if (setrlimit(RLIMIT_NOFILE, &rlimNew) != 0) {
1563             rlimNew.rlim_cur = rlimNew.rlim_max = rlim.rlim_max;
1564             (void)setrlimit(RLIMIT_NOFILE, &rlimNew);
1565         }
1566     } else {
1567         tloge("getrlimit error is 0x%" PUBLIC "x, errno is %" PUBLIC "x", rRet, errno);
1568     }
1569 }
1570