1/* 2 * Copyright (c) 2024 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 <fcntl.h> 16#include <grp.h> 17#include <inttypes.h> 18#include <limits.h> 19#include <sys/capability.h> 20#include <stdbool.h> 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <sys/ioctl.h> 25#include <sys/mount.h> 26#include <sys/prctl.h> 27#include <sys/signalfd.h> 28#include <sys/stat.h> 29#include <sys/syscall.h> 30#include <sys/types.h> 31#include <sys/wait.h> 32#include <unistd.h> 33 34#undef _GNU_SOURCE 35#define _GNU_SOURCE 36#include <dlfcn.h> 37#include <malloc.h> 38#include <sched.h> 39 40#include "appspawn_adapter.h" 41#include "appspawn_hook.h" 42#include "appspawn_service.h" 43#include "appspawn_msg.h" 44#include "appspawn_manager.h" 45#include "appspawn_silk.h" 46#include "init_param.h" 47#include "parameter.h" 48#include "securec.h" 49 50#ifdef CODE_SIGNATURE_ENABLE // for xpm 51#include "code_sign_attr_utils.h" 52#endif 53#ifdef SECURITY_COMPONENT_ENABLE 54#include "sec_comp_enhance_kit_c.h" 55#endif 56#ifdef WITH_SELINUX 57#include "selinux/selinux.h" 58#endif 59 60#define PROVISION_TYPE_DEBUG "debug" 61#define DEVICE_NULL_STR "/dev/null" 62#define BITLEN32 32 63#define PID_NS_INIT_UID 100000 // reserved for pid_ns_init process, avoid app, render proc, etc. 64#define PID_NS_INIT_GID 100000 65 66static int SetProcessName(const AppSpawnMgr *content, const AppSpawningCtx *property) 67{ 68 const char *processName = GetProcessName(property); 69 APPSPAWN_CHECK(processName != NULL, return -EINVAL, "Can not get process name"); 70 // 解析时已经检查 71 size_t len = strlen(processName); 72 char shortName[MAX_LEN_SHORT_NAME] = {0}; 73 // process short name max length 16 bytes. 74 size_t copyLen = len; 75 const char *pos = processName; 76 if (len >= MAX_LEN_SHORT_NAME) { 77 copyLen = MAX_LEN_SHORT_NAME - 1; 78 pos += (len - copyLen); 79 } 80 bool isRet = strncpy_s(shortName, MAX_LEN_SHORT_NAME, pos, copyLen) != EOK; 81 APPSPAWN_CHECK(!isRet, return EINVAL, "strncpy_s short name error: %{public}d", errno); 82 83 // set short name 84 isRet = prctl(PR_SET_NAME, shortName) == -1; 85 APPSPAWN_CHECK(!isRet, return errno, "prctl(PR_SET_NAME) error: %{public}d", errno); 86 87 // reset longProcName 88 isRet = memset_s(content->content.longProcName, 89 (size_t)content->content.longProcNameLen, 0, (size_t)content->content.longProcNameLen) != EOK; 90 APPSPAWN_CHECK(!isRet, return EINVAL, "Failed to memset long process name"); 91 92 // set long process name 93 isRet = strncpy_s(content->content.longProcName, content->content.longProcNameLen, processName, len) != EOK; 94 APPSPAWN_CHECK(!isRet, return EINVAL, 95 "strncpy_s long name error: %{public}d longProcNameLen %{public}u", errno, content->content.longProcNameLen); 96 return 0; 97} 98 99static int SetKeepCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property) 100{ 101 AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO); 102 APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE, 103 "No tlv %{public}d in msg %{public}s", TLV_DOMAIN_INFO, GetProcessName(property)); 104 105 // set keep capabilities when user not root. 106 if (dacInfo->uid != 0) { 107 bool isRet = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1; 108 APPSPAWN_CHECK(!isRet, return errno, "set keepcaps failed: %{public}d", errno); 109 } 110 return 0; 111} 112 113static int SetCapabilities(const AppSpawnMgr *content, const AppSpawningCtx *property) 114{ 115 // init cap 116 struct __user_cap_header_struct capHeader; 117 118 bool isRet = memset_s(&capHeader, sizeof(capHeader), 0, sizeof(capHeader)) != EOK; 119 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header"); 120 121 capHeader.version = _LINUX_CAPABILITY_VERSION_3; 122 capHeader.pid = 0; 123 124 struct __user_cap_data_struct capData[2]; // 2 is data number 125 isRet = memset_s(&capData, sizeof(capData), 0, sizeof(capData)) != EOK; 126 APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data"); 127 128 // init inheritable permitted effective zero 129#ifdef GRAPHIC_PERMISSION_CHECK 130 const uint64_t inheriTable = 0; 131 const uint64_t permitted = 0; 132 const uint64_t effective = 0; 133#else 134 const uint64_t inheriTable = 0x3fffffffff; 135 const uint64_t permitted = 0x3fffffffff; 136 const uint64_t effective = 0x3fffffffff; 137#endif 138 139 capData[0].inheritable = (__u32)(inheriTable); 140 capData[1].inheritable = (__u32)(inheriTable >> BITLEN32); 141 capData[0].permitted = (__u32)(permitted); 142 capData[1].permitted = (__u32)(permitted >> BITLEN32); 143 capData[0].effective = (__u32)(effective); 144 capData[1].effective = (__u32)(effective >> BITLEN32); 145 146 // set capabilities 147 isRet = capset(&capHeader, &capData[0]) != 0; 148 APPSPAWN_CHECK(!isRet, return -errno, "Failed to capset errno: %{public}d", errno); 149 return 0; 150} 151 152static void InitDebugParams(const AppSpawnMgr *content, const AppSpawningCtx *property) 153{ 154#if defined(__aarch64__) || defined(__x86_64__) 155 const char *debugSoPath = "/system/lib64/libhidebug.so"; 156#else 157 const char *debugSoPath = "/system/lib/libhidebug.so"; 158#endif 159 const char *processName = GetProcessName(property); 160 APPSPAWN_CHECK(processName != NULL, return, "Can not get process name"); 161 162 bool isRet = access(debugSoPath, F_OK) != 0; 163 APPSPAWN_CHECK(!isRet, return, 164 "access failed, errno: %{public}d debugSoPath: %{public}s", errno, debugSoPath); 165 166 void *handle = dlopen(debugSoPath, RTLD_LAZY); 167 APPSPAWN_CHECK(handle != NULL, return, "Failed to dlopen libhidebug.so errno: %{public}s", dlerror()); 168 169 bool (*initParam)(const char *name); 170 initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam"); 171 APPSPAWN_CHECK(initParam != NULL, dlclose(handle); 172 return, "Failed to dlsym errno: %{public}s", dlerror()); 173 (*initParam)(processName); 174 dlclose(handle); 175} 176 177static void ClearEnvironment(const AppSpawnMgr *content, const AppSpawningCtx *property) 178{ 179 sigset_t mask; 180 sigemptyset(&mask); 181 sigaddset(&mask, SIGCHLD); 182 sigaddset(&mask, SIGTERM); 183 sigprocmask(SIG_UNBLOCK, &mask, NULL); 184 // close child fd 185 AppSpawningCtx *ctx = (AppSpawningCtx *)property; 186 close(ctx->forkCtx.fd[0]); 187 ctx->forkCtx.fd[0] = -1; 188 return; 189} 190 191static int SetXpmConfig(const AppSpawnMgr *content, const AppSpawningCtx *property) 192{ 193#ifdef CODE_SIGNATURE_ENABLE 194 // nwebspawn no permission set xpm config 195 if (IsNWebSpawnMode(content)) { 196 return 0; 197 } 198 199 uint32_t len = 0; 200 char *provisionType = GetAppPropertyExt(property, MSG_EXT_NAME_PROVISION_TYPE, &len); 201 if (provisionType == NULL || len == 0) { 202 APPSPAWN_LOGE("get provision type failed, defaut is %{public}s", PROVISION_TYPE_DEBUG); 203 provisionType = PROVISION_TYPE_DEBUG; 204 } 205 206 AppSpawnMsgOwnerId *ownerInfo = (AppSpawnMsgOwnerId *)GetAppProperty(property, TLV_OWNER_INFO); 207 int jitfortEnable = IsJitFortModeOn(property) ? 1 : 0; 208 int idType = PROCESS_OWNERID_UNINIT; 209 const char *ownerId = NULL; 210 if (strcmp(provisionType, PROVISION_TYPE_DEBUG) == 0) { 211 idType = PROCESS_OWNERID_DEBUG; 212 } else if (ownerInfo == NULL) { 213 idType = PROCESS_OWNERID_COMPAT; 214 } else if (CheckAppMsgFlagsSet(property, APP_FLAGS_TEMP_JIT)) { 215 idType = PROCESS_OWNERID_APP_TEMP_ALLOW; 216 ownerId = ownerInfo->ownerId; 217 } else { 218 idType = PROCESS_OWNERID_APP; 219 ownerId = ownerInfo->ownerId; 220 } 221 int ret = InitXpm(jitfortEnable, idType, ownerId); 222 APPSPAWN_CHECK(ret == 0, return ret, "set xpm region failed: %{public}d", ret); 223#endif 224 return 0; 225} 226 227static int SetUidGid(const AppSpawnMgr *content, const AppSpawningCtx *property) 228{ 229 AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppProperty(property, TLV_DAC_INFO); 230 APPSPAWN_CHECK(dacInfo != NULL, return APPSPAWN_TLV_NONE, 231 "No tlv %{public}d in msg %{public}s", TLV_DAC_INFO, GetProcessName(property)); 232 233 // set gids 234 int ret = setgroups(dacInfo->gidCount, (const gid_t *)(&dacInfo->gidTable[0])); 235 APPSPAWN_CHECK(ret == 0, return errno, 236 "setgroups failed: %{public}d, gids.size=%{public}u", errno, dacInfo->gidCount); 237 238 // set gid 239 if (IsNWebSpawnMode(content)) { 240 gid_t gid = dacInfo->gid / UID_BASE; 241 if (gid >= 100) { // 100 242 APPSPAWN_LOGE("SetUidGid invalid uid for nwebspawn %{public}d", dacInfo->gid); 243 return 0; 244 } 245 ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid); 246 } else { 247 ret = setresgid(dacInfo->gid, dacInfo->gid, dacInfo->gid); 248 } 249 APPSPAWN_CHECK(ret == 0, return errno, 250 "setgid(%{public}u) failed: %{public}d", dacInfo->gid, errno); 251 252 ret = SetSeccompFilter(content, property); 253 APPSPAWN_CHECK(ret == 0, return ret, "Failed to set setSeccompFilter"); 254 255 /* If the effective user ID is changed from 0 to nonzero, 256 * then all capabilities are cleared from the effective set 257 */ 258 ret = setresuid(dacInfo->uid, dacInfo->uid, dacInfo->uid); 259 APPSPAWN_CHECK(ret == 0, return errno, 260 "setuid(%{public}u) failed: %{public}d", dacInfo->uid, errno); 261 262 if (CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE) && IsDeveloperModeOn(property)) { 263 setenv("HAP_DEBUGGABLE", "true", 1); 264 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { 265 APPSPAWN_LOGE("Failed to set app dumpable: %{public}s", strerror(errno)); 266 } 267 } else { 268 setenv("HAP_DEBUGGABLE", "false", 1); 269 } 270 return 0; 271} 272 273static int32_t SetFileDescriptors(const AppSpawnMgr *content, const AppSpawningCtx *property) 274{ 275#ifndef APPSPAWN_TEST 276 // redirect stdin stdout stderr to /dev/null 277 int devNullFd = open(DEVICE_NULL_STR, O_RDWR); 278 if (devNullFd == -1) { 279 APPSPAWN_LOGE("open dev_null error: %{public}d", errno); 280 return (-errno); 281 } 282 283 // stdin 284 if (dup2(devNullFd, STDIN_FILENO) == -1) { 285 APPSPAWN_LOGE("dup2 STDIN error: %{public}d", errno); 286 return (-errno); 287 } 288 // stdout 289 if (dup2(devNullFd, STDOUT_FILENO) == -1) { 290 APPSPAWN_LOGE("dup2 STDOUT error: %{public}d", errno); 291 return (-errno); 292 } 293 // stderr 294 if (dup2(devNullFd, STDERR_FILENO) == -1) { 295 APPSPAWN_LOGE("dup2 STDERR error: %{public}d", errno); 296 return (-errno); 297 } 298 299 if (devNullFd > STDERR_FILENO) { 300 close(devNullFd); 301 } 302#endif 303 return 0; 304} 305 306static int32_t CheckTraceStatus(void) 307{ 308 int fd = open("/proc/self/status", O_RDONLY); 309 APPSPAWN_CHECK(fd >= 0, return errno, "Failed to open /proc/self/status error: %{public}d", errno); 310 311 char data[1024] = {0}; // 1024 is data length 312 ssize_t dataNum = read(fd, data, sizeof(data) - 1); 313 (void)close(fd); 314 APPSPAWN_CHECK(dataNum > 0, return -1, "Failed to read file /proc/self/status error: %{public}d", errno); 315 316 const char *tracerPid = "TracerPid:\t"; 317 data[dataNum] = '\0'; 318 char *traceStr = strstr(data, tracerPid); 319 APPSPAWN_CHECK(traceStr != NULL, return -1, "Not found %{public}s", tracerPid); 320 321 char *separator = strchr(traceStr, '\n'); 322 APPSPAWN_CHECK(separator != NULL, return -1, "Not found %{public}s", "\n"); 323 324 int len = separator - traceStr - strlen(tracerPid); 325 char pid = *(traceStr + strlen(tracerPid)); 326 if (len > 1 || pid != '0') { 327 return 0; 328 } 329 return -1; 330} 331 332static int32_t WaitForDebugger(const AppSpawningCtx *property) 333{ 334 // wait for debugger only debugging is required and process is debuggable 335 if (CheckAppMsgFlagsSet(property, APP_FLAGS_NATIVEDEBUG) && CheckAppMsgFlagsSet(property, APP_FLAGS_DEBUGGABLE)) { 336 uint32_t count = 0; 337 while (CheckTraceStatus() != 0) { 338#ifndef APPSPAWN_TEST 339 usleep(1000 * 100); // sleep 1000 * 100 microsecond 340#else 341 if (count > 0) { 342 break; 343 } 344#endif 345 count++; 346 // remind users to connect to the debugger every 60 * 10 times 347 if (count % (10 * 60) == 0) { 348 count = 0; 349 APPSPAWN_LOGI("wait for debugger, please attach the process"); 350 } 351 } 352 } 353 return 0; 354} 355 356static int SpawnInitSpawningEnv(AppSpawnMgr *content, AppSpawningCtx *property) 357{ 358 APPSPAWN_LOGV("Spawning: clear env"); 359 int ret = SetProcessName(content, property); 360 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 361 // close socket id and signal for child 362 ClearEnvironment(content, property); 363 364 ResetParamSecurityLabel(); 365 366 ret = SetAppAccessToken(content, property); 367 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 368 return 0; 369} 370 371static int SpawnSetAppEnv(AppSpawnMgr *content, AppSpawningCtx *property) 372{ 373 APPSPAWN_LOGV("Spawning: set appEnv"); 374 int ret = SetEnvInfo(content, property); 375 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 376 return 0; 377} 378 379static int SpawnSetIntPermission(AppSpawnMgr *content, AppSpawningCtx *property) 380{ 381 APPSPAWN_LOGV("Spawning: set Internet Permission for app process"); 382 int ret = SetInternetPermission(property); 383 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 384 return ret; 385} 386 387static void SpawnLoadSilk(const AppSpawnMgr *content, const AppSpawningCtx *property) 388{ 389 const char *processName = GetBundleName(property); 390 APPSPAWN_CHECK(processName != NULL, return, "Can not get bundle name"); 391 LoadSilkLibrary(processName); 392} 393 394static int SpawnSetProperties(AppSpawnMgr *content, AppSpawningCtx *property) 395{ 396 APPSPAWN_LOGV("Spawning: set child property"); 397 SpawnLoadSilk(content, property); 398 (void)umask(DEFAULT_UMASK); 399 int ret = SetKeepCapabilities(content, property); 400 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 401 ret = SetXpmConfig(content, property); 402 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 403 404 ret = SetProcessName(content, property); 405 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 406 407 ret = SetUidGid(content, property); 408 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 409 410 ret = SetFileDescriptors(content, property); 411 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 412 413 ret = SetCapabilities(content, property); 414 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 415 416 ret = SetSelinuxCon(content, property) == -1; 417 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 418 419 ret = WaitForDebugger(property); 420 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 421 422 APPSPAWN_ONLY_EXPER(GetAppSpawnMsgType(property) == MSG_SPAWN_NATIVE_PROCESS, return 0); 423#ifdef SECURITY_COMPONENT_ENABLE 424 InitSecCompClientEnhance(); 425#endif 426 return 0; 427} 428 429static int PreLoadSetSeccompFilter(AppSpawnMgr *content) 430{ 431 // set uid gid filetr 432 int ret = SetUidGidFilter(content); 433 APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); 434 return ret; 435} 436 437static int SpawnComplete(AppSpawnMgr *content, AppSpawningCtx *property) 438{ 439 InitDebugParams(content, property); 440 return 0; 441} 442 443static int CheckEnabled(const char *param, const char *value) 444{ 445 char tmp[32] = {0}; // 32 max 446 int ret = GetParameter(param, "", tmp, sizeof(tmp)); 447 APPSPAWN_LOGV("CheckEnabled key %{public}s ret %{public}d result: %{public}s", param, ret, tmp); 448 int enabled = (ret > 0 && strcmp(tmp, value) == 0); 449 return enabled; 450} 451 452static int SpawnGetSpawningFlag(AppSpawnMgr *content, AppSpawningCtx *property) 453{ 454 APPSPAWN_LOGV("Spawning: prepare app %{public}s", GetProcessName(property)); 455 if (CheckAppMsgFlagsSet(property, APP_FLAGS_COLD_BOOT)) { 456 // check cold start 457 property->client.flags |= CheckEnabled("startup.appspawn.cold.boot", "true") ? APP_COLD_START : 0; 458 } 459 if (CheckAppMsgFlagsSet(property, APP_FLAGS_BEGETCTL_BOOT)) { 460 // Start app from begetctl for debugging. 461 property->client.flags |= APP_BEGETCTL_BOOT; 462 APPSPAWN_LOGI("Spawning: prepare app %{public}s, start from begetctl", GetProcessName(property)); 463 } 464 property->client.flags |= content->flags; 465 return 0; 466} 467 468static int SpawnLoadConfig(AppSpawnMgr *content) 469{ 470 LoadSilkConfig(); 471 // init flags that will not change until next reboot 472 content->flags |= CheckEnabled("const.security.developermode.state", "true") ? APP_DEVELOPER_MODE : 0; 473 content->flags |= CheckEnabled("persist.security.jitfort.disabled", "true") ? 0 : APP_JITFORT_MODE; 474 return 0; 475} 476 477static int CloseFdArgs(AppSpawnMgr *content, AppSpawningCtx *property) 478{ 479 APPSPAWN_CHECK(property != NULL && property->message != NULL 480 && property->message->connection != NULL, 481 return -1, "Get connection info failed"); 482 int fdCount = property->message->connection->receiverCtx.fdCount; 483 int *fds = property->message->connection->receiverCtx.fds; 484 if (fds != NULL && fdCount > 0) { 485 for (int i = 0; i < fdCount; i++) { 486 if (fds[i] > 0) { 487 close(fds[i]); 488 } 489 } 490 } 491 property->message->connection->receiverCtx.fdCount = 0; 492 return 0; 493} 494 495APPSPAWN_STATIC int SetFdEnv(AppSpawnMgr *content, AppSpawningCtx *property) 496{ 497 APPSPAWN_CHECK_ONLY_EXPER(property != NULL, return -1); 498 APPSPAWN_CHECK_ONLY_EXPER(!property->isPrefork, return 0); 499 AppSpawnMsgNode *message = property->message; 500 APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL && message->connection != NULL, return -1); 501 APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset != NULL, return -1); 502 int findFdIndex = 0; 503 AppSpawnMsgReceiverCtx recvCtx = message->connection->receiverCtx; 504 APPSPAWN_CHECK(recvCtx.fds != NULL && recvCtx.fdCount > 0, return 0, 505 "no need set fd info %{public}d, %{public}d", recvCtx.fds != NULL, recvCtx.fdCount); 506 char keyBuffer[APP_FDNAME_MAXLEN + sizeof(APP_FDENV_PREFIX)]; 507 char value[sizeof(int)]; 508 509 for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) { 510 if (message->tlvOffset[index] == INVALID_OFFSET) { 511 return -1; 512 } 513 uint8_t *data = message->buffer + message->tlvOffset[index]; 514 if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) { 515 continue; 516 } 517 AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data; 518 if (strcmp(tlv->tlvName, MSG_EXT_NAME_APP_FD) != 0) { 519 continue; 520 } 521 APPSPAWN_CHECK(findFdIndex < recvCtx.fdCount && recvCtx.fds[findFdIndex] > 0, return -1, 522 "check set env args failed %{public}d, %{public}d, %{public}d", 523 findFdIndex, recvCtx.fdCount, recvCtx.fds[findFdIndex]); 524 APPSPAWN_CHECK(snprintf_s(keyBuffer, sizeof(keyBuffer), sizeof(keyBuffer) - 1, APP_FDENV_PREFIX"%s", 525 data + sizeof(AppSpawnTlvExt)) >= 0, return -1, "failed print env key %{public}d", errno); 526 APPSPAWN_CHECK(snprintf_s(value, sizeof(value), sizeof(value) - 1, 527 "%d", recvCtx.fds[findFdIndex++]) >= 0, return -1, "failed print env key %{public}d", errno); 528 int ret = setenv(keyBuffer, value, 1); 529 APPSPAWN_CHECK(ret == 0, return -1, "failed setenv %{public}s, %{public}s", keyBuffer, value); 530 if (findFdIndex >= recvCtx.fdCount) { 531 break; 532 } 533 } 534 return 0; 535} 536 537MODULE_CONSTRUCTOR(void) 538{ 539 APPSPAWN_LOGV("Load common module ..."); 540 AddPreloadHook(HOOK_PRIO_COMMON, PreLoadSetSeccompFilter); 541 AddPreloadHook(HOOK_PRIO_COMMON, SpawnLoadConfig); 542 543 AddAppSpawnHook(STAGE_PARENT_PRE_FORK, HOOK_PRIO_HIGHEST, SpawnGetSpawningFlag); 544 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SpawnInitSpawningEnv); 545 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_COMMON + 1, SpawnSetAppEnv); 546 AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_HIGHEST, SpawnSetIntPermission); 547 AddAppSpawnHook(STAGE_CHILD_EXECUTE, HOOK_PRIO_PROPERTY, SpawnSetProperties); 548 AddAppSpawnHook(STAGE_CHILD_POST_RELY, HOOK_PRIO_HIGHEST, SpawnComplete); 549 AddAppSpawnHook(STAGE_PARENT_POST_FORK, HOOK_PRIO_HIGHEST, CloseFdArgs); 550 AddAppSpawnHook(STAGE_CHILD_PRE_COLDBOOT, HOOK_PRIO_HIGHEST, SetFdEnv); 551} 552