1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "init_cmds.h"
16
17 #include <dlfcn.h>
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <net/if.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/ioctl.h>
25 #include <sys/mount.h>
26 #include <sys/resource.h>
27 #include <sys/stat.h>
28 #include <sys/syscall.h>
29 #include <sys/sysmacros.h>
30 #include <sys/wait.h>
31 #include <unistd.h>
32 #include <linux/module.h>
33
34 #include "bootstage.h"
35 #include "fs_manager/fs_manager.h"
36 #include "init_cmdexecutor.h"
37 #include "init_jobs_internal.h"
38 #include "init_log.h"
39 #include "init_param.h"
40 #include "init_service_manager.h"
41 #include "init_utils.h"
42 #include "sandbox.h"
43 #include "sandbox_namespace.h"
44 #include "securec.h"
45 #include "fscrypt_utils.h"
46
47 #ifdef SUPPORT_PROFILER_HIDEBUG
48 #include <hidebug_base.h>
49 #endif
50
51 #define FSCRYPT_POLICY_BUF_SIZE (60)
52
GetParamValue(const char * symValue,unsigned int symLen,char * paramValue,unsigned int paramLen)53 int GetParamValue(const char *symValue, unsigned int symLen, char *paramValue, unsigned int paramLen)
54 {
55 INIT_CHECK_RETURN_VALUE((symValue != NULL) && (paramValue != NULL) && (paramLen != 0), -1);
56 char tmpName[PARAM_NAME_LEN_MAX] = { 0 };
57 int ret;
58 uint32_t curr = 0;
59 char *start = (char *)symValue;
60 char *end = (char *)symValue + symLen;
61 do {
62 char *begin = strchr(start, '$');
63 if (begin == NULL || begin >= end) { // not has '$' copy the original string
64 ret = strncpy_s(paramValue + curr, paramLen - curr, start, symLen);
65 INIT_ERROR_CHECK(ret == EOK, return -1, "Failed to copy start %s", start);
66 break;
67 } else {
68 ret = memcpy_s(paramValue + curr, paramLen - curr, start, begin - start);
69 INIT_ERROR_CHECK(ret == 0, return -1, "Failed to copy first value %s", symValue);
70 curr += begin - start;
71 }
72 while (*begin != '{') {
73 INIT_CHECK_RETURN_VALUE(*begin != '\0', -1);
74 begin++;
75 }
76 begin++;
77 char *left = strchr(begin, '}');
78 INIT_CHECK_RETURN_VALUE(left != NULL, -1);
79
80 // copy param name
81 ret = strncpy_s(tmpName, PARAM_NAME_LEN_MAX, begin, left - begin);
82 INIT_ERROR_CHECK(ret == EOK, return -1, "Invalid param name %s", symValue);
83 uint32_t valueLen = paramLen - curr;
84 ret = SystemReadParam(tmpName, paramValue + curr, &valueLen);
85 INIT_ERROR_CHECK(ret == 0, return -1, "Failed to get param %s", tmpName);
86 curr += valueLen;
87 left++;
88 if ((unsigned int)(left - symValue) >= symLen) {
89 break;
90 }
91 start = left;
92 } while (1);
93 return 0;
94 }
95
SyncExecCommand(int argc,char * const * argv)96 static void SyncExecCommand(int argc, char * const *argv)
97 {
98 INIT_CHECK(!(argc == 0 || argv == NULL || argv[0] == NULL), return);
99 INIT_LOGI("Sync exec: %s", argv[0]);
100 pid_t pid = fork();
101 INIT_ERROR_CHECK(!(pid < 0), return, "Fork new process to format failed: %d", errno);
102 if (pid == 0) {
103 INIT_CHECK_ONLY_ELOG(execv(argv[0], argv) == 0, "execv %s failed! err %d.", argv[0], errno);
104 exit(-1);
105 }
106 int status;
107 pid_t ret = waitpid(pid, &status, 0);
108 if (ret != pid) {
109 INIT_LOGE("Failed to wait pid %d, errno %d", pid, errno);
110 return;
111 }
112 INIT_LOGI("Sync exec: %s result %d %d", argv[0], WEXITSTATUS(status), WIFEXITED(status));
113 return;
114 }
115
DoIfup(const struct CmdArgs * ctx)116 static void DoIfup(const struct CmdArgs *ctx)
117 {
118 struct ifreq interface;
119 INIT_ERROR_CHECK(strncpy_s(interface.ifr_name, IFNAMSIZ - 1, ctx->argv[0], strlen(ctx->argv[0])) == EOK,
120 return, "DoIfup failed to copy interface name");
121 INIT_LOGV("interface name: %s", interface.ifr_name);
122
123 int fd = socket(AF_INET, SOCK_DGRAM, 0);
124 INIT_ERROR_CHECK(fd >= 0, return, "DoIfup failed to create socket, err = %d", errno);
125
126 if (ioctl(fd, SIOCGIFFLAGS, &interface) >= 0) {
127 interface.ifr_flags |= IFF_UP;
128 INIT_CHECK_ONLY_ELOG(ioctl(fd, SIOCSIFFLAGS, &interface) >= 0,
129 "DoIfup failed to do ioctl with command \"SIOCSIFFLAGS\", err = %d", errno);
130 }
131 close(fd);
132 fd = -1;
133 }
134
135 // format insmod <ko name> [-f] [options]
DoInsmod(const struct CmdArgs * ctx)136 static void DoInsmod(const struct CmdArgs *ctx)
137 {
138 int index = 0;
139 int flags = 0;
140 char *fileName = NULL;
141 if (ctx->argc > index) {
142 fileName = ctx->argv[index];
143 index++;
144 }
145 INIT_ERROR_CHECK(fileName != NULL, return, "Can not find file name from param %s", ctx->argv[0]);
146 INIT_LOGV("Install mode %s ", fileName);
147 char *realPath = GetRealPath(fileName);
148 INIT_ERROR_CHECK(realPath != NULL, return, "Can not get real file name from param %s", ctx->argv[0]);
149 if (ctx->argc > 1 && ctx->argv[1] != NULL && strcmp(ctx->argv[1], "-f") == 0) { // [-f]
150 flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS;
151 index++;
152 }
153 char *options = BuildStringFromCmdArg(ctx, index); // [options]
154 int fd = open(realPath, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
155 if (fd >= 0) {
156 int rc = syscall(__NR_finit_module, fd, options, flags);
157 if (rc == -1) {
158 INIT_LOGE("Failed to install kernel module for %s failed options %s err: %d", realPath, options, errno);
159 }
160 }
161 if (options != NULL) {
162 free(options);
163 }
164 if (fd >= 0) {
165 close(fd);
166 }
167 free(realPath);
168 return;
169 }
170
DoSetParam(const struct CmdArgs * ctx)171 static void DoSetParam(const struct CmdArgs *ctx)
172 {
173 INIT_LOGV("set param name: %s, value %s ", ctx->argv[0], ctx->argv[1]);
174 SystemWriteParam(ctx->argv[0], ctx->argv[1]);
175 }
176
DoLoadPersistParams(const struct CmdArgs * ctx)177 static void DoLoadPersistParams(const struct CmdArgs *ctx)
178 {
179 INIT_LOGV("LoadPersistParams");
180 LoadPersistParams();
181 HookMgrExecute(GetBootStageHookMgr(), INIT_POST_PERSIST_PARAM_LOAD, NULL, NULL);
182 }
183
DoTriggerCmd(const struct CmdArgs * ctx)184 static void DoTriggerCmd(const struct CmdArgs *ctx)
185 {
186 INIT_LOGV("DoTrigger :%s", ctx->argv[0]);
187 DoTriggerExec(ctx->argv[0]);
188 }
189
DoLoadDefaultParams(const struct CmdArgs * ctx)190 static void DoLoadDefaultParams(const struct CmdArgs *ctx)
191 {
192 int mode = 0;
193 if (ctx->argc > 1 && strcmp(ctx->argv[1], "onlyadd") == 0) {
194 mode = LOAD_PARAM_ONLY_ADD;
195 }
196 INIT_LOGV("DoLoadDefaultParams args : %s %d", ctx->argv[0], mode);
197 LoadDefaultParams(ctx->argv[0], mode);
198 }
199
DoSyncExec(const struct CmdArgs * ctx)200 static void DoSyncExec(const struct CmdArgs *ctx)
201 {
202 // format: syncexec /xxx/xxx/xxx xxx
203 INIT_ERROR_CHECK(ctx != NULL && ctx->argv[0] != NULL, return, "DoSyncExec: invalid arguments");
204 SyncExecCommand(ctx->argc, ctx->argv);
205 return;
206 }
207
DoExec(const struct CmdArgs * ctx)208 static void DoExec(const struct CmdArgs *ctx)
209 {
210 // format: exec /xxx/xxx/xxx xxx
211 INIT_ERROR_CHECK(ctx != NULL && ctx->argv[0] != NULL, return, "DoExec: invalid arguments");
212 pid_t pid = fork();
213 INIT_ERROR_CHECK(pid >= 0, return, "DoExec: failed to fork child process to exec \"%s\"", ctx->argv[0]);
214
215 if (pid == 0) {
216 OpenHidebug(ctx->argv[0]);
217 int ret = execv(ctx->argv[0], ctx->argv);
218 INIT_CHECK_ONLY_ELOG(ret != -1, "DoExec: execute \"%s\" failed: %d.", ctx->argv[0], errno);
219 _exit(0x7f);
220 }
221 return;
222 }
223
DoSymlink(const struct CmdArgs * ctx)224 static void DoSymlink(const struct CmdArgs *ctx)
225 {
226 // format: symlink /xxx/xxx/xxx /xxx/xxx/xxx
227 int ret = symlink(ctx->argv[0], ctx->argv[1]);
228 if (ret != 0 && errno != EEXIST) {
229 INIT_LOGE("DoSymlink: link %s to %s failed: %d", ctx->argv[0], ctx->argv[1], errno);
230 }
231 }
232
GetDeviceMode(const char * deviceStr)233 static mode_t GetDeviceMode(const char *deviceStr)
234 {
235 switch (*deviceStr) {
236 case 'b':
237 case 'B':
238 return S_IFBLK;
239 case 'c':
240 case 'C':
241 return S_IFCHR;
242 case 'f':
243 case 'F':
244 return S_IFIFO;
245 default:
246 return -1;
247 }
248 }
249
DoMakeNode(const struct CmdArgs * ctx)250 static void DoMakeNode(const struct CmdArgs *ctx)
251 {
252 // format: mknod path b 0644 1 9
253 const int deviceTypePos = 1;
254 const int authorityPos = 2;
255 const int majorDevicePos = 3;
256 const int minorDevicePos = 4;
257 const int decimal = 10;
258 const int octal = 8;
259 INIT_ERROR_CHECK(access(ctx->argv[1], F_OK), return, "DoMakeNode failed, path has sexisted");
260 mode_t deviceMode = GetDeviceMode(ctx->argv[deviceTypePos]);
261 errno = 0;
262 unsigned int major = strtoul(ctx->argv[majorDevicePos], NULL, decimal);
263 INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[majorDevicePos]);
264 unsigned int minor = strtoul(ctx->argv[minorDevicePos], NULL, decimal);
265 INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[minorDevicePos]);
266 mode_t authority = strtoul(ctx->argv[authorityPos], NULL, octal);
267 INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[authorityPos]);
268 int ret = mknod(ctx->argv[0], deviceMode | authority, makedev(major, minor));
269 if (ret != 0) {
270 INIT_LOGE("DoMakeNode: path: %s failed: %d", ctx->argv[0], errno);
271 }
272 }
273
DoMakeDevice(const struct CmdArgs * ctx)274 static void DoMakeDevice(const struct CmdArgs *ctx)
275 {
276 // format: makedev major minor
277 const int decimal = 10;
278 errno = 0;
279 unsigned int major = strtoul(ctx->argv[0], NULL, decimal);
280 INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[0]);
281 unsigned int minor = strtoul(ctx->argv[1], NULL, decimal);
282 INIT_CHECK_ONLY_ELOG(errno != ERANGE, "Failed to strtoul %s", ctx->argv[1]);
283 dev_t deviceId = makedev(major, minor);
284 INIT_CHECK_ONLY_ELOG(deviceId >= 0, "DoMakedevice \" major:%s, minor:%s \" failed :%d ", ctx->argv[0],
285 ctx->argv[1], errno);
286 return;
287 }
288
DoMountFstabFile(const struct CmdArgs * ctx)289 static void DoMountFstabFile(const struct CmdArgs *ctx)
290 {
291 INIT_LOGI("Mount partitions from fstab file \" %s \"", ctx->argv[0]);
292 int ret = MountAllWithFstabFile(ctx->argv[0], 0);
293 INIT_LOGI("Mount partitions from fstab file \" %s \" finish ret %d", ctx->argv[0], ret);
294 }
295
DoUmountFstabFile(const struct CmdArgs * ctx)296 static void DoUmountFstabFile(const struct CmdArgs *ctx)
297 {
298 INIT_LOGI("Umount partitions from fstab file \" %s \"", ctx->argv[0]);
299 int rc = UmountAllWithFstabFile(ctx->argv[0]);
300 if (rc < 0) {
301 INIT_LOGE("Run command umount_fstab failed");
302 } else {
303 INIT_LOGI("Umount partitions from fstab done");
304 }
305 }
306
DoRestorecon(const struct CmdArgs * ctx)307 static void DoRestorecon(const struct CmdArgs *ctx)
308 {
309 if (ctx->argc != 1) {
310 INIT_LOGE("DoRestorecon invalid arguments.");
311 return;
312 }
313 PluginExecCmdByName("restoreContentRecurse", ctx->argv[0]);
314 return;
315 }
316
DoLoadAccessTokenId(const struct CmdArgs * ctx)317 static void DoLoadAccessTokenId(const struct CmdArgs *ctx)
318 {
319 LoadAccessTokenId();
320 }
321
FilterService(const Service * service,const char ** exclude,int size)322 static int FilterService(const Service *service, const char **exclude, int size)
323 {
324 for (int i = 0; i < size; i++) {
325 if (exclude[i] != NULL && strcmp(service->name, exclude[i]) == 0) {
326 return 0;
327 }
328 }
329 return 1;
330 }
331
DoStopAllServices(const struct CmdArgs * ctx)332 static void DoStopAllServices(const struct CmdArgs *ctx)
333 {
334 int flags = SERVICE_ATTR_INVALID;
335 if (ctx->argc >= 1 && strcmp(ctx->argv[0], "true") == 0) {
336 flags |= SERVICE_ATTR_NEEDWAIT;
337 StopAllServices(flags, (const char **)(&ctx->argv[1]), ctx->argc - 1, FilterService);
338 } else {
339 StopAllServices(flags, (const char **)ctx->argv, ctx->argc, FilterService);
340 }
341 return;
342 }
343
DoUmount(const struct CmdArgs * ctx)344 static void DoUmount(const struct CmdArgs *ctx)
345 {
346 INIT_LOGI("DoUmount %s", ctx->argv[0]);
347 MountStatus status = GetMountStatusForMountPoint(ctx->argv[0]);
348 if (status == MOUNT_MOUNTED) {
349 int ret = umount(ctx->argv[0]);
350 if ((ret != 0) && (ctx->argc > 1) && (strcmp(ctx->argv[1], "MNT_FORCE") == 0)) {
351 ret = umount2(ctx->argv[0], MNT_FORCE);
352 }
353 INIT_CHECK_ONLY_ELOG(ret == 0, "Failed to umount %s, errno %d", ctx->argv[0], errno);
354 } else if (status == MOUNT_UMOUNTED) {
355 INIT_LOGI("%s is already umounted", ctx->argv[0]);
356 } else {
357 INIT_LOGE("Failed to get %s mount status", ctx->argv[0]);
358 }
359 }
360
DoSync(const struct CmdArgs * ctx)361 static void DoSync(const struct CmdArgs *ctx)
362 {
363 sync();
364 }
365
DoTimerStart(const struct CmdArgs * ctx)366 static void DoTimerStart(const struct CmdArgs *ctx)
367 {
368 INIT_LOGI("Timer start service with arg = %s", ctx->argv[0]);
369 char *arg = ctx->argv[0];
370 int count = 0;
371 int expectedCount = 2;
372 char **splitArgs = SplitStringExt(ctx->argv[0], "|", &count, expectedCount);
373 if (splitArgs == NULL) {
374 INIT_LOGE("Call timer_start with invalid arguments");
375 return;
376 }
377
378 if (count != expectedCount) {
379 INIT_LOGE("Call timer_start with unexpected arguments %s", arg);
380 FreeStringVector(splitArgs, count);
381 return;
382 }
383
384 Service *service = GetServiceByName(splitArgs[0]);
385 if (service == NULL) {
386 INIT_LOGE("Cannot find service in timer_start command");
387 FreeStringVector(splitArgs, count);
388 return;
389 }
390
391 errno = 0;
392 uint64_t timeout = strtoull(splitArgs[1], NULL, DECIMAL_BASE);
393 if (errno != 0) {
394 INIT_LOGE("call timer_start with invalid timer");
395 FreeStringVector(splitArgs, count);
396 return;
397 }
398 // not need this anymore , release memory.
399 FreeStringVector(splitArgs, count);
400 ServiceStartTimer(service, timeout);
401 }
402
DoTimerStop(const struct CmdArgs * ctx)403 static void DoTimerStop(const struct CmdArgs *ctx)
404 {
405 INIT_LOGI("Stop service timer with arg = %s", ctx->argv[0]);
406 const char *serviceName = ctx->argv[0];
407 Service *service = GetServiceByName(serviceName);
408 if (service == NULL) {
409 INIT_LOGE("Cannot find service in timer_stop command");
410 return;
411 }
412 ServiceStopTimer(service);
413 }
414
InitFscryptPolicy(void)415 static bool InitFscryptPolicy(void)
416 {
417 char policy[FSCRYPT_POLICY_BUF_SIZE];
418 if (LoadFscryptPolicy(policy, FSCRYPT_POLICY_BUF_SIZE) != 0) {
419 return false;
420 }
421 if (SetFscryptSysparam(policy) == 0) {
422 return true;
423 }
424 return false;
425 }
426
DoInitGlobalKey(const struct CmdArgs * ctx)427 static void DoInitGlobalKey(const struct CmdArgs *ctx)
428 {
429 INIT_LOGV("Do init global key start");
430 if (ctx == NULL || ctx->argc != 1) {
431 INIT_LOGE("Parameter is invalid");
432 return;
433 }
434 const char *dataDir = "/data";
435 if (strncmp(ctx->argv[0], dataDir, strlen(dataDir)) != 0) {
436 INIT_LOGE("Not data partitation");
437 return;
438 }
439 if (!InitFscryptPolicy()) {
440 INIT_LOGW("Init fscrypt failed, not enable fscrypt");
441 return;
442 }
443
444 char * const argv[] = {
445 "/system/bin/sdc",
446 "filecrypt",
447 "init_global_key",
448 NULL
449 };
450 int argc = ARRAY_LENGTH(argv);
451 SyncExecCommand(argc, argv);
452 }
453
DoInitMainUser(const struct CmdArgs * ctx)454 static void DoInitMainUser(const struct CmdArgs *ctx)
455 {
456 if (ctx == NULL) {
457 INIT_LOGE("Do init main user: para invalid");
458 return;
459 }
460
461 char * const argv[] = {
462 "/system/bin/sdc",
463 "filecrypt",
464 "init_main_user",
465 NULL
466 };
467 int argc = ARRAY_LENGTH(argv);
468 SyncExecCommand(argc, argv);
469 }
470
DoMkswap(const struct CmdArgs * ctx)471 static void DoMkswap(const struct CmdArgs *ctx)
472 {
473 if (ctx == NULL) {
474 INIT_LOGE("Parameter is invalid");
475 return;
476 }
477 char *const argv[] = {
478 "/system/bin/mkswap",
479 ctx->argv[0],
480 NULL
481 };
482 int argc = ARRAY_LENGTH(argv);
483 SyncExecCommand(argc, argv);
484 }
485
DoSwapon(const struct CmdArgs * ctx)486 static void DoSwapon(const struct CmdArgs *ctx)
487 {
488 if (ctx == NULL) {
489 INIT_LOGE("Parameter is invalid");
490 return;
491 }
492 char *const argv[] = {
493 "/system/bin/swapon",
494 ctx->argv[0],
495 NULL
496 };
497 int argc = ARRAY_LENGTH(argv);
498 SyncExecCommand(argc, argv);
499 }
500
DoMkSandbox(const struct CmdArgs * ctx)501 static void DoMkSandbox(const struct CmdArgs *ctx)
502 {
503 INIT_LOGV("Do make sandbox start");
504 if ((ctx == NULL) || (ctx->argc != 1)) {
505 INIT_LOGE("Call DoMkSandbox with invalid arguments");
506 return;
507 }
508
509 const char *sandbox = ctx->argv[0];
510 if (sandbox == NULL) {
511 INIT_LOGE("Invalid sandbox name.");
512 return;
513 }
514 InitDefaultNamespace();
515 if (!InitSandboxWithName(sandbox)) {
516 INIT_LOGE("Failed to init sandbox with name %s.", sandbox);
517 }
518
519 if (PrepareSandbox(sandbox) != 0) {
520 INIT_LOGE("Failed to prepare sandbox %s.", sandbox);
521 DestroySandbox(sandbox);
522 }
523 if (EnterDefaultNamespace() < 0) {
524 INIT_LOGE("Failed to set default namespace.");
525 }
526 CloseDefaultNamespace();
527 }
528
529 static const struct CmdTable g_cmdTable[] = {
530 { "syncexec ", 1, 10, DoSyncExec },
531 { "exec ", 1, 10, DoExec },
532 { "mknode ", 1, 5, DoMakeNode },
533 { "makedev ", 2, 2, DoMakeDevice },
534 { "symlink ", 2, 2, DoSymlink },
535 { "trigger ", 1, 1, DoTriggerCmd },
536 { "insmod ", 1, 10, DoInsmod },
537 { "setparam ", 2, 2, DoSetParam },
538 { "load_persist_params ", 1, 1, DoLoadPersistParams },
539 { "load_param ", 1, 2, DoLoadDefaultParams },
540 { "load_access_token_id ", 1, 1, DoLoadAccessTokenId },
541 { "ifup ", 1, 1, DoIfup },
542 { "mount_fstab ", 1, 1, DoMountFstabFile },
543 { "umount_fstab ", 1, 1, DoUmountFstabFile },
544 { "restorecon ", 1, 1, DoRestorecon },
545 { "stopAllServices ", 0, 10, DoStopAllServices },
546 { "umount ", 1, 1, DoUmount },
547 { "sync ", 0, 1, DoSync },
548 { "timer_start", 1, 1, DoTimerStart },
549 { "timer_stop", 1, 1, DoTimerStop },
550 { "init_global_key ", 1, 1, DoInitGlobalKey },
551 { "init_main_user ", 0, 1, DoInitMainUser },
552 { "mkswap", 1, 1, DoMkswap},
553 { "swapon", 1, 1, DoSwapon},
554 { "mksandbox", 1, 1, DoMkSandbox},
555 };
556
GetCmdTable(int * number)557 const struct CmdTable *GetCmdTable(int *number)
558 {
559 *number = (int)ARRAY_LENGTH(g_cmdTable);
560 return g_cmdTable;
561 }
562
OpenHidebug(const char * name)563 void OpenHidebug(const char *name)
564 {
565 #ifdef SUPPORT_PROFILER_HIDEBUG
566 InitEnvironmentParam(name);
567 #endif
568 }
569
SetFileCryptPolicy(const char * dir)570 int SetFileCryptPolicy(const char *dir)
571 {
572 if (dir == NULL) {
573 INIT_LOGE("SetFileCryptPolicy:dir is null");
574 return -EINVAL;
575 }
576 return FscryptPolicyEnable(dir);
577 }
578