• 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             tlogw("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     if (strncmp(path, oldNameBuff, strlen(oldNameBuff) + 1) == 0) {
755         tlogd("name of bk file is the same as main file, needn't copy\n");
756         return 0;
757     }
758 
759     if (CreateDir(path, pathLen) != 0) {
760         return -1;
761     }
762     tlogw("try copy bk file from main partition to backup partition, %" PUBLIC "s\n", name);
763     ret = CopyFile((char *)oldNameBuff, path);
764     if (ret != 0) {
765         tloge("copy file failed: %" PUBLIC "d\n", errno);
766         return -1;
767     }
768 
769     ret = UnlinkRecursive((char *)oldNameBuff);
770     /* if old file delete failed, OpenWork failed */
771     if (ret != 0) {
772         tloge("delete old file failed: %" PUBLIC "d\n", errno);
773         (void)UnlinkRecursive(path);
774         return -1;
775     }
776 
777     return 0;
778 }
779 
DeleteBackupFile(char * nameBuff,size_t nameLen)780 static int32_t DeleteBackupFile(char *nameBuff, size_t nameLen)
781 {
782     char oldNameBuff[FILE_NAME_MAX_BUF] = { 0 };
783     errno_t rc = memcpy_s(oldNameBuff, sizeof(oldNameBuff), nameBuff, nameLen);
784     if (rc != EOK) {
785         tloge("memcpy_s failed %" PUBLIC "d \n", rc);
786         return -1;
787     }
788 
789     rc = strcat_s(oldNameBuff, sizeof(oldNameBuff), SFS_BACKUP_FILE_SUFFIX);
790     if (rc != EOK) {
791         tloge("strcat_s failed %" PUBLIC "d \n", rc);
792         return -1;
793     }
794 
795     if (IsFileExist(oldNameBuff) == 0)
796         return 0;
797 
798     tlogd("try unlink exist backfile in main partition\n");
799     if (unlink((char *)oldNameBuff) < 0) {
800         tloge("unlink failed, errno is %" PUBLIC "d\n", errno);
801         return -1;
802     }
803     return 0;
804 }
805 #endif
806 
DoOpenFile(const char * path,struct SecStorageType * transControl)807 static uint32_t DoOpenFile(const char *path, struct SecStorageType *transControl)
808 {
809     char trustPath[PATH_MAX] = { 0 };
810 
811     uint32_t rRet = GetRealFilePath(path, trustPath, sizeof(trustPath));
812     if (rRet != 0) {
813         tloge("get real path failed. err=%" PUBLIC "u\n", rRet);
814         return rRet;
815     }
816 
817     FILE *pFile = fopen(trustPath, transControl->args.open.mode);
818     if (pFile == NULL) {
819         tloge("open file with flag %" PUBLIC "s failed: %" PUBLIC "d\n", transControl->args.open.mode, errno);
820         return (uint32_t)errno;
821     }
822     ChownSecStorage(trustPath, true);
823     int32_t ret = AddOpenFile(pFile);
824     if (ret != 0) {
825         tloge("add OpenedFile failed\n");
826         (void)fclose(pFile);
827         return ENOMEM;
828     }
829     transControl->ret = fileno(pFile); /* return fileno */
830     return 0;
831 }
832 
833 #ifndef CONFIG_SMART_LOCK_PLATFORM
CheckPartitionReady(const char * mntDir)834 static int32_t CheckPartitionReady(const char *mntDir)
835 {
836     int err;
837     struct statfs rootStat, secStorageStat;
838     err = statfs("/", &rootStat);
839     if (err != 0) {
840         tloge("statfs root fail, errno=%" PUBLIC "d\n", errno);
841         return err;
842     }
843 
844     err = statfs(mntDir, &secStorageStat);
845     if (err != 0) {
846         tloge("statfs mntDir[%" PUBLIC "s] fail, errno=%" PUBLIC "d\n", mntDir, errno);
847         return err;
848     }
849     tlogd("statfs root.f_blocks=%" PUBLIC "llx, mntDir.f_blocks=%" PUBLIC "llx\n",
850         (unsigned long long)(rootStat.f_blocks), (unsigned long long)(secStorageStat.f_blocks));
851 
852     return rootStat.f_blocks != secStorageStat.f_blocks;
853 }
854 #endif
855 
GetTimeStampUs(void)856 static inline uint64_t GetTimeStampUs(void)
857 {
858     struct timespec ts = { 0 };
859     (void)clock_gettime(CLOCK_MONOTONIC, &ts);
860     return ts.tv_sec * USEC_PER_SEC + ts.tv_nsec / NSEC_PER_USEC;
861 }
862 
CheckOpenWorkValid(struct SecStorageType * transControl,bool isBackup,char * nameBuff,size_t nameLen)863 static int CheckOpenWorkValid(struct SecStorageType *transControl, bool isBackup, char *nameBuff, size_t nameLen)
864 {
865     int ret = 0;
866     if (transControl->cmd == SEC_CREATE) {
867         /* create a exist file, remove it at first */
868         errno_t rc = strncpy_s(transControl->args.open.mode,
869             sizeof(transControl->args.open.mode), "w+", sizeof("w+"));
870         if (rc != EOK) {
871             tloge("strncpy_s failed %" PUBLIC "d\n", rc);
872             ret = ENOENT;
873         }
874     } else {
875 #ifdef CONFIG_BACKUP_PARTITION
876         if (isBackup && CopyFromOldFile((char *)(transControl->args.open.name), nameBuff, nameLen) != 0) {
877             tloge("failed to copy bk file from main partition to backup partition\n");
878             return ENOENT;
879         }
880 #endif
881 
882         if (IsFileExist(nameBuff) == 0) {
883             /* open a nonexist file, return fail */
884             tlogw("file is not exist, open failed\n");
885             ret = ENOENT;
886         }
887     }
888     (void)isBackup;
889     (void)nameLen;
890     return ret;
891 }
892 
OpenWork(struct SecStorageType * transControl)893 static void OpenWork(struct SecStorageType *transControl)
894 {
895     uint32_t error;
896     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
897     bool isBackup = false;
898 
899     SetCurrentUserId(transControl->userId);
900     SetCurrentStorageId(transControl->storageId);
901 
902     tlogw("sec storage: cmd=%" PUBLIC "d, file=%" PUBLIC "s\n",
903         transControl->cmd, (char *)(transControl->args.open.name));
904 
905 #ifdef CONFIG_BACKUP_PARTITION
906     isBackup = transControl->isBackup;
907 #endif
908     if (JoinFileName((char *)(transControl->args.open.name), isBackup, nameBuff, sizeof(nameBuff)) != 0) {
909         transControl->ret = -1;
910         return;
911     }
912 #ifdef CONFIG_BACKUP_PARTITION
913     if (transControl->cmd == SEC_CREATE && DeleteBackupFile(nameBuff, sizeof(nameBuff)) != 0) {
914         tloge("create failed, bk file exist and delete it failed\n");
915         transControl->ret = -1;
916         return;
917     }
918 #endif
919 
920 #ifndef CONFIG_SMART_LOCK_PLATFORM
921     if (strstr((char *)nameBuff, SFS_PARTITION_PERSISTENT) != NULL) {
922         if (CheckPartitionReady("/sec_storage") <= 0) {
923             tloge("check /sec_storage partition_ready failed ----------->\n");
924             transControl->ret = -1;
925             return;
926         }
927     }
928 #endif
929 
930     if (CheckOpenWorkValid(transControl, isBackup, nameBuff, sizeof(nameBuff)) != 0) {
931         error = ENOENT;
932         goto ERROR;
933     }
934 
935     /* mkdir -p for new create files */
936     if (CreateDir(nameBuff, sizeof(nameBuff)) != 0) {
937         error = (uint32_t)errno;
938         goto ERROR;
939     }
940 
941     error = DoOpenFile(nameBuff, transControl);
942     if (error != 0) {
943         goto ERROR;
944     }
945 
946     return;
947 
948 ERROR:
949     transControl->ret   = -1;
950     transControl->error = error;
951     return;
952 }
953 
CloseWork(struct SecStorageType * transControl)954 static void CloseWork(struct SecStorageType *transControl)
955 {
956     struct OpenedFile *selFile = NULL;
957 
958     tlogv("sec storage : close\n");
959 
960     if (FindOpenFile(transControl->args.close.fd, &selFile) != 0) {
961         int32_t ret = fclose(selFile->file);
962         if (ret == 0) {
963             tlogv("close file %" PUBLIC "d success\n", transControl->args.close.fd);
964             DelOpenFile(selFile);
965             free(selFile);
966             selFile = NULL;
967             (void)selFile;
968         } else {
969             tloge("close file %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.close.fd, errno);
970             transControl->error = (uint32_t)errno;
971         }
972         transControl->ret = ret;
973     } else {
974         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.close.fd);
975         transControl->ret   = -1;
976         transControl->error = EBADF;
977     }
978 }
979 
ReadWork(struct SecStorageType * transControl)980 static void ReadWork(struct SecStorageType *transControl)
981 {
982     struct OpenedFile *selFile = NULL;
983 
984     tlogv("sec storage : read count = %" PUBLIC "u\n", transControl->args.read.count);
985 
986     if (FindOpenFile(transControl->args.read.fd, &selFile) != 0) {
987         size_t count = fread((void *)(transControl->args.read.buffer), 1, transControl->args.read.count, selFile->file);
988         transControl->ret = (int32_t)count;
989 
990         if (count < transControl->args.read.count) {
991             if (feof(selFile->file)) {
992                 transControl->ret2 = 0;
993                 tlogv("read end of file\n");
994             } else {
995                 transControl->ret2  = -1;
996                 transControl->error = (uint32_t)errno;
997                 tloge("read file failed: %" PUBLIC "d\n", errno);
998             }
999         } else {
1000             transControl->ret2 = 0;
1001             tlogv("read file success, content len=%" PUBLIC "zu\n", count);
1002         }
1003     } else {
1004         transControl->ret   = 0;
1005         transControl->ret2  = -1;
1006         transControl->error = EBADF;
1007         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.read.fd);
1008     }
1009 }
1010 
WriteWork(struct SecStorageType * transControl)1011 static void WriteWork(struct SecStorageType *transControl)
1012 {
1013     struct OpenedFile *selFile = NULL;
1014 
1015     tlogv("sec storage : write count = %" PUBLIC "u\n", transControl->args.write.count);
1016 
1017     if (FindOpenFile(transControl->args.write.fd, &selFile) != 0) {
1018         size_t count = fwrite((void *)(transControl->args.write.buffer), 1,
1019                               transControl->args.write.count, selFile->file);
1020         if (count < transControl->args.write.count) {
1021             tloge("write file failed: %" PUBLIC "d\n", errno);
1022             transControl->ret   = (int32_t)count;
1023             transControl->error = (uint32_t)errno;
1024             return;
1025         }
1026 
1027         if (transControl->ret2 == SEC_WRITE_SSA) {
1028             if (fflush(selFile->file) != 0) {
1029                 tloge("fflush file failed: %" PUBLIC "d\n", errno);
1030                 transControl->ret   = 0;
1031                 transControl->error = (uint32_t)errno;
1032             } else {
1033                 transControl->ret = (int32_t)count;
1034             }
1035         } else {
1036             transControl->ret   = (int32_t)count;
1037             transControl->error = 0;
1038         }
1039     } else {
1040         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.write.fd);
1041         transControl->ret   = 0;
1042         transControl->error = EBADF;
1043     }
1044 }
1045 
SeekWork(struct SecStorageType * transControl)1046 static void SeekWork(struct SecStorageType *transControl)
1047 {
1048     struct OpenedFile *selFile = NULL;
1049 
1050     tlogv("sec storage : seek offset=%" PUBLIC "d, whence=%" PUBLIC "u\n",
1051         transControl->args.seek.offset, transControl->args.seek.whence);
1052 
1053     if (FindOpenFile(transControl->args.seek.fd, &selFile) != 0) {
1054         int32_t ret = fseek(selFile->file, transControl->args.seek.offset, (int32_t)transControl->args.seek.whence);
1055         if (ret) {
1056             tloge("seek file failed: %" PUBLIC "d\n", errno);
1057             transControl->error = (uint32_t)errno;
1058         } else {
1059             tlogv("seek file success\n");
1060         }
1061         transControl->ret = ret;
1062     } else {
1063         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.seek.fd);
1064         transControl->ret   = -1;
1065         transControl->error = EBADF;
1066     }
1067 }
1068 
RemoveWork(struct SecStorageType * transControl)1069 static void RemoveWork(struct SecStorageType *transControl)
1070 {
1071     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1072     bool isBackup = false;
1073 
1074     tlogw("sec storage: remove=%" PUBLIC "s\n", (char *)(transControl->args.remove.name));
1075 
1076     SetCurrentUserId(transControl->userId);
1077     SetCurrentStorageId(transControl->storageId);
1078 
1079 #ifdef CONFIG_BACKUP_PARTITION
1080     isBackup = transControl->isBackup;
1081 #endif
1082     if (JoinFileName((char *)(transControl->args.remove.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1083         int32_t ret = UnlinkRecursive(nameBuff);
1084         if (ret != 0) {
1085             tloge("remove file failed: %" PUBLIC "d\n", errno);
1086             transControl->error = (uint32_t)errno;
1087         } else {
1088             tlogv("remove file success\n");
1089         }
1090         transControl->ret = ret;
1091     } else {
1092         transControl->ret = -1;
1093     }
1094 }
1095 
TruncateWork(struct SecStorageType * transControl)1096 static void TruncateWork(struct SecStorageType *transControl)
1097 {
1098     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1099     bool isBackup = false;
1100 
1101     tlogv("sec storage : truncate, len=%" PUBLIC "u\n", transControl->args.truncate.len);
1102 
1103     SetCurrentUserId(transControl->userId);
1104     SetCurrentStorageId(transControl->storageId);
1105 #ifdef CONFIG_BACKUP_PARTITION
1106     isBackup = transControl->isBackup;
1107 #endif
1108     if (JoinFileName((char *)(transControl->args.truncate.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1109         int32_t ret = truncate(nameBuff, (long)transControl->args.truncate.len);
1110         if (ret != 0) {
1111             tloge("truncate file failed: %" PUBLIC "d\n", errno);
1112             transControl->error = (uint32_t)errno;
1113         } else {
1114             tlogv("truncate file success\n");
1115         }
1116         transControl->ret = ret;
1117     } else {
1118         transControl->ret = -1;
1119     }
1120 }
1121 
RenameWork(struct SecStorageType * transControl)1122 static void RenameWork(struct SecStorageType *transControl)
1123 {
1124     char nameBuff[FILE_NAME_MAX_BUF]  = { 0 };
1125     char nameBuff2[FILE_NAME_MAX_BUF] = { 0 };
1126     bool oldIsBackup = false;
1127     bool newIsBackup = false;
1128 
1129     SetCurrentUserId(transControl->userId);
1130     SetCurrentStorageId(transControl->storageId);
1131 
1132     tlogw("sec storage: rename, old=%" PUBLIC "s, new=%" PUBLIC "s\n", (char *)(transControl->args.open.name),
1133         (char *)(transControl->args.rename.buffer) + transControl->args.rename.oldNameLen);
1134 
1135 #ifdef CONFIG_BACKUP_PARTITION
1136     oldIsBackup = transControl->isBackup;
1137     newIsBackup = transControl->isBackupExt;
1138 #endif
1139     int32_t joinRet1 = JoinFileName((char *)(transControl->args.rename.buffer), oldIsBackup, nameBuff,
1140         sizeof(nameBuff));
1141     int32_t joinRet2 = JoinFileName((char *)(transControl->args.rename.buffer) + transControl->args.rename.oldNameLen,
1142                                     newIsBackup, nameBuff2, sizeof(nameBuff2));
1143     if (joinRet1 == 0 && joinRet2 == 0) {
1144         int32_t ret = rename(nameBuff, nameBuff2);
1145         if (ret != 0) {
1146             tloge("rename file failed: %" PUBLIC "d\n", errno);
1147             transControl->error = (uint32_t)errno;
1148         } else {
1149             tlogv("rename file success\n");
1150         }
1151         transControl->ret = ret;
1152     } else {
1153         transControl->ret = -1;
1154     }
1155 }
1156 
1157 #define MAXBSIZE 65536
1158 
DoCopy(int32_t fromFd,int32_t toFd)1159 static int32_t DoCopy(int32_t fromFd, int32_t toFd)
1160 {
1161     int32_t ret;
1162     ssize_t rcount;
1163     ssize_t wcount;
1164 
1165     char *buf = (char *)malloc(MAXBSIZE * sizeof(char));
1166     if (buf == NULL) {
1167         tloge("malloc buf failed\n");
1168         return -1;
1169     }
1170 
1171     rcount = read(fromFd, buf, MAXBSIZE);
1172     while (rcount > 0) {
1173         wcount = write(toFd, buf, (size_t)rcount);
1174         if (rcount != wcount || wcount == -1) {
1175             tloge("write file failed: %" PUBLIC "d\n", errno);
1176             ret = -1;
1177             goto OUT;
1178         }
1179         rcount = read(fromFd, buf, MAXBSIZE);
1180     }
1181 
1182     if (rcount < 0) {
1183         tloge("read file failed: %" PUBLIC "d\n", errno);
1184         ret = -1;
1185         goto OUT;
1186     }
1187 
1188     /* fsync memory from kernel to disk */
1189     ret = fsync(toFd);
1190     if (ret != 0) {
1191         tloge("CopyFile:fsync file failed: %" PUBLIC "d\n", errno);
1192         goto OUT;
1193     }
1194 
1195 OUT:
1196     free(buf);
1197     return ret;
1198 }
1199 
CopyFile(const char * fromPath,const char * toPath)1200 static int32_t CopyFile(const char *fromPath, const char *toPath)
1201 {
1202     struct stat fromStat;
1203     char realFromPath[PATH_MAX] = { 0 };
1204     char realToPath[PATH_MAX]   = { 0 };
1205 
1206     uint32_t rRet = GetRealFilePath(fromPath, realFromPath, sizeof(realFromPath));
1207     if (rRet != 0) {
1208         tloge("get real from path failed. err=%" PUBLIC "u\n", rRet);
1209         return -1;
1210     }
1211 
1212     rRet = GetRealFilePath(toPath, realToPath, sizeof(realToPath));
1213     if (rRet != 0) {
1214         tloge("get real to path failed. err=%" PUBLIC "u\n", rRet);
1215         return -1;
1216     }
1217 
1218     int32_t fromFd = tee_open(realFromPath, O_RDONLY, 0);
1219     if (fromFd == -1) {
1220         tloge("open file failed: %" PUBLIC "d\n", errno);
1221         return -1;
1222     }
1223 
1224     int32_t ret = fstat(fromFd, &fromStat);
1225     if (ret == -1) {
1226         tloge("stat file failed: %" PUBLIC "d\n", errno);
1227         tee_close(&fromFd);
1228         return ret;
1229     }
1230 
1231     tlogw("Copy file size: %" PUBLIC "u bytes\n", (uint32_t)fromStat.st_size);
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     tlogw("sec storage: copy, oldpath=%" PUBLIC "s, newpath=%" PUBLIC "s\n", (char *)(transControl->args.cp.buffer),
1269         (char *)(transControl->args.cp.buffer) + transControl->args.cp.fromPathLen);
1270     if (joinRet1 == 0 && joinRet2 == 0) {
1271 #ifdef CONFIG_BACKUP_PARTITION
1272         if (IsFileExist(toPath) == 0) {
1273             tlogd("copy_to path not exist, mkdir it.\n");
1274             if (CreateDir(toPath, sizeof(toPath)) != 0) {
1275                 transControl->ret = -1;
1276                 return;
1277             }
1278         }
1279 #endif
1280         int32_t ret = CopyFile(fromPath, toPath);
1281         if (ret != 0) {
1282             tloge("copy file failed: %" PUBLIC "d\n", errno);
1283             transControl->error = (uint32_t)errno;
1284         } else {
1285             tlogv("copy file success\n");
1286         }
1287         transControl->ret = ret;
1288     } else {
1289         transControl->ret = -1;
1290     }
1291 }
1292 
FileInfoWork(struct SecStorageType * transControl)1293 static void FileInfoWork(struct SecStorageType *transControl)
1294 {
1295     struct OpenedFile *selFile = NULL;
1296     struct stat statBuff;
1297 
1298     tlogv("sec storage : file info\n");
1299 
1300     transControl->args.info.fileLen = transControl->args.info.curPos = 0;
1301 
1302     if (FindOpenFile(transControl->args.info.fd, &selFile) != 0) {
1303         int32_t ret = fstat(transControl->args.info.fd, &statBuff);
1304         if (ret == 0) {
1305             transControl->args.info.fileLen = (uint32_t)statBuff.st_size;
1306             transControl->args.info.curPos  = (uint32_t)ftell(selFile->file);
1307         } else {
1308             tloge("fstat file failed: %" PUBLIC "d\n", errno);
1309             transControl->error = (uint32_t)errno;
1310         }
1311         transControl->ret = ret;
1312     } else {
1313         transControl->ret   = -1;
1314         transControl->error = EBADF;
1315     }
1316 }
1317 
FileAccessWork(struct SecStorageType * transControl)1318 static void FileAccessWork(struct SecStorageType *transControl)
1319 {
1320     int32_t ret;
1321     bool isBackup = false;
1322 
1323     tlogv("sec storage : file access\n");
1324 
1325     if (transControl->cmd == SEC_ACCESS) {
1326         char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1327         SetCurrentUserId(transControl->userId);
1328         SetCurrentStorageId(transControl->storageId);
1329 
1330 #ifdef CONFIG_BACKUP_PARTITION
1331         isBackup = transControl->isBackup;
1332 #endif
1333         if (JoinFileName((char *)(transControl->args.access.name), isBackup, nameBuff, sizeof(nameBuff)) == 0) {
1334             ret = access(nameBuff, transControl->args.access.mode);
1335             if (ret < 0) {
1336                 tloge("access file mode %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.access.mode, errno);
1337             }
1338             transControl->ret   = ret;
1339             transControl->error = (uint32_t)errno;
1340         } else {
1341             transControl->ret = -1;
1342         }
1343     } else {
1344         ret = access((char *)(transControl->args.access.name), transControl->args.access.mode);
1345         if (ret < 0) {
1346             tloge("access2 file mode %" PUBLIC "d failed: %" PUBLIC "d\n", transControl->args.access.mode, errno);
1347         }
1348         transControl->ret   = ret;
1349         transControl->error = (uint32_t)errno;
1350     }
1351 }
1352 
FsyncWork(struct SecStorageType * transControl)1353 static void FsyncWork(struct SecStorageType *transControl)
1354 {
1355     struct OpenedFile *selFile = NULL;
1356 
1357     tlogw("sec storage : file fsync\n");
1358 
1359     /* opened file */
1360     if (transControl->args.fsync.fd != 0 && FindOpenFile(transControl->args.fsync.fd, &selFile) != 0) {
1361         /* first,flush memory from user to kernel */
1362         int32_t ret = fflush(selFile->file);
1363         if (ret != 0) {
1364             tloge("fsync:fflush file failed: %" PUBLIC "d\n", errno);
1365             transControl->ret   = -1;
1366             transControl->error = (uint32_t)errno;
1367             return;
1368         }
1369         tlogw("fflush file %" PUBLIC "d success\n", transControl->args.fsync.fd);
1370 
1371         /* second,fsync memory from kernel to disk */
1372         int32_t fd  = fileno(selFile->file);
1373         ret = fsync(fd);
1374         if (ret != 0) {
1375             tloge("fsync:fsync file failed: %" PUBLIC "d\n", errno);
1376             transControl->ret   = -1;
1377             transControl->error = (uint32_t)errno;
1378             return;
1379         }
1380 
1381         transControl->ret = 0;
1382         tlogw("fsync file %" PUBLIC "d success\n", transControl->args.fsync.fd);
1383     } else {
1384         tloge("can't find opened file(fileno = %" PUBLIC "d)\n", transControl->args.fsync.fd);
1385         transControl->ret   = -1;
1386         transControl->error = EBADF;
1387     }
1388 }
1389 
1390 #define KBYTE 1024
DiskUsageWork(struct SecStorageType * transControl)1391 static void DiskUsageWork(struct SecStorageType *transControl)
1392 {
1393     struct statfs st;
1394     uint32_t dataRemain;
1395     uint32_t secStorageRemain;
1396     char nameBuff[FILE_NAME_MAX_BUF] = { 0 };
1397 
1398     tlogv("sec storage : disk usage\n");
1399     if (GetTransientDir(nameBuff, FILE_NAME_MAX_BUF) != 0)
1400         goto ERROR;
1401     if (statfs((const char*)nameBuff, &st) < 0) {
1402         tloge("statfs /secStorageData failed, err=%" PUBLIC "d\n", errno);
1403         goto ERROR;
1404     }
1405     dataRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1406 
1407     if (GetPersistentDir(nameBuff, FILE_NAME_MAX_BUF) != 0) {
1408         tloge("get persistent dir error\n");
1409         goto ERROR;
1410     }
1411     if (strncat_s(nameBuff, FILE_NAME_MAX_BUF, SFS_PARTITION_PERSISTENT, strlen(SFS_PARTITION_PERSISTENT)) != EOK) {
1412         tloge("strncat_s error\n");
1413         goto ERROR;
1414     }
1415     if (statfs((const char*)nameBuff, &st) < 0) {
1416         tloge("statfs /secStorage failed, err=%" PUBLIC "d\n", errno);
1417         goto ERROR;
1418     }
1419     secStorageRemain = (uint32_t)st.f_bfree * (uint32_t)st.f_bsize / KBYTE;
1420 
1421     transControl->ret                       = 0;
1422     transControl->args.diskUsage.data       = dataRemain;
1423     transControl->args.diskUsage.secStorage = secStorageRemain;
1424     return;
1425 
1426 ERROR:
1427     transControl->ret   = -1;
1428     transControl->error = (uint32_t)errno;
1429 }
1430 
DeleteAllWork(struct SecStorageType * transControl)1431 static void DeleteAllWork(struct SecStorageType *transControl)
1432 {
1433     int32_t ret;
1434     char path[FILE_NAME_MAX_BUF] = { 0 };
1435     char *pathIn                 = (char *)(transControl->args.deleteAll.path);
1436     SetCurrentUserId(transControl->userId);
1437 
1438     tlogv("sec storage : delete path, userid:%" PUBLIC "d\n", transControl->userId);
1439 
1440     ret = DoJoinFileName(pathIn, path, sizeof(path));
1441     if (ret != EOK) {
1442         tloge("join name failed %" PUBLIC "d\n", ret);
1443         transControl->ret = -1;
1444         return;
1445     }
1446 
1447     tlogv("sec storage : joint delete path\n");
1448 
1449     ret = UnlinkRecursive(path);
1450     if (ret != 0) {
1451         tloge("delete file failed: %" PUBLIC "d\n", errno);
1452         transControl->error = (uint32_t)errno;
1453     } else {
1454         tloge("delete file success\n");
1455     }
1456     transControl->ret = ret;
1457 }
1458 
1459 typedef void (*FsWorkFunc)(struct SecStorageType *transControl);
1460 
1461 struct FsWorkTbl {
1462     enum FsCmdType cmd;
1463     FsWorkFunc fn;
1464 };
1465 
1466 static const struct FsWorkTbl g_fsWorkTbl[] = {
1467     { SEC_OPEN, OpenWork },           { SEC_CLOSE, CloseWork },
1468     { SEC_READ, ReadWork },           { SEC_WRITE, WriteWork },
1469     { SEC_SEEK, SeekWork },           { SEC_REMOVE, RemoveWork },
1470     { SEC_TRUNCATE, TruncateWork },   { SEC_RENAME, RenameWork },
1471     { SEC_CREATE, OpenWork },         { SEC_INFO, FileInfoWork },
1472     { SEC_ACCESS, FileAccessWork },   { SEC_ACCESS2, FileAccessWork },
1473     { SEC_FSYNC, FsyncWork },         { SEC_CP, CopyWork },
1474     { SEC_DISKUSAGE, DiskUsageWork }, { SEC_DELETE_ALL, DeleteAllWork },
1475 };
1476 
FsWorkEventHandle(struct SecStorageType * transControl,int32_t fsFd)1477 static int FsWorkEventHandle(struct SecStorageType *transControl, int32_t fsFd)
1478 {
1479     int32_t ret;
1480     uint64_t tsStart, tsEnd;
1481 
1482     ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_WAIT_EVENT, AGENT_FS_ID);
1483     if (ret != 0) {
1484         tloge("fs agent wait event failed, errno = %" PUBLIC "d\n", errno);
1485         return ret;
1486     }
1487 
1488     tlogv("fs agent wake up and working!!\n");
1489     tsStart = GetTimeStampUs();
1490 
1491     if ((transControl->cmd < SEC_MAX) && (g_fsWorkTbl[transControl->cmd].fn != NULL)) {
1492         g_fsWorkTbl[transControl->cmd].fn(transControl);
1493     } else {
1494         tloge("fs agent error cmd:transControl->cmd=%" PUBLIC "x\n", transControl->cmd);
1495     }
1496 
1497     tsEnd = GetTimeStampUs();
1498     if (tsEnd - tsStart > FSCMD_TIMEOUT_US) {
1499         tlogw("fs agent timeout, cmd=0x%" PUBLIC "x, cost=%" PUBLIC "llums\n",
1500             transControl->cmd, (tsEnd - tsStart) / USEC_PER_MSEC);
1501     }
1502 
1503     __asm__ volatile("isb");
1504     __asm__ volatile("dsb sy");
1505 
1506     transControl->magic = AGENT_FS_ID;
1507 
1508     __asm__ volatile("isb");
1509     __asm__ volatile("dsb sy");
1510 
1511     ret = ioctl(fsFd, (int32_t)TC_NS_CLIENT_IOCTL_SEND_EVENT_RESPONSE, AGENT_FS_ID);
1512     if (ret != 0) {
1513         tloge("fs agent send reponse failed\n");
1514         return ret;
1515     }
1516 
1517     return 0;
1518 }
1519 
FsWorkThread(void * control)1520 void *FsWorkThread(void *control)
1521 {
1522     struct SecStorageType *transControl = NULL;
1523     int32_t ret;
1524     int32_t fsFd;
1525 
1526     if (control == NULL) {
1527         return NULL;
1528     }
1529     transControl = control;
1530 
1531     fsFd = GetFsFd();
1532     if (fsFd == -1) {
1533         tloge("fs is not open\n");
1534         return NULL;
1535     }
1536 
1537     transControl->magic = AGENT_FS_ID;
1538 
1539 #ifdef CONFIG_FSWORK_THREAD_ELEVATE_PRIO
1540     if (setpriority(0, 0, FS_AGENT_THREAD_PRIO) != 0) {
1541         tloge("set fs work thread priority fail, err=%" PUBLIC "d\n", errno);
1542     }
1543 #endif
1544 
1545     while (1) {
1546         tlogv("++ fs agent loop ++\n");
1547         ret = FsWorkEventHandle(transControl, fsFd);
1548         if (ret != 0) {
1549             break;
1550         }
1551         tlogv("-- fs agent loop --\n");
1552     }
1553 
1554     return NULL;
1555 }
1556 
SetFileNumLimit(void)1557 void SetFileNumLimit(void)
1558 {
1559     struct rlimit rlim, rlimNew;
1560 
1561     int32_t rRet = getrlimit(RLIMIT_NOFILE, &rlim);
1562     if (rRet == 0) {
1563         rlimNew.rlim_cur = rlimNew.rlim_max = FILE_NUM_LIMIT_MAX;
1564         if (setrlimit(RLIMIT_NOFILE, &rlimNew) != 0) {
1565             rlimNew.rlim_cur = rlimNew.rlim_max = rlim.rlim_max;
1566             (void)setrlimit(RLIMIT_NOFILE, &rlimNew);
1567         }
1568     } else {
1569         tloge("getrlimit error is 0x%" PUBLIC "x, errno is %" PUBLIC "x", rRet, errno);
1570     }
1571 }
1572