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