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