diff --git a/adapter/appspawn_ace.cpp b/adapter/appspawn_ace.cpp index 9d72b673..57049ced 100644 --- a/adapter/appspawn_ace.cpp +++ b/adapter/appspawn_ace.cpp @@ -117,7 +117,14 @@ void LoadExtendLib(AppSpawnContent *content) void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) { - APPSPAWN_LOGI("AppExecFwk::MainThread::Start"); + APPSPAWN_CHECK(client != NULL && content != NULL, return, "Invalid client"); + AppSpawnClientExt *appProperty = reinterpret_cast(client); + if (appProperty->property.code == SPAWN_NATIVE_PROCESS) { + APPSPAWN_LOGI("renderCmd %{public}s", appProperty->property.renderCmd); + (void)system(appProperty->property.renderCmd); + return; + } + APPSPAWN_LOGI("LoadExtendLib: RunChildProcessor"); #ifndef APPSPAWN_TEST OHOS::AppExecFwk::MainThread::Start(); #endif diff --git a/adapter/appspawn_adapter.cpp b/adapter/appspawn_adapter.cpp index e6a6ab59..d5ab4eb8 100644 --- a/adapter/appspawn_adapter.cpp +++ b/adapter/appspawn_adapter.cpp @@ -94,8 +94,8 @@ void HandleInternetPermission(const AppSpawnClient *client) { AppSpawnClientExt *appPropertyExt = (AppSpawnClientExt *)client; APPSPAWN_LOGV("HandleInternetPermission id %{public}d setAllowInternet %hhu allowInternet %hhu", - client->id, appPropertyExt->setAllowInternet, appPropertyExt->allowInternet); - if (appPropertyExt->setAllowInternet == 1 && appPropertyExt->allowInternet == 0) { + client->id, appPropertyExt->property.setAllowInternet, appPropertyExt->property.allowInternet); + if (appPropertyExt->property.setAllowInternet == 1 && appPropertyExt->property.allowInternet == 0) { DisallowInternet(); } } diff --git a/adapter/appspawn_adapter.h b/adapter/appspawn_adapter.h index f6782368..af5f0333 100644 --- a/adapter/appspawn_adapter.h +++ b/adapter/appspawn_adapter.h @@ -29,8 +29,6 @@ void SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client) void SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client); void LoadExtendLib(AppSpawnContent *content); void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); -int GetRenderProcessTerminationStatus(int32_t pid, int *status); -void RecordRenderProcessExitedStatus(pid_t pid, int status); void LoadAppSandboxConfig(void); void SetUidGidFilter(struct AppSpawnContent_ *content); int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client); @@ -38,6 +36,9 @@ uint32_t GetAppNamespaceFlags(const char *bundleName); void HandleInternetPermission(const AppSpawnClient *client); void DisallowInternet(void); + +void RecordRenderProcessExitedStatus(pid_t pid, int status); +int GetProcessTerminationStatus(AppSpawnClient *client); #ifdef __cplusplus } #endif diff --git a/adapter/appspawn_nweb.cpp b/adapter/appspawn_nweb.cpp index 63b77f85..2fff2b63 100644 --- a/adapter/appspawn_nweb.cpp +++ b/adapter/appspawn_nweb.cpp @@ -13,7 +13,11 @@ * limitations under the License. */ +#include #include +#include +#include +#include #include #include @@ -66,7 +70,7 @@ void *LoadWithRelroFile(const std::string &lib, const std::string &nsName, APPSPAWN_LOGE("LoadWithRelroFile open failed, error=[%{public}s]", strerror(tmpNo)); return nullptr; } - void *nwebReservedAddress = mmap(NULL, nwebReservedSize, PROT_NONE, + void *nwebReservedAddress = mmap(nullptr, nwebReservedSize, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (nwebReservedAddress == MAP_FAILED) { close(relroFd); @@ -201,3 +205,40 @@ int GetRenderProcessTerminationStatus(int32_t pid, int *status) DumpRenderProcessExitedMap(); return -1; } + +static int GetProcessTerminationStatusInner(int32_t pid, int *status) +{ + if (status == nullptr) { + return -1; + } + + if (GetRenderProcessTerminationStatus(pid, status) == 0) { + // this shows that the parent process has received SIGCHLD signal. + return 0; + } + + if (kill(pid, SIGKILL) != 0) { + APPSPAWN_LOGE("unable to kill render process, pid: %d ret %d", pid, errno); + } + + pid_t exitPid = waitpid(pid, status, WNOHANG); + if (exitPid != pid) { + APPSPAWN_LOGE("waitpid failed, return : %d, pid: %d, status: %d", exitPid, pid, *status); + return -1; + } + return 0; +} + +int GetProcessTerminationStatus(AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = reinterpret_cast(client); + int exitStatus = 0; + int ret = GetProcessTerminationStatusInner(appProperty->property.pid, &exitStatus); + if (ret) { + exitStatus = ret; + } + APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s", + exitStatus, appProperty->property.pid, appProperty->property.uid, + appProperty->property.processName, appProperty->property.bundleName); + return exitStatus; +} diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index 373fe149..3329373c 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -56,16 +56,23 @@ void LoadAppSandboxConfig(void) int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) { APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); - AppSpawnClientExt *appProperty = reinterpret_cast(client); - appProperty->property.cloneFlags = client->cloneFlags; - int ret = SandboxUtils::SetAppSandboxProperty(&appProperty->property); + AppSpawnClientExt *clientExt = reinterpret_cast(client); + // no sandbox + if (clientExt->property.flags & APP_NO_SANDBOX) { + return 0; + } + // no news + if ((client->cloneFlags & CLONE_NEWNS) != CLONE_NEWNS) { + return 0; + } + int ret = SandboxUtils::SetAppSandboxProperty(client); // free HspList - if (appProperty->property.hspList.data != nullptr) { - free(appProperty->property.hspList.data); - appProperty->property.hspList = {}; + if (clientExt->property.hspList.data != nullptr) { + free(clientExt->property.hspList.data); + clientExt->property.hspList = {}; } // for module test do not create sandbox - if (strncmp(appProperty->property.bundleName, + if (strncmp(clientExt->property.bundleName, MODULE_TEST_BUNDLE_NAME.c_str(), MODULE_TEST_BUNDLE_NAME.size()) == 0) { return 0; } diff --git a/appspawn.gni b/appspawn.gni index d03da7ba..7a91d569 100644 --- a/appspawn.gni +++ b/appspawn.gni @@ -21,4 +21,5 @@ module_output_path = "${part_name}/appspawn_l2" declare_args() { appspawn_support_nweb = true appspawn_report_event = true + appspawn_test_cmd = false } diff --git a/common/appspawn_server.c b/common/appspawn_server.c index 29360bbc..fda94d77 100644 --- a/common/appspawn_server.c +++ b/common/appspawn_server.c @@ -17,14 +17,12 @@ #include #include -#include #include #include #include #undef _GNU_SOURCE #define _GNU_SOURCE #include -#include #include #include @@ -89,7 +87,7 @@ int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *l content->handleInternetPermission(client); } - if ((client->cloneFlags & CLONE_NEWNS) && (content->setAppSandbox)) { + if (content->setAppSandbox) { ret = content->setAppSandbox(content, client); APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set app sandbox"); diff --git a/common/appspawn_server.h b/common/appspawn_server.h index 3771f186..c73c7433 100644 --- a/common/appspawn_server.h +++ b/common/appspawn_server.h @@ -38,8 +38,8 @@ extern "C" { typedef struct AppSpawnClient_ { uint32_t id; - uint32_t flags; - uint32_t cloneFlags; + uint32_t flags; // Save negotiated flags + uint32_t cloneFlags; // for clone flags } AppSpawnClient; #define MAX_SOCKEYT_NAME_LEN 128 diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 476c7875..e0a473be 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -49,6 +49,7 @@ enum AppType { typedef enum AppOperateType_ { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, + SPAWN_NATIVE_PROCESS } AppOperateType; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size @@ -67,6 +68,7 @@ typedef enum AppOperateType_ { #define APP_ASANENABLED 0x10 #define APP_ACCESS_BUNDLE_DIR 0x20 #define APP_NATIVEDEBUG 0X40 +#define APP_NO_SANDBOX 0x80 // Do not enter sandbox #define BITLEN32 32 #define FDLEN2 2 @@ -79,21 +81,20 @@ typedef struct HspList_ { } HspList; typedef struct AppParameter_ { - uint32_t cloneFlags; + AppOperateType code; + uint32_t flags; + int32_t pid; // query render process exited status by render process pid uint32_t uid; // the UNIX uid that the child process setuid() to after fork() uint32_t gid; // the UNIX gid that the child process setgid() to after fork() - uint32_t gidTable[APP_MAX_GIDS]; // a list of UNIX gids that the child process setgroups() to after fork() uint32_t gidCount; // the size of gidTable + uint32_t gidTable[APP_MAX_GIDS]; // a list of UNIX gids that the child process setgroups() to after fork() char processName[APP_LEN_PROC_NAME]; // process name char bundleName[APP_LEN_BUNDLE_NAME]; // bundle name char soPath[APP_LEN_SO_PATH]; // so lib path - uint32_t accessTokenId; char apl[APP_APL_MAX_LEN]; char renderCmd[APP_RENDER_CMD_MAX_LEN]; - uint32_t flags; - int32_t pid; // query render process exited status by render process pid + uint32_t accessTokenId; int32_t bundleIndex; - AppOperateType code; uint64_t accessTokenIdEx; int32_t hapFlags; #ifndef OHOS_LITE diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index 57267dc1..901a615d 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -17,6 +17,7 @@ #include "appspawn_adapter.h" #include +#include #include #include #include @@ -211,7 +212,7 @@ int SetXpmRegion(struct AppSpawnContent_ *content) APPSPAWN_CHECK_ONLY_LOG(ret != -1, "set xpm region failed: %s", strerror(errno)); close(fd); - return ret; + return 0; } static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) @@ -409,6 +410,34 @@ static int GetWrapBundleNameValue(struct AppSpawnContent_ *content, AppSpawnClie } #endif +static int EncodeAppClient(AppSpawnClient *client, char *param, int32_t originLen) +{ + AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; + int32_t startLen = 0; + int32_t len = sprintf_s(param + startLen, originLen - startLen, "%u:%u:%u:%u:%u:%u:%u:%u:%u:%u", + client->id, client->flags, client->cloneFlags, appProperty->code, + appProperty->flags, appProperty->uid, appProperty->gid, + appProperty->setAllowInternet, appProperty->allowInternet, appProperty->gidCount); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format"); + startLen += len; + for (uint32_t i = 0; i < appProperty->gidCount; i++) { + len = sprintf_s(param + startLen, originLen - startLen, ":%u", appProperty->gidTable[i]); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format gid"); + startLen += len; + } + // processName + if (appProperty->soPath[0] == '\0') { + strcpy_s(appProperty->soPath, sizeof(appProperty->soPath), "NULL"); + } + len = sprintf_s(param + startLen, originLen - startLen, ":%s:%s:%s:%u:%s:%s:%u:%" PRId64 "", + appProperty->processName, appProperty->bundleName, appProperty->soPath, + appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd, + appProperty->hapFlags, appProperty->accessTokenIdEx); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), return -1, "Invalid to format processName"); + startLen += len; + return 0; +} + static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; @@ -418,16 +447,11 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_CHECK(len > 0, return -1, "Invalid to format fd"); char **argv = calloc(1, (NULL_INDEX + 1) * sizeof(char *)); APPSPAWN_CHECK(argv != NULL, return -1, "Failed to get argv"); - - int32_t startLen = 0; - const int32_t originLen = sizeof(AppParameter) + PARAM_BUFFER_LEN; - // param - char *param = malloc(originLen + APP_LEN_PROC_NAME); - APPSPAWN_CHECK(param != NULL, free(argv); - return -1, "Failed to malloc for param"); - int ret = -1; do { + const int32_t originLen = sizeof(AppParameter) + PARAM_BUFFER_LEN; + char *param = malloc(originLen + APP_LEN_PROC_NAME); + APPSPAWN_CHECK(param != NULL, break, "Failed to malloc for param"); argv[PARAM_INDEX] = param; argv[0] = param + originLen; const char *appSpawnPath = "/system/bin/appspawn"; @@ -443,32 +467,13 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup"); argv[FD_INDEX] = strdup(buffer); APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup"); - - len = sprintf_s(param + startLen, originLen - startLen, "%u:%u:%u:%u:%u", - ((AppSpawnClientExt *)client)->client.id, ((AppSpawnClientExt *)client)->client.cloneFlags, - appProperty->uid, appProperty->gid, appProperty->gidCount); - APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format"); - startLen += len; - for (uint32_t i = 0; i < appProperty->gidCount; i++) { - len = sprintf_s(param + startLen, originLen - startLen, ":%u", appProperty->gidTable[i]); - APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format gid"); - startLen += len; - } - // processName - if (appProperty->soPath[0] == '\0') { - strcpy_s(appProperty->soPath, sizeof(appProperty->soPath), "NULL"); - } - len = sprintf_s(param + startLen, originLen - startLen, ":%s:%s:%s:%u:%s:%s", - appProperty->processName, appProperty->bundleName, appProperty->soPath, - appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd); - APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format processName"); - startLen += len; + ret = EncodeAppClient(client, param, originLen); + APPSPAWN_CHECK(ret == 0, break, "Failed to encode client"); len = sprintf_s(buffer, sizeof(buffer), "%u", appProperty->hspList.totalLength); - APPSPAWN_CHECK(len > 0 && len < sizeof(buffer), break, "Invalid hspList.totalLength"); + APPSPAWN_CHECK(len > 0 && len < (int)sizeof(buffer), break, "Invalid hspList.totalLength"); argv[HSP_LIST_LEN_INDEX] = strdup(buffer); argv[HSP_LIST_INDEX] = appProperty->hspList.data; - ret = 0; } while (0); @@ -483,90 +488,94 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_LOGE("Failed to execv, errno = %{public}d", errno); } } + argv[0] = NULL; Free(argv, &appProperty->hspList); return ret; } +static int GetUInt32FromArg(char *begin, char **end, uint32_t *value) +{ + char *start = strtok_r(begin, ":", end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint32 value"); + *value = atoi(start); + return 0; +} + +static int GetUInt64FromArg(char *begin, char **end, uint64_t *value) +{ + char *start = strtok_r(begin, ":", end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uint64 value"); + APPSPAWN_LOGV("GetUInt64FromArg %{public}s ", start); + *value = atoll(start); + return 0; +} + +static int GetStringFromArg(char *begin, char **end, char *value, uint32_t valueLen) +{ + char *start = strtok_r(NULL, ":", end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get string"); + if (strcmp(start, "NULL")) { + return strcpy_s(value, valueLen, start); + } else { + value[0] = '\0'; + } + return 0; +} + int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client) { APPSPAWN_CHECK(argv != NULL && argc > PARAM_INDEX, return -1, "Invalid argv argc %{public}d", argc); - client->fd[1] = atoi(argv[FD_INDEX]); APPSPAWN_LOGV("GetAppSpawnClientFromArg %{public}s ", argv[PARAM_INDEX]); - char *end = NULL; - char *start = strtok_r(argv[PARAM_INDEX], ":", &end); - // clientid - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get client id"); - client->client.id = atoi(start); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get client cloneFlags"); - client->client.cloneFlags = atoi(start); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uid"); - client->property.uid = atoi(start); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gid"); - client->property.gid = atoi(start); - - // gidCount - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gidCount"); - client->property.gidCount = atoi(start); + char *end = NULL; + int ret = GetUInt32FromArg(argv[PARAM_INDEX], &end, &client->client.id); + ret += GetUInt32FromArg(NULL, &end, &client->client.flags); + ret += GetUInt32FromArg(NULL, &end, &client->client.cloneFlags); + ret += GetUInt32FromArg(NULL, &end, &client->property.code); + ret += GetUInt32FromArg(NULL, &end, &client->property.flags); + ret += GetUInt32FromArg(NULL, &end, &client->property.uid); + ret += GetUInt32FromArg(NULL, &end, &client->property.gid); + uint32_t value = 0; + ret += GetUInt32FromArg(NULL, &end, &value); + client->property.setAllowInternet = (uint8_t)value; + ret += GetUInt32FromArg(NULL, &end, &value); + client->property.allowInternet = (uint8_t)value; + ret += GetUInt32FromArg(NULL, &end, &client->property.gidCount); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to get client info"); for (uint32_t i = 0; i < client->property.gidCount; i++) { - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gidTable"); - client->property.gidTable[i] = atoi(start); + ret = GetUInt32FromArg(NULL, &end, &client->property.gidTable[i]); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to get gidTable"); } // processname - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get processName"); - int ret = strcpy_s(client->property.processName, sizeof(client->property.processName), start); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy processName"); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get bundleName"); - ret = strcpy_s(client->property.bundleName, sizeof(client->property.bundleName), start); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy bundleName"); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get soPath"); - if (strcmp(start, "NULL")) { - ret = strcpy_s(client->property.soPath, sizeof(client->property.soPath), start); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy soPath"); - } else { - client->property.soPath[0] = '\0'; - } + ret = GetStringFromArg(NULL, &end, client->property.processName, sizeof(client->property.processName)); + ret += GetStringFromArg(NULL, &end, client->property.bundleName, sizeof(client->property.bundleName)); + ret += GetStringFromArg(NULL, &end, client->property.soPath, sizeof(client->property.soPath)); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to get process name"); - // accesstoken - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get accessTokenId"); - client->property.accessTokenId = atoi(start); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get apl"); - ret = strcpy_s(client->property.apl, sizeof(client->property.apl), start); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy apl"); - start = strtok_r(NULL, ":", &end); - APPSPAWN_CHECK(start != NULL, return -1, "Failed to get renderCmd"); - ret = strcpy_s(client->property.renderCmd, sizeof(client->property.renderCmd), start); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy renderCmd"); + // access token + ret = GetUInt32FromArg(NULL, &end, &client->property.accessTokenId); + ret += GetStringFromArg(NULL, &end, client->property.apl, sizeof(client->property.apl)); + ret += GetStringFromArg(NULL, &end, client->property.renderCmd, sizeof(client->property.renderCmd)); + ret += GetUInt32FromArg(NULL, &end, &value); + client->property.hapFlags = (int32_t)value; + ret += GetUInt64FromArg(NULL, &end, &client->property.accessTokenIdEx); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to access token info"); - if (argc > HSP_LIST_LEN_INDEX) { - APPSPAWN_CHECK(argv[HSP_LIST_LEN_INDEX] != NULL, return -1, "Invalid HspList length"); - client->property.hspList.totalLength = atoi(argv[HSP_LIST_LEN_INDEX]); - } else { - client->property.hspList.totalLength = 0; - } + client->property.hspList.totalLength = 0; client->property.hspList.data = NULL; - - if (client->property.hspList.totalLength > 0) { - APPSPAWN_CHECK(argc > HSP_LIST_INDEX && argv[HSP_LIST_INDEX] != NULL, return -1, "Invalid argv for HspList"); + ret = -1; + if (argc > HSP_LIST_LEN_INDEX && argv[HSP_LIST_LEN_INDEX] != NULL) { + client->property.hspList.totalLength = atoi(argv[HSP_LIST_LEN_INDEX]); + APPSPAWN_CHECK_ONLY_EXPER(client->property.hspList.totalLength != 0, return 0); + APPSPAWN_CHECK(argc > HSP_LIST_INDEX && argv[HSP_LIST_INDEX] != NULL, return -1, "Invalid hspList.data"); client->property.hspList.data = malloc(client->property.hspList.totalLength); APPSPAWN_CHECK(client->property.hspList.data != NULL, return -1, "Failed to malloc hspList.data"); ret = strcpy_s(client->property.hspList.data, client->property.hspList.totalLength, argv[HSP_LIST_INDEX]); APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy hspList.data"); } - - return 0; + return ret; } void SetContentFunction(AppSpawnContent *content) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 0424f061..25ef5729 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -100,12 +100,17 @@ APPSPAWN_STATIC void ProcessTimer(const TimerHandle taskHandle, void *context) LE_StopLoop(LE_GetDefaultLoop()); } -static void RemoveAppInfo(pid_t pid) +static AppInfo *GetAppInfo(pid_t pid) { HashNode *node = OH_HashMapGet(g_appSpawnContent->appMap, (const void *)&pid); - APPSPAWN_CHECK(node != NULL, return, "Invalid node %{public}d", pid); - AppInfo *appInfo = HASHMAP_ENTRY(node, AppInfo, node); - APPSPAWN_CHECK(appInfo != NULL, return, "Invalid node %{public}d", pid); + APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return NULL); + return HASHMAP_ENTRY(node, AppInfo, node); +} + +static void RemoveAppInfo(pid_t pid) +{ + AppInfo *appInfo = GetAppInfo(pid); + APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid); OH_HashMapRemove(g_appSpawnContent->appMap, (const void *)&pid); free(appInfo); if ((g_appSpawnContent->flags & FLAGS_ON_DEMAND) != FLAGS_ON_DEMAND) { @@ -129,7 +134,16 @@ static void KillProcess(const HashNode *node, const void *context) static void OnClose(const TaskHandle taskHandle) { - UNUSED(taskHandle); + AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(taskHandle); + APPSPAWN_CHECK(client != NULL, return, "Invalid client"); + APPSPAWN_LOGI("OnClose %{public}d processName = %{public}s", + client->client.id, client->property.processName); + if (client->property.hspList.data != NULL) { + free(client->property.hspList.data); + client->property.hspList.totalLength = 0; + client->property.hspList.savedLength = 0; + client->property.hspList.data = NULL; + } } static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle) @@ -155,14 +169,10 @@ static int SendResponse(AppSpawnClientExt *client, const char *buff, size_t buff return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize); } -#ifdef REPORT_EVENT -static void PrintProcessExitInfo(pid_t pid, uid_t uid, int status) +static void HandleDiedPid(pid_t pid, uid_t uid, int status) { - HashNode *node = OH_HashMapGet(g_appSpawnContent->appMap, (const void *)&pid); - APPSPAWN_CHECK(node != NULL, return, "Handle SIGCHLD from pid:%{public}d status:%{public}d", pid, status); - AppInfo *appInfo = HASHMAP_ENTRY(node, AppInfo, node); - APPSPAWN_CHECK(appInfo != NULL, return, "Handle SIGCHLD from pid:%{public}d status:%{public}d", pid, status); - + AppInfo *appInfo = GetAppInfo(pid); + APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid); if (WIFSIGNALED(status)) { APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d", appInfo->name, pid, WTERMSIG(status)); @@ -172,21 +182,17 @@ static void PrintProcessExitInfo(pid_t pid, uid_t uid, int status) appInfo->name, pid, WEXITSTATUS(status)); } +#ifdef REPORT_EVENT ReportProcessExitInfo(appInfo->name, pid, uid, status); -} #endif -static void HandleDiedPid(pid_t pid, uid_t uid, int status) -{ - APPSPAWN_LOGI("SignalHandler pid %{public}d status %{public}d", pid, status); -#ifdef REPORT_EVENT - PrintProcessExitInfo(pid, uid, status); -#endif #ifdef NWEB_SPAWN // nwebspawn will invoke waitpid and remove appinfo at GetProcessTerminationStatusInner when // GetProcessTerminationStatusInner is called before the parent process receives the SIGCHLD signal. RecordRenderProcessExitedStatus(pid, status); #endif + + // delete app info RemoveAppInfo(pid); } @@ -276,67 +282,6 @@ static void CheckColdAppEnabled(AppSpawnClientExt *appProperty) } } -#ifdef NWEB_SPAWN -static int GetProcessTerminationStatusInner(int32_t pid, int *status) -{ - if (status == NULL) { - return -1; - } - - if (GetRenderProcessTerminationStatus(pid, status) == 0) { - // this shows that the parent process has received SIGCHLD signal. - return 0; - } - - if (kill(pid, SIGKILL) != 0) { - APPSPAWN_LOGE("unable to kill render process, pid: %{public}d", pid); - } - - pid_t exitPid = waitpid(pid, status, WNOHANG); - if (exitPid != pid) { - APPSPAWN_LOGE("waitpid failed, return : %{public}d, pid: %{public}d, status: %{public}d", - exitPid, pid, *status); - return -1; - } - - RemoveAppInfo(pid); - return 0; -} - -static void GetProcessTerminationStatus(AppSpawnClientExt *appProperty) -{ - int exitStatus = 0; - int ret = GetProcessTerminationStatusInner(appProperty->property.pid, &exitStatus); - if (ret) { - SendResponse(appProperty, (char *)&ret, sizeof(ret)); - } else { - SendResponse(appProperty, (char *)&exitStatus, sizeof(exitStatus)); - } - APPSPAWN_LOGI("AppSpawnServer::get render process termination status, \ - status = %{public}d pid = %{public}d uid %{public}d %{public}s %{public}s", - exitStatus, appProperty->property.pid, appProperty->property.uid, - appProperty->property.processName, appProperty->property.bundleName); -} -#endif - -static void SetInternetPermission(AppSpawnClientExt *appProperty) -{ - if (appProperty->property.setAllowInternet == 1 && appProperty->property.allowInternet == 0) { - appProperty->setAllowInternet = 1; - appProperty->allowInternet = 0; - } -} - -static void FreeHspList(AppSpawnClientExt *client) -{ - if (client != NULL && client->property.hspList.data != NULL) { - free(client->property.hspList.data); - client->property.hspList.totalLength = 0; - client->property.hspList.savedLength = 0; - client->property.hspList.data = NULL; - } -} - APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client, const uint8_t *buffer, uint32_t buffLen) { @@ -375,8 +320,8 @@ APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnCli HspList *hspList = &client->property.hspList; if (hspList->savedLength == 0) { hspList->data = (char *)malloc(hspList->totalLength); - APPSPAWN_CHECK(hspList->data != NULL, FreeHspList(client); LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: malloc hspList failed"); + APPSPAWN_CHECK(hspList->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: malloc hspList failed %{public}u", hspList->totalLength); } uint32_t saved = hspList->savedLength; @@ -385,12 +330,12 @@ APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnCli APPSPAWN_LOGV("Receiving hspList: (%{public}u saved + %{public}u incoming) / %{public}u total", saved, buffLen, total); - APPSPAWN_CHECK((total - saved) >= buffLen, FreeHspList(client); LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: too many data for hspList %{public}u ", buffLen); + APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: too many data for hspList %{public}u ", buffLen); int ret = memcpy_s(data + saved, buffLen, buffer, buffLen); - APPSPAWN_CHECK(ret == 0, FreeHspList(client); LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: memcpy hspList failed"); + APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: memcpy hspList failed"); hspList->savedLength += buffLen; if (hspList->savedLength < hspList->totalLength) { @@ -401,6 +346,38 @@ APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnCli return true; } +static int HandleMessage(AppSpawnClientExt *appProperty) +{ + // create pipe + if (pipe(appProperty->fd) == -1) { + APPSPAWN_LOGE("create pipe fail, errno = %{public}d", errno); + return -1; + } + fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); + /* Clone support only one parameter, so need to package application parameters */ + AppSandboxArg sandboxArg = { 0 }; + sandboxArg.content = &g_appSpawnContent->content; + sandboxArg.client = &appProperty->client; + sandboxArg.client->cloneFlags = GetAppNamespaceFlags(appProperty->property.bundleName); + + SHOW_CLIENT("Receive client message ", appProperty); + int result = AppSpawnProcessMsg(&sandboxArg, &appProperty->pid); + if (result == 0) { // wait child process result + result = WaitChild(appProperty->fd[0], appProperty->pid, appProperty); + } + close(appProperty->fd[0]); + close(appProperty->fd[1]); + APPSPAWN_LOGI("child process %{public}s %{public}s pid %{public}d", + appProperty->property.processName, (result == 0) ? "success" : "fail", appProperty->pid); + if (result == 0) { + AddAppInfo(appProperty->pid, appProperty->property.processName); + SendResponse(appProperty, (char *)&appProperty->pid, sizeof(appProperty->pid)); + } else { + SendResponse(appProperty, (char *)&result, sizeof(result)); + } + return 0; +} + static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) { AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle); @@ -414,56 +391,29 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, #ifdef NWEB_SPAWN // get render process termination status, only nwebspawn need this logic. if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) { - GetProcessTerminationStatus(appProperty); + int ret = GetProcessTerminationStatus(&appProperty->client); + RemoveAppInfo(appProperty->property.pid); + SendResponse(appProperty, (char *)&ret, sizeof(ret)); return; } #endif APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0, - LE_CloseTask(LE_GetDefaultLoop(), taskHandle); FreeHspList(appProperty); + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); return, "Invalid property %{public}u", appProperty->property.gidCount); + // special handle bundle name medialibrary and scanner HandleSpecial(appProperty); - SetInternetPermission(appProperty); if (g_appSpawnContent->timer != NULL) { LE_StopTimer(LE_GetDefaultLoop(), g_appSpawnContent->timer); g_appSpawnContent->timer = NULL; } appProperty->pid = 0; CheckColdAppEnabled(appProperty); - // create pipe for commication from child - if (pipe(appProperty->fd) == -1) { - APPSPAWN_LOGE("create pipe fail, errno = %{public}d", errno); + int ret = HandleMessage(appProperty); + if (ret != 0) { LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - FreeHspList(appProperty); - return; } - - APPSPAWN_LOGI("Client.id %{public}d appProperty %{public}d processname %{public}s buffLen %{public}d flags 0x%x", - appProperty->client.id, appProperty->property.uid, appProperty->property.processName, - buffLen, appProperty->property.flags); - fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); - - /* Clone support only one parameter, so need to package application parameters */ - AppSandboxArg sandboxArg = { 0 }; - sandboxArg.content = &g_appSpawnContent->content; - sandboxArg.client = &appProperty->client; - sandboxArg.client->cloneFlags = GetAppNamespaceFlags(appProperty->property.bundleName); - int result = AppSpawnProcessMsg(&sandboxArg, &appProperty->pid); - if (result == 0) { // wait child process result - result = WaitChild(appProperty->fd[0], appProperty->pid, appProperty); - } - close(appProperty->fd[0]); - close(appProperty->fd[1]); - APPSPAWN_LOGI("child process %{public}s %{public}s pid %{public}d", - appProperty->property.processName, (result == 0) ? "success" : "fail", appProperty->pid); - if (result == 0) { - AddAppInfo(appProperty->pid, appProperty->property.processName); - SendResponse(appProperty, (char *)&appProperty->pid, sizeof(appProperty->pid)); - } else { - SendResponse(appProperty, (char *)&result, sizeof(result)); - } - FreeHspList(appProperty); } APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags) @@ -497,8 +447,6 @@ APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskH client->stream = stream; client->client.id = ++clientId; client->client.flags = 0; - client->setAllowInternet = 0; - client->allowInternet = 1; client->property.hspList.totalLength = 0; client->property.hspList.savedLength = 0; client->property.hspList.data = NULL; @@ -558,9 +506,8 @@ void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]) int ret = GetAppSpawnClientFromArg(argc, argv, client); APPSPAWN_CHECK(ret == 0, free(client); return, "Failed to get client from arg"); - APPSPAWN_LOGI("Cold running %{public}d processName %{public}s %{public}u ", - getpid(), client->property.processName, content->longProcNameLen); - + client->client.flags &= ~ APP_COLD_START; + SHOW_CLIENT("Cold running", client); ret = DoStartApp(content, &client->client, content->longProcName, content->longProcNameLen); if (ret == 0 && content->runChildProcessor != NULL) { content->runChildProcessor(content, &client->client); diff --git a/standard/appspawn_service.h b/standard/appspawn_service.h index 0df104fd..2be45921 100644 --- a/standard/appspawn_service.h +++ b/standard/appspawn_service.h @@ -51,10 +51,6 @@ typedef struct { int32_t fd[2]; // 2 fd count AppParameter property; pid_t pid; - uint8_t setAllowInternet; - uint8_t allowInternet; - uint8_t reserved1; - uint8_t reserved2; } AppSpawnClientExt; typedef struct { @@ -75,6 +71,23 @@ typedef struct { void SetContentFunction(AppSpawnContent *content); void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]); int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client); +#define SHOW_CLIENT(info, clientExt) \ +do { \ + APPSPAWN_LOGI("Info %{public}s id %{public}d code %{public}d ", \ + info, (clientExt)->client.id, (clientExt)->property.code); \ + APPSPAWN_LOGI("processname %{public}s flags 0x%{public}x", \ + (clientExt)->property.processName, (clientExt)->property.flags); \ + APPSPAWN_LOGI("flags 0x%{public}x cloneFlags 0x%{public}x hapFlags 0x%{public}x", \ + (clientExt)->client.flags, (clientExt)->client.cloneFlags, (clientExt)->property.hapFlags); \ + APPSPAWN_LOGI("bundleName %{public}s soPath %{public}s", \ + (clientExt)->property.bundleName, (clientExt)->property.soPath); \ + APPSPAWN_LOGI("Access token apl %{public}s renderCmd %{public}s", \ + (clientExt)->property.apl, (clientExt)->property.renderCmd); \ + APPSPAWN_LOGI("uid %{public}u %{public}u gid count %{public}u", \ + (clientExt)->property.uid, (clientExt)->property.gid, (clientExt)->property.gidCount); \ + APPSPAWN_LOGI("setAllowInternet %{public}d allowInternet %{public}d ", \ + (clientExt)->property.setAllowInternet, (clientExt)->property.allowInternet); \ +} while (0) #ifdef __cplusplus } diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index c59a8a16..169dd17a 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -14,10 +14,33 @@ import("//base/startup/appspawn/appspawn.gni") import("//build/test.gni") +ohos_executable("AppSpawnTest") { + sources = [ "${appspawn_path}/test/moduletest/appspawn_test_cmd.cpp" ] + + include_dirs = [ + "//commonlibrary/c_utils/base/include", + "//third_party/zlib/contrib/minizip", + "//third_party/zlib", + ] + + configs = [ "${appspawn_path}:appspawn_config" ] + + deps = [ "${appspawn_path}/interfaces/innerkits:appspawn_socket_client" ] + + external_deps = [ + "c_utils:utils", + "hiviewdfx_hilog_native:libhilog", + "init:libbegetutil", + ] +} + ohos_moduletest("AppSpawnModuleTest") { module_out_path = "${module_output_path}" - sources = [ "${appspawn_path}/test/moduletest/appspawn_module_test.cpp" ] + sources = [ + "${appspawn_path}/test/moduletest/appspawn_client_test.cpp", + "${appspawn_path}/test/moduletest/appspawn_module_test.cpp", + ] include_dirs = [ "//commonlibrary/c_utils/base/include", @@ -40,6 +63,7 @@ ohos_moduletest("AppSpawnModuleTest") { "bundle_framework:appexecfwk_base", "c_utils:utils", "hiviewdfx_hilog_native:libhilog", + "init:libbegetutil", ] } @@ -47,4 +71,7 @@ group("moduletest") { testonly = true deps = [ ":AppSpawnModuleTest" ] + if (appspawn_test_cmd) { + deps += [ ":AppSpawnTest" ] + } } diff --git a/test/moduletest/appspawn_client_test.cpp b/test/moduletest/appspawn_client_test.cpp new file mode 100644 index 00000000..ef8e7e7b --- /dev/null +++ b/test/moduletest/appspawn_client_test.cpp @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_test_client.h" + +#include "gtest/gtest.h" +#include "securec.h" + +using namespace testing::ext; +using namespace OHOS; + +namespace OHOS { +namespace AppSpawn { + +class AppSpawnClientTest : public testing::Test, public AppSpawnTestClient { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} +}; + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_1, TestSize.Level0) +{ + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + request.code = SPAWN_NATIVE_PROCESS; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_2, TestSize.Level0) +{ + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + + // more gid + request.gidCount = APP_MAX_GIDS + 1; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_NE(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); +} + +// has hsp data,read json from etc +static const std::string g_jsonStr = "{ " + "\"bundles\": [{ " + "\"name\":\"test_service\", " + "\"path\":[\"/data/init_ut/test_service\"], " + "\"importance\":-20, " + "\"uid\":\"system\", " + "\"writepid\":[\"/dev/test_service\"], " + "\"console\":1, " + "\"caps\":[\"TEST_ERR\"], " + "\"gid\":[\"system\"], " + "\"critical\":1 " + "}], " + "\"modules\": [{ " + "\"name\":\"test_service\", " + "\"path\":[\"/data/init_ut/test_service\"], " + "\"importance\":-20, " + "\"uid\":\"system\", " + "\"writepid\":[\"/dev/test_service\"], " + "\"console\":1, " + "\"caps\":[\"TEST_ERR\"], " + "\"gid\":[\"system\"], " + "\"critical\":1 " + "}], " + " \"versions\": [{ " + "\"name\":\"test_service\", " + "\"path\":[\"/data/init_ut/test_service\"], " + "\"importance\":-20, " + "\"uid\":\"system\", " + "\"writepid\":[\"/dev/test_service\"], " + "\"console\":1, " + "\"caps\":[\"TEST_ERR\"], " + "\"gid\":[\"system\"], " + "\"critical\":1 " + "}] " +"}"; + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_3, TestSize.Level0) +{ + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + + printf("AppSpawn_Client_AppSpawn_3 hsp %zu %s \n", g_jsonStr.size(), g_jsonStr.c_str()); + request.hspList.totalLength = g_jsonStr.size(); + std::vector data(sizeof(request) + g_jsonStr.size()); + memcpy_s(data.data(), sizeof(request), &request, sizeof(request)); + memcpy_s(data.data() + sizeof(request), g_jsonStr.size(), g_jsonStr.data(), g_jsonStr.size()); + ret = ClientSendMsg(reinterpret_cast(data.data()), data.size()); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_4, TestSize.Level0) +{ + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_4"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + + // has hsp data,read json from etc + const std::string jsonPath("/system/etc/sandbox/system-sandbox.json"); + std::ifstream jsonFileStream; + jsonFileStream.open(jsonPath.c_str(), std::ios::in); + EXPECT_EQ(jsonFileStream.is_open() == true, 1); + std::vector buf; + char ch; + while (jsonFileStream.get(ch)) { + buf.insert(buf.end(), ch); + } + jsonFileStream.close(); + + printf("AppSpawn_Client_AppSpawn_4 hsp %zu \n", buf.size()); + request.hspList.totalLength = buf.size(); + std::vector data(sizeof(request) + buf.size()); + memcpy_s(data.data(), sizeof(request), &request, sizeof(request)); + memcpy_s(data.data() + sizeof(request), buf.size(), buf.data(), buf.size()); + ret = ClientSendMsg(reinterpret_cast(data.data()), data.size()); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_5, TestSize.Level0) +{ + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_5 start"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + + // more hsp data,read json from etc + const std::string jsonPath("/system/etc/sandbox/appdata-sandbox.json"); + std::ifstream jsonFileStream; + jsonFileStream.open(jsonPath.c_str(), std::ios::in); + EXPECT_EQ(jsonFileStream.is_open() == true, 1); + std::vector buf; + char ch; + while (jsonFileStream.get(ch)) { + buf.insert(buf.end(), ch); + } + jsonFileStream.close(); + + request.hspList.totalLength = buf.size(); + std::vector data(sizeof(request) + buf.size()); + memcpy_s(data.data(), sizeof(request), &request, sizeof(request)); + memcpy_s(data.data() + sizeof(request), buf.size(), buf.data(), buf.size()); + ret = ClientSendMsg(reinterpret_cast(data.data()), data.size()); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_5 end"); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_6, TestSize.Level0) +{ + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_6 start"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + SetParameter("startup.appspawn.cold.boot", "1"); + SetParameter("persist.appspawn.client.timeout", "10"); + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > /data/aaa.txt"); + request.flags = APP_COLD_BOOT; + request.code = SPAWN_NATIVE_PROCESS; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_6 end"); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_7, TestSize.Level0) +{ + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_7 start"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + SetParameter("startup.appspawn.cold.boot", "1"); + SetParameter("persist.appspawn.client.timeout", "10"); + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.2222222222222clock", "ls -l > /data/aaa.txt"); + request.flags = APP_COLD_BOOT | APP_NO_SANDBOX; + request.code = SPAWN_NATIVE_PROCESS; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_7 end"); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_8, TestSize.Level0) +{ + // for clod start, but not in sandbox + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_8 start"); + int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); + EXPECT_EQ(ret, 0); + + SetParameter("startup.appspawn.cold.boot", "1"); + SetParameter("persist.appspawn.client.timeout", "10"); + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.2222222222222clock", "ls -l > /data/aaa.txt"); + request.flags = APP_COLD_BOOT | APP_NO_SANDBOX; + request.code = SPAWN_NATIVE_PROCESS; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); + APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_8 end"); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_NWebSpawn_1, TestSize.Level0) +{ + int ret = ClientCreateSocket("/dev/unix/socket/NWebSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + if (pid > 0) { + kill(pid, SIGKILL); + } + // close client + ClientClose(); +} + +HWTEST_F(AppSpawnClientTest, AppSpawn_Client_NWebSpawn_2, TestSize.Level0) +{ + int ret = ClientCreateSocket("/dev/unix/socket/NWebSpawn"); + EXPECT_EQ(ret, 0); + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + ClientFillMsg(&request, "ohos.samples.clock", "ls -l > aaa.txt"); + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + pid_t pid = 0; + ret = ClientRecvMsg(pid); + EXPECT_EQ(ret, 0); + printf("AppSpawn_Client_NWebSpawn_2 pid %d \n", pid); + request.code = GET_RENDER_TERMINATION_STATUS; + request.pid = pid; + ret = ClientSendMsg(reinterpret_cast(&request), sizeof(request)); + EXPECT_EQ(ret, 0); + ret = ClientRecvMsg(pid); + printf("AppSpawn_Client_NWebSpawn_2 result %d \n", ret); + // close client + ClientClose(); +} +} // namespace AppSpawn +} // namespace OHOS \ No newline at end of file diff --git a/test/moduletest/appspawn_test_client.h b/test/moduletest/appspawn_test_client.h new file mode 100644 index 00000000..1d5637e8 --- /dev/null +++ b/test/moduletest/appspawn_test_client.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef APPSPAWN_CLIENT_TEST_H +#define APPSPAWN_CLIENT_TEST_H + +#include +#include + +#include +#include +#include +#include + +#include "client_socket.h" +#include "appspawn_server.h" +#include "parameter.h" + +namespace OHOS { +namespace AppSpawn { + +class AppSpawnTestClient { +public: + AppSpawnTestClient() = default; + ~AppSpawnTestClient() = default; + + int ClientCreateSocket(std::string path = "/dev/unix/socket/NWebSpawn") + { + // close old socket and create new + if (clientSocket_ != nullptr) { + clientSocket_->CloseClient(); + clientSocket_ = nullptr; + } + clientSocket_ = std::make_shared(path); + APPSPAWN_CHECK(clientSocket_ != nullptr, return -1, "Failed to create client for path %s", path.c_str()); + int ret = clientSocket_->CreateClient(); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for path %ss", path.c_str()); + ret = clientSocket_->ConnectSocket(); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to connect to server %ss", path.c_str()); + return 0; + } + + void ClientClose() + { + if (clientSocket_ != nullptr) { + clientSocket_->CloseClient(); + clientSocket_ = nullptr; + } + } + int ClientSendMsg(const uint8_t *buf, int len) + { + int curr = 0; + int real = 0; + uint8_t *buffer = const_cast(buf); + const int maxLen = 5 * 1024; + while (curr < len) { + if ((len - curr) > maxLen) { + real = maxLen; + } else { + real = len - curr; + } + if (clientSocket_->WriteSocketMessage(static_cast(buffer + curr), real) != real) { + return -1; + } + curr += real; + } + return 0; + } + + int ClientRecvMsg(pid_t &pid) + { + pid = -1; + std::vector data(sizeof(pid_t)); // 4 pid size + if (clientSocket_->ReadSocketMessage(data.data(), data.size()) == sizeof(pid_t)) { + int ret = *(reinterpret_cast(data.data())); + if (ret < 0) { + return ret; + } + pid = static_cast(ret); + return 0; + } + return -1; + } + + void ClientFillMsg(AppParameter *request, const std::string &processName, const std::string &cmd) + { + request->code = DEFAULT; + request->flags = 0; + request->uid = 20010033; // 20010033 test uid + request->gid = 20010033; // 20010033 test gid + request->gidCount = 0; + request->accessTokenId = 0x200a509d; // 0x200a509d test token id + request->accessTokenIdEx = 0x4832514205; // 0x4832514205 test token id + request->allowInternet = 1; + request->hspList.totalLength = 0; + request->hspList.savedLength = 0; + request->hspList.data = nullptr; + int ret = strcpy_s(request->apl, sizeof(request->processName), processName.c_str()); + ret += strcpy_s(request->processName, sizeof(request->processName), processName.c_str()); + ret += strcpy_s(request->bundleName, sizeof(request->bundleName), processName.c_str()); + ret += strcpy_s(request->renderCmd, sizeof(request->renderCmd), cmd.c_str()); + if (ret != 0) { + printf("Failed to copy bundle name \n"); + } + } +private: + std::shared_ptr clientSocket_ {}; +}; + +} // namespace AppSpawn +} // namespace OHOS +#endif // APPSPAWN_CLIENT_TEST_H \ No newline at end of file diff --git a/test/moduletest/appspawn_test_cmd.cpp b/test/moduletest/appspawn_test_cmd.cpp new file mode 100644 index 00000000..4de4313f --- /dev/null +++ b/test/moduletest/appspawn_test_cmd.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_test_client.h" + +#include +#include + +OHOS::AppSpawn::AppSpawnTestClient g_testClient; + +static int DoRun(const char *server, const AppParameter *request) +{ + int ret = g_testClient.ClientCreateSocket(server); + if (ret != 0) { + printf("Failed to connect server \n"); + return 1; + } + ret = g_testClient.ClientSendMsg(reinterpret_cast(request), sizeof(AppParameter)); + if (ret != 0) { + printf("Failed to send msg to server \n"); + g_testClient.ClientClose(); + return 1; + } + pid_t pid = 0; + ret = g_testClient.ClientRecvMsg(pid); + if (ret != 0) { + printf("Failed spawn new app result %d \n", ret); + g_testClient.ClientClose(); + quick_exit(0); + return 1; + } + if (pid > 0) { + printf("Success spawn new app pid %d \n", pid); + } + int index = 0; + while (index < 5) { // wait 5s + sleep(1); + index++; + } + if (pid > 0) { + APPSPAWN_LOGI("Success spawn new app pid %{public}d \n", pid); + kill(pid, SIGKILL); + } + // close client + g_testClient.ClientClose(); + quick_exit(0); + return 0; +} + +int main(int argc, char *const argv[]) +{ + int coldStart = 0; + int withSandbox = 0; + const char *cmd = "ls -l /data > /data/test.log"; + const char *bundleName = "ohos.samples.test"; + const char *server = "/dev/unix/socket/AppSpawn"; + for (int32_t i = 0; i < argc; i++) { + if (strcmp(argv[i], "-c") == 0) { + coldStart = 1; + } else if (strcmp(argv[i], "-s") == 0) { + withSandbox = 1; + } else if (strcmp(argv[i], "--nwebspawn") == 0) { + server = "/dev/unix/socket/NWebSpawn"; + } else if (strcmp(argv[i], "-b") == 0 && ((i + 1) < argc)) { + i++; + bundleName = argv[i]; + } else if (strcmp(argv[i], "-C") == 0 && ((i + 1) < argc)) { + i++; + cmd= argv[i]; + } + } + + if (coldStart) { + SetParameter("startup.appspawn.cold.boot", "1"); + SetParameter("persist.appspawn.client.timeout", "10"); + } + + AppParameter request = {}; + memset_s((void *)(&request), sizeof(request), 0, sizeof(request)); + g_testClient.ClientFillMsg(&request, bundleName, cmd); + + request.flags = coldStart ? APP_COLD_BOOT : 0; + request.flags |= !withSandbox ? APP_NO_SANDBOX : 0; + request.code = SPAWN_NATIVE_PROCESS; + return DoRun(server, &request); +} diff --git a/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp index a208bb31..16ddf935 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_sandbox_test.cpp @@ -56,10 +56,20 @@ void AppSpawnSandboxTest::SetUp() void AppSpawnSandboxTest::TearDown() {} -static ClientSocket::AppProperty *GetAppProperty(void) +static AppSpawnClientExt *GetAppSpawnClientExt(void) { static AppSpawnClientExt client; - return &client.property; + return &client; +} + +static ClientSocket::AppProperty *GetAppProperty(void) +{ + return &GetAppSpawnClientExt()->property; +} + +static AppSpawnClient *GetAppSpawnClient(void) +{ + return &GetAppSpawnClientExt()->client; } /** @@ -95,7 +105,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_08, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_08 end"; } @@ -131,7 +141,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_09, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_09 end"; } @@ -159,17 +169,17 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_09_1, TestSize.Level0) int ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(nullptr); EXPECT_NE(ret, 0); m_appProperty->bundleName[0] = '\0'; - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_NE(ret, 0); if (strcpy_s(m_appProperty->bundleName, APP_LEN_BUNDLE_NAME, "com.\\ohos.dlpmanager") != 0) { GTEST_LOG_(INFO) << "SetAppSandboxProperty start 2" << std::endl; } - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_NE(ret, 0); if (strcpy_s(m_appProperty->bundleName, APP_LEN_BUNDLE_NAME, "com./ohos.dlpmanager") != 0) { GTEST_LOG_(INFO) << "SetAppSandboxProperty start 2" << std::endl; } - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_NE(ret, 0); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_09_1 end"; } @@ -225,7 +235,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_10, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_10 end"; } @@ -351,7 +361,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_13, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_13 end"; } @@ -404,7 +414,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_14, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_14 end"; } @@ -458,7 +468,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_15, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_15 end"; } @@ -505,7 +515,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_16, TestSize.Level0) m_appProperty->accessTokenId = 671201800; // 671201800 is accessTokenId m_appProperty->pid = 354; // query render process exited status by render process pid - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); GTEST_LOG_(INFO) << "App_Spawn_Sandbox_16 end"; } @@ -576,7 +586,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_19, TestSize.Level0) GTEST_LOG_(ERROR) << "Failed to memset_s err=" << errno; ASSERT_TRUE(0); } - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_EQ(ret, -1); ret = strncpy_s(m_appProperty->bundleName, APP_LEN_BUNDLE_NAME, "\\test", APP_LEN_BUNDLE_NAME - 1); @@ -584,7 +594,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_19, TestSize.Level0) GTEST_LOG_(ERROR) << "Failed to strncpy_s err=" << errno; ASSERT_TRUE(0); } - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_EQ(ret, -1); ret = strncpy_s(m_appProperty->bundleName, APP_LEN_BUNDLE_NAME, "/test", APP_LEN_BUNDLE_NAME - 1); @@ -592,7 +602,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_19, TestSize.Level0) GTEST_LOG_(ERROR) << "Failed to strncpy_s err=" << errno; ASSERT_TRUE(0); } - ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + ret = OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); EXPECT_EQ(ret, -1); } @@ -615,7 +625,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_20, TestSize.Level0) m_appProperty->uid = 1000; // the UNIX uid that the child process setuid() to after fork() m_appProperty->gid = 1000; // the UNIX gid that the child process setgid() to after fork() - m_appProperty->cloneFlags = CLONE_NEWPID; + GetAppSpawnClient()->cloneFlags = CLONE_NEWPID; if (strcpy_s(m_appProperty->processName, APP_LEN_PROC_NAME, "test.appspawn") != 0) { GTEST_LOG_(INFO) << "Failed to strcpy_s err=" << errno << std::endl; @@ -626,7 +636,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_20, TestSize.Level0) if (strcpy_s(m_appProperty->apl, APP_APL_MAX_LEN, "normal") != 0) { GTEST_LOG_(INFO) << "Failed to strcpy_s err=" << errno << std::endl; } - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); std::string mJsconfig1 = "{ \ \"common\":[{ \ @@ -644,7 +654,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_20, TestSize.Level0) }"; nlohmann::json j_config1 = nlohmann::json::parse(mJsconfig1.c_str()); OHOS::AppSpawn::SandboxUtils::StoreJsonConfig(j_config1); - OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(m_appProperty); + OHOS::AppSpawn::SandboxUtils::SetAppSandboxProperty(GetAppSpawnClient()); } HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_21, TestSize.Level0) @@ -665,13 +675,6 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_22, TestSize.Level0) nlohmann::json j_config1 = nlohmann::json::parse(mJsconfig1.c_str()); OHOS::AppSpawn::SandboxUtils::StoreJsonConfig(j_config1); - std::string pJsconfig1 = "{ \ - \"common\":[], \ - \"individual\": [] \ - }"; - nlohmann::json p_config1 = nlohmann::json::parse(pJsconfig1.c_str()); - OHOS::AppSpawn::SandboxUtils::StoreProductJsonConfig(p_config1); - ClientSocket::AppProperty *m_appProperty = GetAppProperty(); int ret = strcpy_s(m_appProperty->apl, APP_APL_MAX_LEN, "system_basic"); if (ret != 0) { diff --git a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp index 1243622b..a90b1141 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp @@ -278,13 +278,14 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003, TestSize.Level0) */ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_1, TestSize.Level0) { - GTEST_LOG_(INFO) << "App_Spawn_Standard_003_1 start"; + APPSPAWN_LOGI("App_Spawn_Standard_003_1 start"); AppSpawnClientExt client = {}; char arg1[] = "/system/bin/appspawn"; char arg2[] = "cold-start"; char arg3[] = "1"; { - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "10"; char arg6[] = "012345678"; char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6}; @@ -293,35 +294,39 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_1, TestSize.Level0) FreeHspList(client.property.hspList); } { // hsp length is 0 - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "0"; char* argv[] = {arg1, arg2, arg3, arg4, arg5, nullptr}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(0, GetAppSpawnClientFromArg(argc, argv, &client)); } { // hsp length is null - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg6[] = "0123456789"; char* argv[] = {arg1, arg2, arg3, arg4, nullptr, arg6}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client)); } { // hsp length is non-zero, but argc is 5 - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "10"; char* argv[] = {arg1, arg2, arg3, arg4, arg5}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client)); } { // hsp length is non-zero, but content is null - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "10"; char* argv[] = {arg1, arg2, arg3, arg4, arg5, nullptr}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client)); } - GTEST_LOG_(INFO) << "App_Spawn_Standard_003_1 end"; + APPSPAWN_LOGI("App_Spawn_Standard_003_1 en"); } /** @@ -333,13 +338,14 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_1, TestSize.Level0) */ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_2, TestSize.Level0) { - GTEST_LOG_(INFO) << "App_Spawn_Standard_003_2 start"; + APPSPAWN_LOGI("App_Spawn_Standard_003_2 start"); AppSpawnClientExt client = {}; char arg1[] = "/system/bin/appspawn"; char arg2[] = "cold-start"; char arg3[] = "1"; { // actual data is shorter than totalLength - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "10"; char arg6[] = "01234"; char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6}; @@ -348,7 +354,8 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_2, TestSize.Level0) FreeHspList(client.property.hspList); } { // actual data is longer than totalLength - char arg4[] = "1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:default:671201800:system_core:default"; + char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char arg5[] = "5"; char arg6[] = "0123456789"; char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6}; @@ -357,7 +364,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_2, TestSize.Level0) FreeHspList(client.property.hspList); } - GTEST_LOG_(INFO) << "App_Spawn_Standard_003_2 end"; + APPSPAWN_LOGI("App_Spawn_Standard_003_2 end"); } /** @@ -379,12 +386,13 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_004, TestSize.Level0) content->runChildProcessor = RunChildProcessor; content->runChildProcessor(content, nullptr); + char tmp0[] = "/system/bin/appspawn"; char tmp1[] = "cold-start"; char tmp2[] = "1"; { - char tmp3[] = "1:1:1:1:2:1000:1000:ohos.samples.ecg.default: \ - ohos.samples.ecg:default:671201800:system_core:default"; + char tmp3[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:" + "default:671201800:system_core:default:0:671201800"; char * const argv[] = {tmp0, tmp1, tmp2, tmp3}; AppSpawnColdRun(content, 4, argv); } @@ -448,7 +456,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0) GTEST_LOG_(INFO) << "App_Spawn_Standard_005 end"; } -static int RunClient(AppSpawnContentExt *content, int cold, AppOperateType code, const std::string &processName) +static int RunClient(AppSpawnContentExt *content, int flags, AppOperateType code, const std::string &processName) { // create connection TaskHandle stream = AcceptClient(LE_GetDefaultLoop(), content->server, TASK_TEST); @@ -465,12 +473,16 @@ static int RunClient(AppSpawnContentExt *content, int cold, AppOperateType code, property.gid = 100; // 100 is gid property.gidCount = 1; // 1 is gidCount property.gidTable[0] = 101; // 101 is gidTable - (void)strcpy_s(property.processName, sizeof(property.processName), processName.c_str()); + if (code == SPAWN_NATIVE_PROCESS) { + (void)strcpy_s(property.processName, sizeof(property.processName), "ohos.appspawn.test.cmd"); + } else { + (void)strcpy_s(property.processName, sizeof(property.processName), processName.c_str()); + } (void)strcpy_s(property.bundleName, sizeof(property.bundleName), processName.c_str()); (void)strcpy_s(property.renderCmd, sizeof(property.renderCmd), processName.c_str()); (void)strcpy_s(property.soPath, sizeof(property.soPath), processName.c_str()); (void)strcpy_s(property.apl, sizeof(property.apl), "system_core"); - property.flags = cold ? 0x01 : 0; + property.flags = flags; property.code = code; property.accessTokenId = 0; property.setAllowInternet = 1; @@ -491,7 +503,7 @@ static int RunClient(AppSpawnContentExt *content, int cold, AppOperateType code, return 0; } -static AppSpawnContentExt *TestClient(int cold, +static AppSpawnContentExt *TestClient(int flags, AppOperateType code, const std::string &processName, const std::string &serverName) { char buffer[64] = {0}; // 64 buffer size @@ -506,7 +518,7 @@ static AppSpawnContentExt *TestClient(int cold, // set common operation content->content.loadExtendLib = LoadExtendLib; content->content.runChildProcessor = RunChildProcessor; - content->flags |= cold ? FLAGS_ON_DEMAND : 0; + content->flags |= (flags & APP_COLD_BOOT) ? FLAGS_ON_DEMAND : 0; // test null StreamServerTask *task = reinterpret_cast(content->server); task->incommingConnect(nullptr, nullptr); @@ -519,7 +531,7 @@ static AppSpawnContentExt *TestClient(int cold, ret = LE_StartTimer(LE_GetDefaultLoop(), content->timer, 500, 1); // 500 ms is timeout EXPECT_EQ(ret, 0); } - ret = RunClient(content, cold, code, processName); + ret = RunClient(content, flags, code, processName); EXPECT_EQ(ret, 0); if (content->timer == nullptr) { // create timer for exit @@ -562,7 +574,8 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_006_2, TestSize.Level0) GTEST_LOG_(INFO) << "App_Spawn_Standard_006_2 start"; SetHapDomainSetcontextResult(-1); SetParameter("startup.appspawn.cold.boot", "1"); - AppSpawnContentExt *content = TestClient(1, DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); + AppSpawnContentExt *content = TestClient(APP_COLD_BOOT, + DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); ASSERT_TRUE(content != nullptr); content->content.runAppSpawn(&content->content, 0, nullptr); GTEST_LOG_(INFO) << "App_Spawn_Standard_006_2 end"; @@ -572,7 +585,8 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_006_3, TestSize.Level0) { GTEST_LOG_(INFO) << "App_Spawn_Standard_006_3 start"; SetHapDomainSetcontextResult(-1); - AppSpawnContentExt *content = TestClient(1, DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); + AppSpawnContentExt *content = TestClient(APP_COLD_BOOT, + DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); ASSERT_TRUE(content != nullptr); content->content.runAppSpawn(&content->content, 0, nullptr); GTEST_LOG_(INFO) << "App_Spawn_Standard_006_3 end"; @@ -583,7 +597,8 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_006_4, TestSize.Level0) GTEST_LOG_(INFO) << "App_Spawn_Standard_006_4 start"; SetHapDomainSetcontextResult(-1); SetParameter("const.appspawn.preload", "false"); - AppSpawnContentExt *content = TestClient(1, DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); + AppSpawnContentExt *content = TestClient(APP_COLD_BOOT, + DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2"); ASSERT_TRUE(content != nullptr); content->content.coldStartApp = nullptr; content->content.runAppSpawn(&content->content, 0, nullptr); @@ -817,4 +832,48 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_ReportEvent, TestSize.Level0) ReportProcessExitInfo(nullptr, 100, 100, 0); ReportProcessExitInfo("nullptr", 100, 100, 0); } + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_009_01, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_01 start"; + SetHapDomainSetcontextResult(-1); + AppSpawnContentExt *content = TestClient(0, + SPAWN_NATIVE_PROCESS, "ls -l > /data/appspawn_ut/test009_1", "test009_1"); + ASSERT_TRUE(content != nullptr); + content->content.runAppSpawn(&content->content, 0, nullptr); + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_01 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_009_02, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_02 start"; + SetHapDomainSetcontextResult(-1); + AppSpawnContentExt *content = TestClient(APP_NO_SANDBOX, + SPAWN_NATIVE_PROCESS, "ls -l > /data/appspawn_ut/test009_02", "test009_02"); + ASSERT_TRUE(content != nullptr); + content->content.runAppSpawn(&content->content, 0, nullptr); + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_02 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_009_03, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_03 start"; + SetHapDomainSetcontextResult(-1); + AppSpawnContentExt *content = TestClient(APP_COLD_BOOT, + SPAWN_NATIVE_PROCESS, "ls -l > /data/appspawn_ut/test009_03", "test009_03"); + ASSERT_TRUE(content != nullptr); + content->content.runAppSpawn(&content->content, 0, nullptr); + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_03 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_009_04, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_04 start"; + SetHapDomainSetcontextResult(-1); + AppSpawnContentExt *content = TestClient(APP_COLD_BOOT | APP_NO_SANDBOX, + SPAWN_NATIVE_PROCESS, "ls -l > /data/appspawn_ut/test009_04", "test009_04"); + ASSERT_TRUE(content != nullptr); + content->content.runAppSpawn(&content->content, 0, nullptr); + GTEST_LOG_(INFO) << "App_Spawn_Standard_009_04 end"; +} } // namespace OHOS diff --git a/util/include/sandbox_utils.h b/util/include/sandbox_utils.h index 945bf61d..54604929 100644 --- a/util/include/sandbox_utils.h +++ b/util/include/sandbox_utils.h @@ -21,6 +21,7 @@ #include #include "nlohmann/json.hpp" #include "client_socket.h" +#include "appspawn_server.h" namespace OHOS { namespace AppSpawn { @@ -32,7 +33,7 @@ public: static nlohmann::json GetJsonConfig(); static void StoreProductJsonConfig(nlohmann::json &productSandboxConfig); static nlohmann::json GetProductJsonConfig(); - static int32_t SetAppSandboxProperty(const ClientSocket::AppProperty *appProperty); + static int32_t SetAppSandboxProperty(AppSpawnClient *client); static uint32_t GetNamespaceFlagsFromConfig(const char *bundleName); private: diff --git a/util/src/sandbox_utils.cpp b/util/src/sandbox_utils.cpp index fd632702..2c1af828 100644 --- a/util/src/sandbox_utils.cpp +++ b/util/src/sandbox_utils.cpp @@ -27,6 +27,7 @@ #include "json_utils.h" #include "securec.h" #include "appspawn_server.h" +#include "appspawn_service.h" #ifdef WITH_SELINUX #include "hap_restorecon.h" #endif @@ -936,18 +937,22 @@ static int CheckBundleName(const std::string &bundleName) return 0; } -int32_t SandboxUtils::SetAppSandboxProperty(const ClientSocket::AppProperty *appProperty) +int32_t SandboxUtils::SetAppSandboxProperty(AppSpawnClient *client) { - if (appProperty == nullptr || CheckBundleName(appProperty->bundleName) != 0) { + APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); + AppSpawnClientExt *clientExt = reinterpret_cast(client); + ClientSocket::AppProperty *appProperty = &clientExt->property; + if (CheckBundleName(appProperty->bundleName) != 0) { return -1; } + std::string sandboxPackagePath = g_sandBoxRootDir; const std::string bundleName = appProperty->bundleName; sandboxPackagePath += bundleName; MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE); int rc = 0; // when CLONE_NEWPID is enabled, CLONE_NEWNS must be enabled. - if (!(appProperty->cloneFlags & CLONE_NEWPID)) { + if (!(client->cloneFlags & CLONE_NEWPID)) { // add pid to a new mnt namespace rc = unshare(CLONE_NEWNS); APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());