diff --git a/hisysevent.yaml b/hisysevent.yaml index 38bcc4645907ba9c3c4bb41f214e6da1a9f306ae..10df09ac4c3c8e1f24ba15ab58a54c1045032d8a 100644 --- a/hisysevent.yaml +++ b/hisysevent.yaml @@ -17,6 +17,13 @@ SPAWN_CHILD_PROCESS_FAIL: __BASE: {type: FAULT, level: CRITICAL, desc: Spawn Child Process Fail} PROCESS_NAME: {type: STRING, desc: Process Name} ERROR_CODE: {type: INT32, desc: Error Code} + SRC_PATH : {type: STRING, desc: Source Path For Mount Failed} + TARGET_PATH: {type: STRING, desc: Target Path For Mount Failed} + SPAWN_RESULT : {type: INT32, desc: Process Spawn Result} + +SPAWN_KEY_EVENT: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Spawn Key Event Finish} + EVENT_NAME: {type: STRING, desc: Event Name} SPAWN_PROCESS_DURATION: __BASE: {type: STATISTIC, level: CRITICAL, desc: Boot Process Duration} @@ -24,4 +31,9 @@ SPAWN_PROCESS_DURATION: MINDURATION: {type: INT64, desc: Min Spawn Process Duration} TOTALDURATION: {type: INT64, desc: Total Spawn Process Duration} EVENTCOUNT: {type: INT64, desc: Total Spawn Process Count} - STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} \ No newline at end of file + STAGE: {type: STRING, desc: Boot Stage Or BootFinished Stage} + +SPAWN_ABNORMAL_DURATION: + __BASE: {type: BEHAVIOR, level: CRITICAL, desc: Scene Duration} + SCENE_NAME: {type: STRING, desc: Scene Name} + DURATION: {type: INT64, desc: Scene Duration} \ No newline at end of file diff --git a/modules/common/BUILD.gn b/modules/common/BUILD.gn index 41c028f05e43bc3660593add8a1b1116fe1ced01..a8441284e6a382e00e7405c7acd3995d671530cf 100644 --- a/modules/common/BUILD.gn +++ b/modules/common/BUILD.gn @@ -84,6 +84,12 @@ ohos_shared_library("appspawn_common") { if (appspawn_allow_internet_permission) { defines += [ "APPSPAWN_ALLOW_INTERNET_PERMISSION" ] } + if (appspawn_report_event) { + defines += [ "APPSPAWN_HISYSEVENT" ] + external_deps += [ "hisysevent:libhisysevent" ] + include_dirs += [ "${appspawn_path}/modules/sysevent" ] + sources += [ "${appspawn_path}/modules/sysevent/hisysevent_adapter.cpp" ] + } subsystem_name = "${subsystem_name}" part_name = "${part_name}" diff --git a/modules/sandbox/BUILD.gn b/modules/sandbox/BUILD.gn index 5a7d2d2c7188861dbf3efcf98882ee7119cd8f66..37fb9c8095381ccdafa424dbf1c2135e3719a024 100644 --- a/modules/sandbox/BUILD.gn +++ b/modules/sandbox/BUILD.gn @@ -80,6 +80,7 @@ if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { "appspawn_permission.c", "sandbox_shared_mount.cpp", "sandbox_utils.cpp", + "${appspawn_path}/common/appspawn_trace.cpp" ] include_dirs = [ @@ -102,6 +103,7 @@ if (defined(appspawn_sandbox_new) && appspawn_sandbox_new) { "c_utils:utils", "config_policy:configpolicy_util", "hilog:libhilog", + "hitrace:hitrace_meter", "init:libbegetutil", "json:nlohmann_json_static", ] diff --git a/modules/sandbox/sandbox_utils.cpp b/modules/sandbox/sandbox_utils.cpp index fccbb286348d700915bc89201599744a3ce159f8..ce6e9a59c18c8cb254e4a7e8cbdf7cb2d0aef3bc 100644 --- a/modules/sandbox/sandbox_utils.cpp +++ b/modules/sandbox/sandbox_utils.cpp @@ -44,6 +44,7 @@ #include "parameter.h" #include "parameters.h" #include "securec.h" +#include "appspawn_trace.h" #ifdef APPSPAWN_HISYSEVENT #include "hisysevent_adapter.h" #endif @@ -225,6 +226,39 @@ static void MakeDirRecursive(const std::string &path, mode_t mode) } while (index < size); } +static void MakeDirRecursiveWithClock(const std::string &path, mode_t mode) +{ + StartAppspawnTrace("MakeDirRecursive"); + size_t size = path.size(); + if (size == 0) { + return; + } +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif + size_t index = 0; + do { + size_t pathIndex = path.find_first_of('/', index); + index = pathIndex == std::string::npos ? size : pathIndex + 1; + std::string dir = path.substr(0, index); +#ifndef APPSPAWN_TEST + APPSPAWN_CHECK(!(access(dir.c_str(), F_OK) < 0 && mkdir(dir.c_str(), mode) < 0), + return, "errno is %{public}d, mkdir %{public}s failed", errno, dir.c_str()); +#endif + } while (index < size); + +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, + ReportAbnormalDuration("MakeDirRecursive", diff)); +#endif + FinishAppspawnTrace(); +} + static bool CheckDirRecursive(const std::string &path) { size_t size = path.size(); @@ -308,6 +342,9 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char * clock_gettime(CLOCK_MONOTONIC_COARSE, &mountEnd); uint64_t diff = DiffTime(&mountStart, &mountEnd); APPSPAWN_CHECK_ONLY_LOG(diff < MAX_MOUNT_TIME, "mount %{public}s time %{public}" PRId64 " us", originPath, diff); +#ifdef APPSPAWN_HISYSEVENT + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("MOUNT", diff)); +#endif if (ret != 0) { APPSPAWN_LOGI("errno is: %{public}d, bind mount %{public}s to %{public}s", errno, originPath, destinationPath); std::string originPathStr = originPath == nullptr ? "" : originPath; @@ -884,6 +921,10 @@ int SandboxUtils::DoAllMntPointsMount(const AppSpawningCtx *appProperty, if (actionStatus == g_statusCheck) { APPSPAWN_LOGE("DoAppSandboxMountOnce section %{public}s failed, %{public}s", section.c_str(), sandboxPath.c_str()); +#ifdef APPSPAWN_HISYSEVENT + ReportMountFail(bundleName.c_str(), srcPath.c_str(), sandboxPath.c_str(), errno); + ret = APPSPAWN_SANDBOX_MOUNT_FAIL; +#endif return ret; } } @@ -1198,6 +1239,7 @@ int32_t SandboxUtils::SetPrivateAppSandboxProperty(const AppSpawningCtx *appProp static bool GetSandboxPrivateSharedStatus(const string &bundleName, AppSpawningCtx *appProperty) { + StartAppspawnTrace("GetSandboxPrivateSharedStatus"); bool result = false; SandboxConfigType type = CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? SANBOX_ISOLATED_JSON_CONFIG : SANBOX_APP_JSON_CONFIG; @@ -1214,6 +1256,7 @@ static bool GetSandboxPrivateSharedStatus(const string &bundleName, AppSpawningC } } } + FinishAppspawnTrace(); return result; } @@ -1646,15 +1689,27 @@ int32_t SandboxUtils::ChangeCurrentDir(std::string &sandboxPackagePath, const st return ret; } -static inline int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) +static int EnableSandboxNamespace(AppSpawningCtx *appProperty, uint32_t sandboxNsFlags) { + StartAppspawnTrace("EnableSandboxNamespace"); +#ifdef APPSPAWN_HISYSEVENT + struct timespec startClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &startClock); +#endif int rc = unshare(sandboxNsFlags); +#ifdef APPSPAWN_HISYSEVENT + struct timespec endClock = {0}; + clock_gettime(CLOCK_MONOTONIC, &endClock); + uint64_t diff = DiffTime(&startClock, &endClock); + APPSPAWN_CHECK_ONLY_EXPER(diff < FUNC_REPORT_DURATION, ReportAbnormalDuration("unshare", diff)); +#endif APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", GetBundleName(appProperty)); if ((sandboxNsFlags & CLONE_NEWNET) == CLONE_NEWNET) { rc = EnableNewNetNamespace(); APPSPAWN_CHECK(rc == 0, return rc, "Set new netnamespace failed %{public}s", GetBundleName(appProperty)); } + FinishAppspawnTrace(); return 0; } @@ -1727,18 +1782,17 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_ ACCESS_DLP_FILE_MODE.c_str()))) != 0); sandboxPackagePath += CheckAppMsgFlagsSet(appProperty, APP_FLAGS_ISOLATED_SANDBOX_TYPE) ? "isolated/" : ""; sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str()); - if (UpdatePermissionFlags(appProperty) != 0) { APPSPAWN_LOGW("Set app permission flag fail."); return -1; } UpdateMsgFlagsWithPermission(appProperty); - + StartAppspawnTrace("DoSandboxRootFolderCreate"); // check app sandbox switch if ((CheckTotalSandboxSwitchStatus(appProperty) == false) || (CheckAppSandboxSwitchStatus(appProperty) == false)) { @@ -1746,6 +1800,7 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawningCtx *appProperty, uint32_ } else if (!sandboxSharedStatus) { rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath); } + FinishAppspawnTrace(); APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str()); rc = SetSandboxProperty(appProperty, sandboxPackagePath); APPSPAWN_CHECK(rc == 0, return rc, "SetSandboxProperty failed, %{public}s", bundleName.c_str()); @@ -1775,7 +1830,7 @@ int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawningCtx *appProperty, uin const std::string bundleName = GetBundleName(appProperty); bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName, appProperty); sandboxPackagePath += bundleName; - MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); + MakeDirRecursiveWithClock(sandboxPackagePath.c_str(), FILE_MODE); // add pid to a new mnt namespace int rc = EnableSandboxNamespace(appProperty, sandboxNsFlags); diff --git a/modules/sysevent/hisysevent_adapter.cpp b/modules/sysevent/hisysevent_adapter.cpp index 8e1dbad17a42251afd35f8ab1d8ed84fb044b0b0..78711cf7444787a7a03c1ba41571e0dad4c07cd2 100644 --- a/modules/sysevent/hisysevent_adapter.cpp +++ b/modules/sysevent/hisysevent_adapter.cpp @@ -19,13 +19,28 @@ using namespace OHOS::HiviewDFX; namespace { -// event -constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; +// fail event constexpr const char* SPAWN_CHILD_PROCESS_FAIL = "SPAWN_CHILD_PROCESS_FAIL"; +// behavior event +constexpr const char* SPAWN_KEY_EVENT = "SPAWN_KEY_EVENT"; +constexpr const char* SPAWN_ABNORMAL_DURATION = "SPAWN_ABNORMAL_DURATION"; + +// statistic event +constexpr const char* SPAWN_PROCESS_DURATION = "SPAWN_PROCESS_DURATION"; + // param constexpr const char* PROCESS_NAME = "PROCESS_NAME"; constexpr const char* ERROR_CODE = "ERROR_CODE"; +constexpr const char* SPAWN_RESULT = "SPAWN_RESULT"; +constexpr const char* SRC_PATH = "SRC_PATH"; +constexpr const char* TARGET_PATH = "TARGET_PATH"; + +constexpr const char* EVENT_NAME = "EVENT_NAME"; + +constexpr const char* SCENE_NAME = "SCENE_NAME"; +constexpr const char* DURATION = "DURATION"; + constexpr const char* MAXDURATION = "MAXDURATION"; constexpr const char* MINDURATION = "MINDURATION"; constexpr const char* TOTALDURATION = "TOTALDURATION"; @@ -121,14 +136,60 @@ AppSpawnHisyseventInfo *InitHisyseventTimer(void) return hisyseventInfo; } -void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode) +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult) { + if (spawnResult == APPSPAWN_SANDBOX_MOUNT_FAIL) { + return; + } int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, HiSysEvent::EventType::FAULT, PROCESS_NAME, processName, - ERROR_CODE, errorCode); + ERROR_CODE, errorCode, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportSpawnChildProcessFail error, ret: %{public}d", ret); + } +} + +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult) +{ + if (srcPath == nullptr || (strstr(srcPath, "data/app/el1/") == nullptr && + strstr(srcPath, "data/app/el2/") == nullptr)) { + return; + } + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_CHILD_PROCESS_FAIL, + HiSysEvent::EventType::FAULT, + PROCESS_NAME, bundleName, + ERROR_CODE, ERR_APPSPAWN_CHILD_MOUNT_FAILED, + SRC_PATH, srcPath, + TARGET_PATH, targetPath, + SPAWN_RESULT, spawnResult); + if (ret != 0) { + APPSPAWN_LOGE("ReportMountFail error, ret: %{public}d", ret); + } +} + +void ReportKeyEvent(const char *eventName) +{ + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_KEY_EVENT, + HiSysEvent::EventType::BEHAVIOR, + EVENT_NAME, eventName); + if (ret != 0) { + APPSPAWN_LOGE("ReportKeyEvent error, ret: %{public}d", ret); + } +} + +void ReportAbnormalDuration(const char* scene, uint64_t duration) +{ + APPSPAWN_LOGI("ReportAbnormalDuration %{public}d with %{public}s %{public}" PRId64 " us", + getpid(), scene, duration); + int ret = HiSysEventWrite(HiSysEvent::Domain::APPSPAWN, SPAWN_ABNORMAL_DURATION, + HiSysEvent::EventType::BEHAVIOR, + SCENE_NAME, scene, + DURATION, duration); if (ret != 0) { - APPSPAWN_LOGE("HiSysEventWrite error, ret: %{public}d", ret); + APPSPAWN_LOGE("ReportAbnormalDuration error, ret: %{public}d", ret); } } @@ -142,7 +203,7 @@ void ReportSpawnProcessDuration(AppSpawnHisysevent *hisysevent, const char* stag EVENTCOUNT, hisysevent->eventCount, STAGE, stage); if (ret != 0) { - APPSPAWN_LOGE("HiSysEventWrite error, ret: %{public}d", ret); + APPSPAWN_LOGE("ReportSpawnProcessDuration error, ret: %{public}d", ret); } } diff --git a/modules/sysevent/hisysevent_adapter.h b/modules/sysevent/hisysevent_adapter.h index 89f3fbacc5889a3a81a2edd6a9d75d801a29cb68..1e9fb62e6164c4b1cd8a3253e6b5836f6f964e9a 100644 --- a/modules/sysevent/hisysevent_adapter.h +++ b/modules/sysevent/hisysevent_adapter.h @@ -73,6 +73,7 @@ typedef enum { ERR_APPSPAWN_SPAWN_FAIL = ERR_APPSPAWN_BASE + 0x0381, ERR_APPSPAWN_SPAWN_TIMEOUT, ERR_APPSPAWN_CHILD_CRASH, + ERR_APPSPAWN_CHILD_MOUNT_FAILED, ERR_APPSPAWN_MAX_FAILURES_EXCEEDED, } AppSpawnHisysErrorCode; @@ -88,12 +89,23 @@ typedef struct { AppSpawnHisysevent manualEvent; // bootFinished } AppSpawnHisyseventInfo; +#define FUNC_REPORT_DURATION (20 * 1000) +#define SPAWN_DURATION (120 * 1000) +#define SPAWN_COLDRUN_DURATION (5 * 1000 * 1000) + +#define UNLOCK_SUCCESS "UNLOCK_SUCCESS" +#define LOCK_SUCCESS "LOCK_SUCCESS" +#define APPSPAWN_MAX_FAILURES_EXCEEDED "APPSPAWN_MAX_FAILURES_EXCEEDED" AppSpawnHisyseventInfo *InitHisyseventTimer(void); AppSpawnHisyseventInfo *GetAppSpawnHisyseventInfo(void); void AddStatisticEventInfo(AppSpawnHisyseventInfo *hisyseventInfo, uint32_t duration, bool stage); void DeleteHisyseventInfo(AppSpawnHisyseventInfo *hisyseventInfo); -void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode); +void ReportSpawnChildProcessFail(const char* processName, int32_t errorCode, int32_t spawnResult); +void ReportMountFail(const char* bundleName, const char* srcPath, const char* targetPath, + int32_t spawnResult); +void ReportKeyEvent(const char *eventName); +void ReportAbnormalDuration(const char* funcName, uint64_t duration); void ReportSpawnStatisticDuration(const TimerHandle taskHandle, void* content); #ifdef __cplusplus diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 1764d93c5eef9cb6a16f8e16224524401cf8a8d9..6ed135e6ff42eb97c748491ad0939e46a76fc346 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -943,7 +943,7 @@ static void WaitChildDied(pid_t pid) APPSPAWN_LOGI("Child process %{public}s fail \'child crash \'pid %{public}d appId: %{public}d", processName, property->pid, property->client.id); #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH); + ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_CHILD_CRASH, APPSPAWN_CHILD_CRASH); #endif if (property->client.id == g_lastDiedAppId + 1) { g_crashTimes++; @@ -958,7 +958,7 @@ static void WaitChildDied(pid_t pid) if (g_crashTimes >= MAX_CRASH_TIME) { APPSPAWN_LOGW("Continuous failures in spawning the app, restart appspawn"); #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(processName, ERR_APPSPAWN_MAX_FAILURES_EXCEEDED); + ReportKeyEvent(APPSPAWN_MAX_FAILURES_EXCEEDED); #endif StopAppSpawn(); } @@ -977,7 +977,7 @@ static void WaitChildTimeout(const TimerHandle taskHandle, void *context) kill(property->pid, SIGKILL); } #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT); + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_TIMEOUT, APPSPAWN_SPAWN_TIMEOUT); #endif SendResponse(property->message->connection, &property->message->msgHeader, APPSPAWN_SPAWN_TIMEOUT, 0); DeleteAppSpawningCtx(property); @@ -993,7 +993,7 @@ static int ProcessChildFdCheck(int fd, AppSpawningCtx *property) if (result != 0) { #ifdef APPSPAWN_HISYSEVENT - ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL); + ReportSpawnChildProcessFail(GetProcessName(property), ERR_APPSPAWN_SPAWN_FAIL, result); #endif SendResponse(property->message->connection, &property->message->msgHeader, result, property->pid); DeleteAppSpawningCtx(property); @@ -1038,6 +1038,11 @@ static void ProcessChildResponse(const WatcherHandle taskHandle, int fd, uint32_ if (appspawnMgr != NULL) { AddStatisticEventInfo(appspawnMgr->hisyseventInfo, spawnProcessDuration, IsBootFinished()); } +#ifndef ASAN_DETECTOR + uint64_t diff = DiffTime(&appInfo->spawnStart, &appInfo->spawnEnd); + APPSPAWN_CHECK_ONLY_EXPER(diff < (IsChildColdRun(property) ? SPAWN_COLDRUN_DURATION : SPAWN_DURATION), + ReportAbnormalDuration("SPAWNCHILD", diff)); +#endif #endif } @@ -1685,6 +1690,9 @@ static void ProcessAppSpawnLockStatusMsg(AppSpawnMsgNode *message) APPSPAWN_CHECK(ret > 0, return, "get lock status param failed, errno %{public}d", errno); ret = SetParameter(lockStatusParam, userLockStatus); APPSPAWN_CHECK(ret == 0, return, "failed to set lockstatus param value ret %{public}d", ret); +#ifdef APPSPAWN_HISYSEVENT + ReportKeyEvent(strcmp(userLockStatus, "0") == 0 ? UNLOCK_SUCCESS : LOCK_SUCCESS); +#endif #ifndef APPSPAWN_SANDBOX_NEW if (strcmp(userLockStatus, "0") == 0) { ServerStageHookExecute(STAGE_SERVER_LOCK, GetAppSpawnContent());