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