diff --git a/BUILD.gn b/BUILD.gn index 990f4cda..c6e9b6eb 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -16,10 +16,12 @@ import("//build/ohos.gni") config("appspawn_config") { visibility = [ "./*" ] include_dirs = [ + "${appspawn_path}", "common", "standard", "adapter", "interfaces/innerkits/include", + "interfaces/innerkits_new/include", "util/include", "//third_party/json/include", ] @@ -61,6 +63,7 @@ if (!defined(ohos_lite)) { "ability_runtime:runtime", "access_token:libtoken_setproc", "ace_engine:ace_forward_compatibility", + "cJSON:cjson", "c_utils:utils", "common_event_service:cesfwk_innerkits", "config_policy:configpolicy_util", @@ -132,6 +135,7 @@ if (!defined(ohos_lite)) { "${appspawn_path}/adapter/appspawn_sandbox.cpp", "${appspawn_path}/common/appspawn_server.c", "${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp", + "${appspawn_path}/standard/appspawn_msgmgr.c", "${appspawn_path}/standard/appspawn_process.c", "${appspawn_path}/standard/appspawn_service.c", "${appspawn_path}/util/src/env_utils.cpp", @@ -148,10 +152,12 @@ if (!defined(ohos_lite)) { } configs = [ ":appspawn_config" ] ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ] + deps = [] external_deps = [ "ability_runtime:appkit_native", "access_token:libtoken_setproc", "access_token:libtokenid_sdk", + "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", "eventhandler:libeventhandler", @@ -191,7 +197,7 @@ if (!defined(ohos_lite)) { if (appspawn_report_event) { cflags += [ "-DREPORT_EVENT" ] - deps = [ "adapter/sysevent:event_reporter" ] + deps += [ "adapter/sysevent:event_reporter" ] } subsystem_name = "${subsystem_name}" diff --git a/adapter/appspawn_adapter.cpp b/adapter/appspawn_adapter.cpp index 1fa2e5c3..cd01febb 100644 --- a/adapter/appspawn_adapter.cpp +++ b/adapter/appspawn_adapter.cpp @@ -37,7 +37,7 @@ const char* RENDERER_NAME = "renderer"; #define NWEBSPAWN_SERVER_NAME "nwebspawn" using namespace OHOS::Security::AccessToken; -int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client) +int SetAppAccessToken(struct AppSpawnContent *content, AppSpawnClient *client) { AppSpawnClientExt *appProperty = reinterpret_cast(client); int32_t ret = 0; @@ -64,7 +64,7 @@ int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client) return 0; } -int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client) +int SetSelinuxCon(struct AppSpawnContent *content, AppSpawnClient *client) { #ifdef WITH_SELINUX if (content->isNweb) { @@ -100,7 +100,7 @@ int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client) return 0; } -void SetUidGidFilter(struct AppSpawnContent_ *content) +void SetUidGidFilter(struct AppSpawnContent *content) { #ifdef WITH_SECCOMP bool ret = false; @@ -123,7 +123,7 @@ void SetUidGidFilter(struct AppSpawnContent_ *content) #endif } -int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client) +int SetSeccompFilter(struct AppSpawnContent *content, AppSpawnClient *client) { #ifdef WITH_SECCOMP const char *appName = APP_NAME; diff --git a/adapter/appspawn_adapter.h b/adapter/appspawn_adapter.h index bd297005..5e21687e 100644 --- a/adapter/appspawn_adapter.h +++ b/adapter/appspawn_adapter.h @@ -24,19 +24,19 @@ extern "C" { #endif -typedef struct AppSpawnContentExt_ AppSpawnContentExt; -typedef struct AppInfo_ AppSpawnAppInfo; +typedef struct AppSpawnContentExt AppSpawnContentExt; +typedef struct AppInfo AppSpawnAppInfo; -int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client); -int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client); -int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client); +int32_t SetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client); +int SetAppAccessToken(struct AppSpawnContent *content, AppSpawnClient *client); +int SetSelinuxCon(struct AppSpawnContent *content, AppSpawnClient *client); void LoadExtendLib(AppSpawnContent *content); void LoadExtendLibNweb(AppSpawnContent *content); void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); void RunChildProcessorNweb(AppSpawnContent *content, AppSpawnClient *client); void LoadAppSandboxConfig(AppSpawnContent *content); -void SetUidGidFilter(struct AppSpawnContent_ *content); -int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client); +void SetUidGidFilter(struct AppSpawnContent *content); +int SetSeccompFilter(struct AppSpawnContent *content, AppSpawnClient *client); void HandleInternetPermission(const AppSpawnClient *client); void DisallowInternet(void); diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index eb21a279..3cff5db1 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -70,7 +70,7 @@ void LoadAppSandboxConfig(AppSpawnContent *content) content->sandboxNsFlags = SandboxUtils::GetSandboxNsFlags(content->isNweb); } -int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) +int32_t SetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client) { APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); AppSpawnClientExt *clientExt = reinterpret_cast(client); diff --git a/appspawn.gni b/appspawn.gni index 7a91d569..ac18b375 100644 --- a/appspawn.gni +++ b/appspawn.gni @@ -14,6 +14,8 @@ ability_runtime_path = "//foundation/ability/ability_runtime" ability_runtime_kits_path = "${ability_runtime_path}/frameworks/kits" appspawn_path = "//base/startup/appspawn" +appspawn_innerkits_path = "//base/startup/appspawn/interfaces/innerkits_new" +startup_path = "//base/startup" subsystem_name = "startup" part_name = "appspawn" module_output_path = "${part_name}/appspawn_l2" diff --git a/bundle.json b/bundle.json index e8182d84..456e564e 100644 --- a/bundle.json +++ b/bundle.json @@ -60,7 +60,8 @@ "ui_lite", "code_signature", "bounds_checking_function", - "zlib" + "zlib", + "cJSON" ], "third_party": [ "bounds_checking_function", @@ -74,6 +75,15 @@ "//base/startup/appspawn:appspawn_all" ], "inner_kits": [ + { + "header": { + "header_base": "//base/startup/appspawn/interfaces/innerkits_new/include/", + "header_files": [ + "appspawn.h" + ] + }, + "name": "//base/startup/appspawn/interfaces/innerkits_new/client:appspawn_client" + }, { "header": { "header_base": "//base/startup/appspawn/interfaces/innerkits/include/", diff --git a/common/appspawn_server.c b/common/appspawn_server.c index 168d82f7..455af03f 100644 --- a/common/appspawn_server.c +++ b/common/appspawn_server.c @@ -44,7 +44,7 @@ long long DiffTime(struct timespec *startTime) return diff; } -static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result) +static void NotifyResToParent(struct AppSpawnContent *content, AppSpawnClient *client, int result) { if (content->notifyResToParent != NULL) { content->notifyResToParent(content, client, result); @@ -78,7 +78,7 @@ void exit(int code) } #endif -int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen) +int DoStartApp(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen) { int32_t ret = 0; APPSPAWN_LOGV("DoStartApp id %{public}d longProcNameLen %{public}u", client->id, longProcNameLen); @@ -88,14 +88,12 @@ int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *l if (content->setEnvInfo) { ret = content->setEnvInfo(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to setEnvInfo"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setEnvInfo"); } if (content->setAppSandbox) { ret = content->setAppSandbox(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to set app sandbox"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set app sandbox"); } (void)umask(DEFAULT_UMASK); @@ -107,38 +105,32 @@ int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *l if (content->setXpmConfig) { ret = content->setXpmConfig(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to set setXpmConfig"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set setXpmConfig"); } if (content->setProcessName) { ret = content->setProcessName(content, client, content->longProcName, content->longProcNameLen); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to set setProcessName"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to set setProcessName"); } if (content->setUidGid) { ret = content->setUidGid(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to setUidGid"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setUidGid"); } if (content->setFileDescriptors) { ret = content->setFileDescriptors(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to setFileDescriptors"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setFileDescriptors"); } if (content->setCapabilities) { ret = content->setCapabilities(content, client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to setCapabilities"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to setCapabilities"); } if (content->waitForDebugger) { ret = content->waitForDebugger(client); - APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); - return ret, "Failed to waitForDebugger"); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); return ret, "Failed to waitForDebugger"); } #ifdef SECURITY_COMPONENT_ENABLE @@ -154,7 +146,7 @@ static int AppSpawnChild(void *arg) { APPSPAWN_CHECK(arg != NULL, return -1, "Invalid arg for appspawn child"); AppSandboxArg *sandbox = (AppSandboxArg *)arg; - struct AppSpawnContent_ *content = sandbox->content; + struct AppSpawnContent *content = sandbox->content; AppSpawnClient *client = sandbox->client; int ret = -1; diff --git a/common/appspawn_server.h b/common/appspawn_server.h index 494ae454..d52b3d41 100644 --- a/common/appspawn_server.h +++ b/common/appspawn_server.h @@ -38,63 +38,63 @@ extern "C" { #define APPSPAWN_CHECK_EXIT "AppSpawnCheckUnexpectedExitCall" -typedef struct AppSpawnClient_ { +typedef struct AppSpawnClient { uint32_t id; uint32_t flags; // Save negotiated flags uint32_t cloneFlags; // for clone flags } AppSpawnClient; #define MAX_SOCKEYT_NAME_LEN 128 -typedef struct AppSpawnContent_ { +typedef struct AppSpawnContent { char *longProcName; uint32_t longProcNameLen; uint32_t sandboxNsFlags; bool isNweb; // system - void (*loadExtendLib)(struct AppSpawnContent_ *content); - int (*initAppSpawn)(struct AppSpawnContent_ *content); - void (*runAppSpawn)(struct AppSpawnContent_ *content, int argc, char *const argv[]); - void (*setUidGidFilter)(struct AppSpawnContent_ *content); + void (*loadExtendLib)(struct AppSpawnContent *content); + int (*initAppSpawn)(struct AppSpawnContent *content); + void (*runAppSpawn)(struct AppSpawnContent *content, int argc, char *const argv[]); + void (*setUidGidFilter)(struct AppSpawnContent *content); // for child - void (*clearEnvironment)(struct AppSpawnContent_ *content, AppSpawnClient *client); - void (*initDebugParams)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setAppAccessToken)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setAppSandbox)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setKeepCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setFileDescriptors)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setEnvInfo)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setProcessName)(struct AppSpawnContent_ *content, AppSpawnClient *client, + void (*clearEnvironment)(struct AppSpawnContent *content, AppSpawnClient *client); + void (*initDebugParams)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setAppAccessToken)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setAppSandbox)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setKeepCapabilities)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setFileDescriptors)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setEnvInfo)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setProcessName)(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen); - int (*setUidGid)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setXpmConfig)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setUidGid)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setCapabilities)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setXpmConfig)(struct AppSpawnContent *content, AppSpawnClient *client); - void (*notifyResToParent)(struct AppSpawnContent_ *content, AppSpawnClient *client, int result); - void (*runChildProcessor)(struct AppSpawnContent_ *content, AppSpawnClient *client); + void (*notifyResToParent)(struct AppSpawnContent *content, AppSpawnClient *client, int result); + void (*runChildProcessor)(struct AppSpawnContent *content, AppSpawnClient *client); #ifndef ASAN_DETECTOR - int (*setAsanEnabledEnv)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setAsanEnabledEnv)(struct AppSpawnContent *content, AppSpawnClient *client); #endif // for pid namespace - int (*enablePidNs)(struct AppSpawnContent_ *content); + int (*enablePidNs)(struct AppSpawnContent *content); // for cold start - int (*coldStartApp)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*getWrapBundleNameValue)(struct AppSpawnContent_ *content, AppSpawnClient *client); - int (*setSeccompFilter)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*coldStartApp)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*getWrapBundleNameValue)(struct AppSpawnContent *content, AppSpawnClient *client); + int (*setSeccompFilter)(struct AppSpawnContent *content, AppSpawnClient *client); void (*handleInternetPermission)(const AppSpawnClient *client); int (*waitForDebugger)(AppSpawnClient *client); } AppSpawnContent; typedef struct { - struct AppSpawnContent_ *content; + struct AppSpawnContent *content; AppSpawnClient *client; } AppSandboxArg; AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int cold); int AppSpawnProcessMsg(AppSandboxArg *sandbox, pid_t *childPid); -int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen); +int DoStartApp(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen); long long DiffTime(struct timespec *startTime); pid_t AppSpawnFork(int (*childFunc)(void *arg), void *args); #define UNUSED(x) (void)(x) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 85074aad..f33b17dd 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -80,13 +80,13 @@ typedef enum AppOperateType_ { #define APPSPAWN_COLDSTART_KEY "cold-start" #define NWEBSPAWN_COLDSTART_KEY "nweb-cold-start" -typedef struct ExtraInfo_ { +typedef struct ExtraInfo { uint32_t totalLength; uint32_t savedLength; char* data; } ExtraInfo; -typedef struct AppParameter_ { +typedef struct AppParameter { AppOperateType code; uint32_t flags; int32_t pid; // query render process exited status by render process pid diff --git a/interfaces/innerkits_new/client/BUILD.gn b/interfaces/innerkits_new/client/BUILD.gn index 495e55db..3f133bf7 100644 --- a/interfaces/innerkits_new/client/BUILD.gn +++ b/interfaces/innerkits_new/client/BUILD.gn @@ -24,8 +24,7 @@ if (!defined(ohos_lite)) { sources = [ "${appspawn_path}/modules/sandbox/appspawn_permission.c", "${appspawn_path}/util/src/appspawn_utils.c", - "${appspawn_path}/util/src/json_utils.cpp", - "../permission/appspawn_mount_permission.cpp", + "../permission/appspawn_mount_permission.c", "appspawn_client.c", "appspawn_msg.c", ] @@ -35,6 +34,7 @@ if (!defined(ohos_lite)) { "../permission", "../module_engine/include", "${appspawn_path}", + "${appspawn_path}/common", "${appspawn_path}/modules/sandbox", "${appspawn_path}/util/include", ] @@ -52,8 +52,8 @@ if (!defined(ohos_lite)) { public_configs = [ ":exported_header_files" ] version_script = "libappspawn_client.versionscript" - deps = [ "//third_party/cJSON:cjson" ] external_deps = [ + "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", "hilog:libhilog", diff --git a/interfaces/innerkits_new/client/appspawn_client.c b/interfaces/innerkits_new/client/appspawn_client.c index 64a0a50d..e54790b5 100644 --- a/interfaces/innerkits_new/client/appspawn_client.c +++ b/interfaces/innerkits_new/client/appspawn_client.c @@ -253,6 +253,10 @@ int AppSpawnClientDestroy(AppSpawnClientHandle handle) } pthread_mutex_unlock(&g_mutex); pthread_mutex_destroy(&reqMgr->mutex); + if (reqMgr->socketId >= 0) { + CloseClientSocket(reqMgr->socketId); + reqMgr->socketId = -1; + } free(reqMgr); return 0; } diff --git a/interfaces/innerkits_new/client/appspawn_msg.c b/interfaces/innerkits_new/client/appspawn_msg.c index 763437d0..b71beafd 100644 --- a/interfaces/innerkits_new/client/appspawn_msg.c +++ b/interfaces/innerkits_new/client/appspawn_msg.c @@ -274,6 +274,8 @@ static int CreateBaseMsg(AppSpawnReqMsgNode *reqNode, uint32_t msgType, const ch APPSPAWN_CHECK_ONLY_EXPER(msgType == MSG_APP_SPAWN || msgType == MSG_SPAWN_NATIVE_PROCESS, return 0); ret = SetFlagsTlv(reqNode, block, &reqNode->msgFlags, TLV_MSG_FLAGS, MAX_FLAGS_INDEX); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); + int maxCount = GetMaxPermissionIndex(); + APPSPAWN_CHECK(maxCount > 0, return APPSPAWN_SYSTEM_ERROR, "Invalid max for permission %{public}s", processName); ret = SetFlagsTlv(reqNode, block, &reqNode->permissionFlags, TLV_PERMISSION, GetMaxPermissionIndex()); APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); APPSPAWN_LOGV("CreateBaseMsg msgLen: %{public}u %{public}u", reqNode->msg->msgLen, block->currentIndex); diff --git a/interfaces/innerkits_new/client/libappspawn_client.versionscript b/interfaces/innerkits_new/client/libappspawn_client.versionscript index 3af4270f..82956afa 100644 --- a/interfaces/innerkits_new/client/libappspawn_client.versionscript +++ b/interfaces/innerkits_new/client/libappspawn_client.versionscript @@ -31,6 +31,9 @@ AppSpawnReqMsgSetFlags; AppSpawnReqMsgAddStringInfo; AppSpawnTerminateMsgCreate; + GetPermissionIndex; + GetMaxPermissionIndex; + GetPermissionByIndex; local: *; }; diff --git a/interfaces/innerkits_new/include/appspawn.h b/interfaces/innerkits_new/include/appspawn.h index b6bfb232..bf36eb24 100644 --- a/interfaces/innerkits_new/include/appspawn.h +++ b/interfaces/innerkits_new/include/appspawn.h @@ -32,6 +32,8 @@ extern "C" { * 如果调用AppSpawnClientSendMsg后,消息句柄不需要处理 * 否则需要调用 AppSpawnReqMsgFree 释放句柄 * + * 所有字符串输入的接口,只能接受合法的字符串,输入null、""、和大于合法长度的字符串都返回错误 + * */ typedef void *AppSpawnReqMsgHandle; @@ -41,6 +43,7 @@ typedef void *AppSpawnReqMsgHandle; */ typedef void *AppSpawnClientHandle; +#define INVALID_PERMISSION_INDEX (-1) #define INVALID_REQ_HANDLE NULL #define NWEBSPAWN_SERVER_NAME "nwebspawn" #define APPSPAWN_SERVER_NAME "appspawn" @@ -239,6 +242,30 @@ int AppSpawnReqMsgAddExtInfo(AppSpawnReqMsgHandle reqHandle, const char *name, c * @return if succeed return 0,else return other value */ int AppSpawnReqMsgAddStringInfo(AppSpawnReqMsgHandle reqHandle, const char *name, const char *value); + +/** + * @brief Get the permission index by permission name + * + * @param permission permission name + * @return int32_t permission index, if not exit, return INVALID_PERMISSION_INDEX + */ +int32_t GetPermissionIndex(const char *permission); + +/** + * @brief Get the max permission Index + * + * @return int32_t max permission Index + */ +int32_t GetMaxPermissionIndex(void); + +/** + * @brief Get the permission name by index + * + * @param index permission index + * @return const char* permission name + */ +const char *GetPermissionByIndex(int32_t index); + #ifdef __cplusplus } #endif diff --git a/interfaces/innerkits_new/module_engine/include/appspawn_hook.h b/interfaces/innerkits_new/module_engine/include/appspawn_hook.h index c3e1b103..64e26643 100644 --- a/interfaces/innerkits_new/module_engine/include/appspawn_hook.h +++ b/interfaces/innerkits_new/module_engine/include/appspawn_hook.h @@ -33,8 +33,8 @@ extern "C" { typedef struct TagAppSpawnMgr AppSpawnMgr; typedef struct TagAppSpawningCtx AppSpawningCtx; -typedef struct TagAppSpawnContent AppSpawnContent; -typedef struct TagAppSpawnClient AppSpawnClient; +typedef struct AppSpawnContent AppSpawnContent; +typedef struct AppSpawnClient AppSpawnClient; typedef struct TagAppSpawnedProcess AppSpawnedProcess; typedef enum { diff --git a/interfaces/innerkits_new/permission/appspawn_mount_permission.cpp b/interfaces/innerkits_new/permission/appspawn_mount_permission.c old mode 100644 new mode 100755 similarity index 64% rename from interfaces/innerkits_new/permission/appspawn_mount_permission.cpp rename to interfaces/innerkits_new/permission/appspawn_mount_permission.c index 8ab75c21..ec77b5fa --- a/interfaces/innerkits_new/permission/appspawn_mount_permission.cpp +++ b/interfaces/innerkits_new/permission/appspawn_mount_permission.c @@ -1,128 +1,115 @@ -/* - * Copyright (c) 2024 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_mount_permission.h" - -#include -#include -#include - -#include "appspawn_sandbox.h" -#include "appspawn_utils.h" -#include "json_utils.h" - -static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; -static int32_t g_maxPermissionIndex = -1; -static SandboxSection g_permissionQueue; - -static int PermissionNodeCompareProc(ListNode *node, ListNode *newNode) -{ - SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxNode, node); - SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxNode, node); - return strcmp(permissionNode->name, newPermissionNode->name); -} - -static int ParsePermissionConfig(const cJSON *permissionConfigs) -{ - cJSON *config = nullptr; - cJSON_ArrayForEach(config, permissionConfigs) - { - const char *name = config->string; - APPSPAWN_LOGV("ParsePermissionConfig %{public}s", name); - SandboxPermissionNode *node = CreateSandboxPermissionNode(name, 0, NULL); - APPSPAWN_CHECK_ONLY_EXPER(node != NULL, return -1); - // success, insert queue - OH_ListAddWithOrder(&g_permissionQueue.front, &node->sandboxNode.node, PermissionNodeCompareProc); - } - return 0; -} - -static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, AppSpawnSandbox *context) -{ - cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission"); - APPSPAWN_CHECK(configs != nullptr && cJSON_IsArray(configs), return 0, "No permission in json"); - - int ret = 0; - uint32_t configSize = cJSON_GetArraySize(configs); - for (uint32_t i = 0; i < configSize; i++) { - cJSON *json = cJSON_GetArrayItem(configs, i); - ret = ParsePermissionConfig(json); - APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret); - } - return ret; -} - -static int LoadPermissionConfig(void) -{ - int ret = ParseSandboxConfig("etc/sandbox", "/appdata-sandbox.json", ParseAppSandboxConfig, nullptr); - if (ret == APPSPAWN_SANDBOX_NONE) { - APPSPAWN_LOGW("No sandbox config"); - ret = 0; - } - APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); - g_maxPermissionIndex = PermissionRenumber(&g_permissionQueue); - return 0; -} - -int32_t GetPermissionIndex(const char *permission) -{ - return GetPermissionIndexInQueue(&g_permissionQueue, permission); -} - -int32_t GetMaxPermissionIndex(void) -{ - return g_maxPermissionIndex; -} - -const SandboxPermissionNode *GetPermissionNode(const char *permission) -{ - return GetPermissionNodeInQueue(&g_permissionQueue, permission); -} - -const SandboxPermissionNode *GetPermissionNodeByIndex(int32_t index) -{ - if (g_maxPermissionIndex <= index) { - return nullptr; - } - return GetPermissionNodeInQueueByIndex(&g_permissionQueue, index); -} - -static void LoadPermission(void) -{ - pthread_mutex_lock(&g_mutex); - if (g_maxPermissionIndex == -1) { - OH_ListInit(&g_permissionQueue.front); - g_permissionQueue.type = SANDBOX_TAG_PERMISSION_QUEUE; - LoadPermissionConfig(); - } - pthread_mutex_unlock(&g_mutex); -} - -static void DeletePermissions(void) -{ - pthread_mutex_lock(&g_mutex); - OH_ListRemoveAll(&g_permissionQueue.front, NULL); - g_maxPermissionIndex = -1; - pthread_mutex_unlock(&g_mutex); -} - -__attribute__((constructor)) static void LoadPermissionModule(void) -{ - LoadPermission(); -} - -__attribute__((destructor)) static void DeletePermissionModule(void) -{ - DeletePermissions(); +/* + * Copyright (c) 2024 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 +#include + +#include "appspawn_mount_permission.h" +#include "appspawn_msg.h" +#include "appspawn_permission.h" +#include "appspawn_utils.h" +#include "cJSON.h" +#include "securec.h" + +static pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER; +static int32_t g_maxPermissionIndex = -1; +static SandboxQueue g_permissionQueue = {0}; + +static int ParsePermissionConfig(const cJSON *permissionConfigs) +{ + cJSON *config = NULL; + cJSON_ArrayForEach(config, permissionConfigs) + { + const char *name = config->string; + APPSPAWN_LOGV("ParsePermissionConfig %{public}s", name); + int ret = AddSandboxPermissionNode(name, &g_permissionQueue); + APPSPAWN_CHECK_ONLY_EXPER(ret == 0, return ret); + } + return 0; +} + +static int ParseAppSandboxConfig(const cJSON *appSandboxConfig, ParseJsonContext *context) +{ + cJSON *configs = cJSON_GetObjectItemCaseSensitive(appSandboxConfig, "permission"); + APPSPAWN_CHECK(configs != NULL && cJSON_IsArray(configs), return 0, "No permission in json"); + + int ret = 0; + uint32_t configSize = cJSON_GetArraySize(configs); + for (uint32_t i = 0; i < configSize; i++) { + cJSON *json = cJSON_GetArrayItem(configs, i); + ret = ParsePermissionConfig(json); + APPSPAWN_CHECK(ret == 0, return ret, "Parse permission config fail result: %{public}d ", ret); + } + return ret; +} + +static int LoadPermissionConfig(void) +{ + int ret = ParseJsonConfig("etc/sandbox", APP_SANDBOX_FILE_NAME, ParseAppSandboxConfig, NULL); + if (ret == APPSPAWN_SANDBOX_NONE) { + APPSPAWN_LOGW("No sandbox config"); + ret = 0; + } + APPSPAWN_CHECK(ret == 0, return ret, "Load sandbox fail"); + g_maxPermissionIndex = PermissionRenumber(&g_permissionQueue); + return 0; +} + +int32_t GetPermissionIndex(const char *permission) +{ + APPSPAWN_CHECK_ONLY_EXPER(permission != NULL && g_maxPermissionIndex > 0, return INVALID_PERMISSION_INDEX); + return GetPermissionIndexInQueue(&g_permissionQueue, permission); +} + +int32_t GetMaxPermissionIndex(void) +{ + return g_maxPermissionIndex; +} + +const char *GetPermissionByIndex(int32_t index) +{ + if (g_maxPermissionIndex <= index) { + return NULL; + } + const SandboxPermissionNode *node = GetPermissionNodeInQueueByIndex(&g_permissionQueue, index); + return node == NULL ? NULL : node->name; +} + +static void LoadPermission(void) +{ + pthread_mutex_lock(&g_mutex); + if (g_maxPermissionIndex == -1) { + OH_ListInit(&g_permissionQueue.front); + LoadPermissionConfig(); + } + pthread_mutex_unlock(&g_mutex); +} + +static void DeletePermissions(void) +{ + pthread_mutex_lock(&g_mutex); + OH_ListRemoveAll(&g_permissionQueue.front, NULL); + g_maxPermissionIndex = -1; + pthread_mutex_unlock(&g_mutex); +} + +__attribute__((constructor)) static void LoadPermissionModule(void) +{ + LoadPermission(); +} + +__attribute__((destructor)) static void DeletePermissionModule(void) +{ + DeletePermissions(); } \ No newline at end of file diff --git a/interfaces/innerkits_new/permission/appspawn_mount_permission.h b/interfaces/innerkits_new/permission/appspawn_mount_permission.h index 12aaceed..a1ae303c 100644 --- a/interfaces/innerkits_new/permission/appspawn_mount_permission.h +++ b/interfaces/innerkits_new/permission/appspawn_mount_permission.h @@ -13,22 +13,38 @@ * limitations under the License. */ -#ifndef APPSPAWN_MOUNT_PERMISSION_H -#define APPSPAWN_MOUNT_PERMISSION_H +#ifndef APPSPAWN_CLIENT_MOUNT_PERMISSION_H +#define APPSPAWN_CLIENT_MOUNT_PERMISSION_H #include #include #include +#include "list.h" + #ifdef __cplusplus extern "C" { #endif -typedef struct TagPermissionNode PermissionNode; -int32_t GetPermissionIndex(const char *permission); -int32_t GetMaxPermissionIndex(void); -const PermissionNode *GetPermissionNode(const char *permission); -const PermissionNode *GetPermissionNodeByIndex(int32_t index); + +typedef struct TagSandboxSection { + struct ListNode front; + uint32_t type; +} SandboxQueue; + +typedef struct TagParseJsonContext { + uint32_t type; +} ParseJsonContext; + +typedef struct { + struct ListNode node; +} SandboxMountNode; + +typedef struct TagPermissionNode { + SandboxMountNode sandboxNode; + uint32_t permissionIndex; + char name[0]; +} SandboxPermissionNode; #ifdef __cplusplus } #endif -#endif // APPSPAWN_MOUNT_PERMISSION_H +#endif // APPSPAWN_CLIENT_MOUNT_PERMISSION_H diff --git a/lite/appspawn_process.c b/lite/appspawn_process.c index 5fe02da8..c65764b8 100644 --- a/lite/appspawn_process.c +++ b/lite/appspawn_process.c @@ -80,14 +80,14 @@ static int SetCapability(unsigned int capsCnt, const unsigned int *caps) return 0; } -static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client, +static int SetProcessName(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen) { AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; return prctl(PR_SET_NAME, appProperty->message.bundleName); } -static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetKeepCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) { APPSPAWN_LOGE("SetKeepCapabilities"); #ifdef __LINUX__ @@ -99,7 +99,7 @@ static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient return 0; } -static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetUidGid(struct AppSpawnContent *content, AppSpawnClient *client) { AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; APPSPAWN_LOGE("SetUidGid %d %d", appProperty->message.uID, appProperty->message.gID); @@ -128,7 +128,7 @@ static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) return 0; } -static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) { AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt); diff --git a/modules/sandbox/appspawn_permission.c b/modules/sandbox/appspawn_permission.c new file mode 100755 index 00000000..f5bf8d11 --- /dev/null +++ b/modules/sandbox/appspawn_permission.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2024 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_permission.h" +#include "appspawn_utils.h" +#include "appspawn_msg.h" +#include "securec.h" +#include "interfaces/innerkits_new/permission/appspawn_mount_permission.h" + +static int PermissionNodeCompareIndex(ListNode *node, void *data) +{ + SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); + return permissionNode->permissionIndex - *(int32_t *)data; +} + +static int PermissionNodeCompareName(ListNode *node, void *data) +{ + SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); + return strcmp(permissionNode->name, (char *)data); +} + +static int PermissionNodeCompareProc(ListNode *node, ListNode *newNode) +{ + SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); + SandboxPermissionNode *newPermissionNode = (SandboxPermissionNode *)ListEntry(newNode, SandboxMountNode, node); + return strcmp(permissionNode->name, newPermissionNode->name); +} + +int AddSandboxPermissionNode(const char *name, SandboxQueue *queue) +{ + size_t len = APPSPAWN_ALIGN(strlen(name) + 1) + sizeof(SandboxPermissionNode); + SandboxPermissionNode *node = (SandboxPermissionNode *)calloc(1, len); + APPSPAWN_CHECK(node != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create permission node"); + OH_ListInit(&node->sandboxNode.node); + node->permissionIndex = 0; + int ret = strcpy_s(node->name, len, name); + APPSPAWN_CHECK(ret == 0, free(node); + return APPSPAWN_SYSTEM_ERROR, "Failed to copy name"); + OH_ListAddWithOrder(&queue->front, &node->sandboxNode.node, PermissionNodeCompareProc); + return 0; +} + +int32_t PermissionRenumber(SandboxQueue *queue) +{ + ListNode *node = queue->front.next; + int index = -1; + while (node != &queue->front) { + SandboxPermissionNode *permissionNode = (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); + permissionNode->permissionIndex = ++index; + APPSPAWN_LOGV("Permission index %{public}d name %{public}s", + permissionNode->permissionIndex, permissionNode->name); + node = node->next; + } + return index + 1; +} + +const SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission) +{ + if (queue == NULL || permission == NULL) { + return NULL; + } + ListNode *node = OH_ListFind(&queue->front, (void *)permission, PermissionNodeCompareName); + return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); +} + +const SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index) +{ + if (queue == NULL) { + return NULL; + } + ListNode *node = OH_ListFind(&queue->front, (void *)&index, PermissionNodeCompareIndex); + return (SandboxPermissionNode *)ListEntry(node, SandboxMountNode, node); +} + +int32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission) +{ + const SandboxPermissionNode *permissionNode = GetPermissionNodeInQueue(queue, permission); + return permissionNode == NULL ? INVALID_PERMISSION_INDEX : permissionNode->permissionIndex; +} \ No newline at end of file diff --git a/modules/sandbox/appspawn_permission.h b/modules/sandbox/appspawn_permission.h new file mode 100755 index 00000000..f0e60efa --- /dev/null +++ b/modules/sandbox/appspawn_permission.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 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_SANDBOX_PERMISSION_H +#define APPSPAWN_SANDBOX_PERMISSION_H +#include +#include +#include + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define APP_SANDBOX_FILE_NAME "/appdata-sandbox.json" +typedef struct TagSandboxSection SandboxQueue; +typedef struct TagPermissionNode SandboxPermissionNode; + +int32_t AddSandboxPermissionNode(const char *name, SandboxQueue *queue); +int32_t GetPermissionIndexInQueue(SandboxQueue *queue, const char *permission); +const SandboxPermissionNode *GetPermissionNodeInQueue(SandboxQueue *queue, const char *permission); +const SandboxPermissionNode *GetPermissionNodeInQueueByIndex(SandboxQueue *queue, int32_t index); +const SandboxPermissionNode *GetPermissionNode(const char *permission); +int32_t PermissionRenumber(SandboxQueue *queue); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_SANDBOX_PERMISSION_H diff --git a/service/hnp/BUILD.gn b/service/hnp/BUILD.gn index e5a867ed..fd65c86e 100644 --- a/service/hnp/BUILD.gn +++ b/service/hnp/BUILD.gn @@ -29,9 +29,9 @@ if (!defined(ohos_lite)) { ] configs = [] cflags = [] - deps = [ "//third_party/cJSON:cjson" ] external_deps = [ "bounds_checking_function:libsec_shared", + "cJSON:cjson", "hilog:libhilog", "zlib:shared_libz", ] @@ -54,9 +54,10 @@ if (!defined(ohos_lite)) { ] configs = [] cflags = [] - deps = [ "//third_party/cJSON:cjson" ] + external_deps = [ "bounds_checking_function:libsec_shared", + "cJSON:cjson", "hilog:libhilog", "zlib:shared_libz", ] diff --git a/standard/appspawn_msgmgr.c b/standard/appspawn_msgmgr.c new file mode 100755 index 00000000..5c661119 --- /dev/null +++ b/standard/appspawn_msgmgr.c @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include + +#include "interfaces/innerkits/include/appspawn_msg.h" +#include "interfaces/innerkits_new/include/appspawn.h" +#include "interfaces/innerkits_new/module_engine/include/appspawn_msg.h" +#include "appspawn_service.h" +#include "appspawn_utils.h" +#include "securec.h" + +#define INVALID_OFFSET 0xffffffff + +void *GetAppSpawnMsgInfo(const AppSpawnMsgNode *message, int type) +{ + APPSPAWN_CHECK(type < TLV_MAX, return NULL, "Invalid tlv type %{public}u", type); + APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return NULL); + APPSPAWN_CHECK_ONLY_EXPER(message->tlvOffset[type] != INVALID_OFFSET, return NULL); + return (void *)(message->buffer + message->tlvOffset[type] + sizeof(AppSpawnTlv)); +} + +void *GetAppSpawnMsgExtInfo(const AppSpawnMsgNode *message, const char *name, uint32_t *len) +{ + APPSPAWN_CHECK(name != NULL, return NULL, "Invalid name "); + APPSPAWN_CHECK_ONLY_EXPER(message != NULL && message->buffer != NULL, return NULL); + + APPSPAWN_LOGV("GetAppSpawnMsgExtInfo tlvCount %{public}d name %{public}s", message->tlvCount, name); + for (uint32_t index = TLV_MAX; index < (TLV_MAX + message->tlvCount); index++) { + if (message->tlvOffset[index] == INVALID_OFFSET) { + return NULL; + } + uint8_t *data = message->buffer + message->tlvOffset[index]; + if (((AppSpawnTlv *)data)->tlvType != TLV_MAX) { + continue; + } + AppSpawnTlvExt *tlv = (AppSpawnTlvExt *)data; + if (strcmp(tlv->tlvName, name) != 0) { + continue; + } + if (len != NULL) { + *len = tlv->dataLen; + } + return data + sizeof(AppSpawnTlvExt); + } + return NULL; +} + +int CheckAppSpawnMsgFlag(const AppSpawnMsgNode *message, uint32_t type, uint32_t index) +{ + AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, type); + APPSPAWN_CHECK(msgFlags != NULL, + return 0, "No tlv %{public}u in msg %{public}s", type, message->msgHeader.processName); + uint32_t blockIndex = index / 32; // 32 max bit in int + uint32_t bitIndex = index % 32; // 32 max bit in int + APPSPAWN_CHECK(blockIndex < msgFlags->count, return 0, + "Invalid index %{public}d max: %{public}d", index, msgFlags->count); + return CHECK_FLAGS_BY_INDEX(msgFlags->flags[blockIndex], bitIndex); +} + +static AppSpawnMsgNode *CreateAppSpawnMsg(void) +{ + AppSpawnMsgNode *message = (AppSpawnMsgNode *)calloc(1, sizeof(AppSpawnMsgNode)); + APPSPAWN_CHECK(message != NULL, return NULL, "Failed to create message"); + message->buffer = NULL; + message->tlvOffset = NULL; + (void)memset_s(&message->msgHeader, sizeof(message->msgHeader), 0, sizeof(message->msgHeader)); + return message; +} + +void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode) +{ + if (msgNode == NULL) { + return; + } + if (msgNode->buffer) { + free(msgNode->buffer); + msgNode->buffer = NULL; + } + if (msgNode->tlvOffset) { + free(msgNode->tlvOffset); + msgNode->tlvOffset = NULL; + } + free(msgNode); +} + +static inline int CheckRecvMsg(const AppSpawnMsg *msg) +{ + APPSPAWN_CHECK(msg != NULL, return -1, "Invalid msg"); + APPSPAWN_CHECK(msg->magic == APPSPAWN_MSG_MAGIC, return -1, "Invalid magic 0x%{public}x", msg->magic); + APPSPAWN_CHECK(msg->msgLen < MAX_MSG_TOTAL_LENGTH, return -1, "Message too long %{public}u", msg->msgLen); + APPSPAWN_CHECK(msg->msgLen >= sizeof(AppSpawnMsg), return -1, "Message too long %{public}u", msg->msgLen); + APPSPAWN_CHECK(msg->tlvCount < MAX_TLV_COUNT, return -1, "Message too long %{public}u", msg->tlvCount); + APPSPAWN_CHECK(msg->tlvCount < (msg->msgLen / sizeof(AppSpawnTlv)), + return -1, "Message too long %{public}u", msg->tlvCount); + return 0; +} + +static int AppSpawnMsgRebuild(AppSpawnMsgNode *message, const AppSpawnMsg *msg) +{ + APPSPAWN_CHECK_ONLY_EXPER(CheckRecvMsg(&message->msgHeader) == 0, return APPSPAWN_MSG_INVALID); + if (msg->msgLen == sizeof(message->msgHeader)) { // only has msg header + return 0; + } + if (message->buffer == NULL) { + message->buffer = calloc(1, msg->msgLen - sizeof(message->msgHeader)); + APPSPAWN_CHECK(message->buffer != NULL, return -1, "Failed to alloc memory for recv message"); + } + if (message->tlvOffset == NULL) { + uint32_t totalCount = msg->tlvCount + TLV_MAX; + message->tlvOffset = malloc(totalCount * sizeof(uint32_t)); + APPSPAWN_CHECK(message->tlvOffset != NULL, return -1, "Failed to alloc memory for recv message"); + for (uint32_t i = 0; i < totalCount; i++) { + message->tlvOffset[i] = INVALID_OFFSET; + } + } + return 0; +} + +int CheckAppSpawnMsg(const AppSpawnMsgNode *message) +{ + APPSPAWN_CHECK(strlen(message->msgHeader.processName) > 0, + return APPSPAWN_MSG_INVALID, "Invalid property processName %{public}s", message->msgHeader.processName); + APPSPAWN_CHECK(message->tlvOffset != NULL, + return APPSPAWN_MSG_INVALID, "Invalid property tlv offset for %{public}s", message->msgHeader.processName); + APPSPAWN_CHECK(message->buffer != NULL, + return APPSPAWN_MSG_INVALID, "Invalid property buffer for %{public}s", message->msgHeader.processName); + + if (message->tlvOffset[TLV_BUNDLE_INFO] == INVALID_OFFSET || + message->tlvOffset[TLV_MSG_FLAGS] == INVALID_OFFSET || + message->tlvOffset[TLV_ACCESS_TOKEN_INFO] == INVALID_OFFSET || + message->tlvOffset[TLV_DAC_INFO] == INVALID_OFFSET) { + APPSPAWN_LOGE("No must tlv: %{public}u %{public}u %{public}u", message->tlvOffset[TLV_BUNDLE_INFO], + message->tlvOffset[TLV_MSG_FLAGS], message->tlvOffset[TLV_DAC_INFO]); + return APPSPAWN_MSG_INVALID; + } + AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(message, TLV_BUNDLE_INFO); + if (bundleInfo != NULL) { + if (strstr(bundleInfo->bundleName, "\\") != NULL || strstr(bundleInfo->bundleName, "/") != NULL) { + APPSPAWN_LOGE("Invalid bundle name %{public}s", bundleInfo->bundleName); + return APPSPAWN_MSG_INVALID; + } + } + return 0; +} + +static int CheckExtTlvInfo(const AppSpawnTlv *tlv, uint32_t remainLen) +{ + AppSpawnTlvExt *tlvExt = (AppSpawnTlvExt *)(tlv); + APPSPAWN_LOGV("Recv type [%{public}s %{public}u] real len: %{public}u", + tlvExt->tlvName, tlvExt->tlvLen, tlvExt->dataLen); + if (tlvExt->dataLen > tlvExt->tlvLen - sizeof(AppSpawnTlvExt)) { + APPSPAWN_LOGE("Invalid tlv [%{public}s %{public}u] real len: %{public}u %{public}u", + tlvExt->tlvName, tlvExt->tlvLen, tlvExt->dataLen, sizeof(AppSpawnTlvExt)); + return APPSPAWN_MSG_INVALID; + } + return 0; +} + +static int CheckMsgTlv(const AppSpawnTlv *tlv, uint32_t remainLen) +{ + uint32_t tlvLen = 0; + switch (tlv->tlvType) { + case TLV_MSG_FLAGS: + tlvLen = ((AppSpawnMsgFlags *)(tlv + 1))->count * sizeof(uint32_t); + break; + case TLV_ACCESS_TOKEN_INFO: + tlvLen = sizeof(AppSpawnMsgAccessToken); + break; + case TLV_DAC_INFO: + tlvLen = sizeof(AppSpawnMsgDacInfo); + break; + case TLV_BUNDLE_INFO: + APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= (sizeof(AppSpawnMsgBundleInfo) + APP_LEN_BUNDLE_NAME), + return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen); + break; + case TLV_OWNER_INFO: + APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= APP_OWNER_ID_LEN, + return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen); + break; + case TLV_DOMAIN_INFO: + APPSPAWN_CHECK((tlv->tlvLen - sizeof(AppSpawnTlv)) <= (APP_APL_MAX_LEN + sizeof(AppSpawnMsgDomainInfo)), + return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen); + break; + case TLV_MAX: + return CheckExtTlvInfo(tlv, remainLen); + default: + break; + } + APPSPAWN_CHECK(tlvLen <= tlv->tlvLen, + return APPSPAWN_MSG_INVALID, "Invalid property tlv %{public}d %{public}d ", tlv->tlvType, tlv->tlvLen); + return 0; +} + +int DecodeAppSpawnMsg(AppSpawnMsgNode *message) +{ + int ret = 0; + uint32_t tlvCount = 0; + uint32_t bufferLen = message->msgHeader.msgLen - sizeof(AppSpawnMsg); + uint32_t currLen = 0; + while (currLen < bufferLen) { + AppSpawnTlv *tlv = (AppSpawnTlv *)(message->buffer + currLen); + APPSPAWN_CHECK(tlv->tlvLen <= (bufferLen - currLen), break, + "Invalid tlv [%{public}d %{public}d] curr: %{public}u", + tlv->tlvType, tlv->tlvLen, currLen + sizeof(AppSpawnMsg)); + + APPSPAWN_LOGV("DecodeAppSpawnMsg tlv %{public}u %{public}u start: %{public}u ", + tlv->tlvType, tlv->tlvLen, currLen + sizeof(AppSpawnMsg)); // show in msg offset + ret = CheckMsgTlv(tlv, bufferLen - currLen); + APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); + + if (tlv->tlvType < TLV_MAX) { // normal + message->tlvOffset[tlv->tlvType] = currLen; + currLen += tlv->tlvLen; + } else { + APPSPAWN_CHECK(tlvCount < message->msgHeader.tlvCount, break, + "Invalid tlv number tlv %{public}d tlvCount: %{public}d", tlv->tlvType, tlvCount); + message->tlvOffset[TLV_MAX + tlvCount] = currLen; + tlvCount++; + currLen += tlv->tlvLen; + } + } + APPSPAWN_CHECK_ONLY_EXPER(currLen >= bufferLen, return APPSPAWN_MSG_INVALID); + // save real ext tlv count + message->tlvCount = tlvCount; + return 0; +} + +int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen, + AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder) +{ + *reminder = 0; + AppSpawnMsgNode *message = *outMsg; + if (message == NULL) { + message = CreateAppSpawnMsg(); + APPSPAWN_CHECK(message != NULL, return APPSPAWN_SYSTEM_ERROR, "Failed to create message"); + *outMsg = message; + } + + uint32_t reminderLen = bufferLen; + const uint8_t *reminderBuffer = buffer; + if (*msgRecvLen < sizeof(AppSpawnMsg)) { // recv partial message + if ((bufferLen + *msgRecvLen) >= sizeof(AppSpawnMsg)) { + int ret = memcpy_s(((uint8_t *)&message->msgHeader) + *msgRecvLen, + sizeof(message->msgHeader) - *msgRecvLen, + buffer, sizeof(message->msgHeader) - *msgRecvLen); + APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer"); + + ret = AppSpawnMsgRebuild(message, &message->msgHeader); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc buffer for receive msg"); + reminderLen = bufferLen - (sizeof(message->msgHeader) - *msgRecvLen); + reminderBuffer = buffer + sizeof(message->msgHeader) - *msgRecvLen; + *msgRecvLen = sizeof(message->msgHeader); + } else { + int ret = memcpy_s(((uint8_t *)&message->msgHeader) + *msgRecvLen, + sizeof(message->msgHeader) - *msgRecvLen, buffer, bufferLen); + APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer"); + *msgRecvLen += bufferLen; + return 0; + } + } + // do not copy msg header + uint32_t realCopy = (reminderLen + *msgRecvLen) > message->msgHeader.msgLen ? + message->msgHeader.msgLen - *msgRecvLen : reminderLen; + if (message->buffer == NULL) { // only has msg header + return 0; + } + APPSPAWN_LOGV("HandleRecvBuffer msgRecvLen: %{public}u reminderLen %{public}u realCopy %{public}u", + *msgRecvLen, reminderLen, realCopy); + int ret = memcpy_s(message->buffer + *msgRecvLen - sizeof(message->msgHeader), + message->msgHeader.msgLen - *msgRecvLen, reminderBuffer, realCopy); + APPSPAWN_CHECK(ret == EOK, return -1, "Failed to copy recv buffer"); + *msgRecvLen += realCopy; + if (realCopy < reminderLen) { + *reminder = reminderLen - realCopy; + } + return 0; +} + +pid_t GetPidFromTerminationMsg(AppSpawnMsgNode *message) +{ + pid_t *pid = (pid_t *)GetAppSpawnMsgInfo(message, TLV_RENDER_TERMINATION_INFO); + if (pid != NULL) { + return *pid; + } + return -1; +} + +static int ChangeAppSpawnMsgExt2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty) +{ + static const char *extInfoNames[] = { "HspList", "Overlay", "DataGroup", "AppEnv"}; + static const char *extraNames[] = { "|HspList|", "|Overlay|", "|DataGroup|", "|AppEnv|"}; + char *data[sizeof(extInfoNames) / sizeof(extInfoNames[0])] = {}; + + AppSpawnMsgDacInfo *dacInfo = (AppSpawnMsgDacInfo *)GetAppSpawnMsgInfo(message, TLV_DAC_INFO); + if (dacInfo != NULL) { + appProperty->property.uid = dacInfo->uid; + appProperty->property.gid = dacInfo->gid; + appProperty->property.gidCount = dacInfo->gidCount; + for (uint32_t i = 0; i < dacInfo->gidCount; i++) { + appProperty->property.gidTable[i] = dacInfo->gidTable[i]; + } + } + + ExtraInfo *extraInfo = &appProperty->property.extraInfo; + uint32_t totalLength = 0; + uint32_t currLen = 0; + uint32_t nameCount = sizeof(extInfoNames) / sizeof(extInfoNames[0]); + for (uint32_t i = 0; i < nameCount; i++) { + currLen = 0; + data[i] = (char *)GetAppSpawnMsgExtInfo(message, extInfoNames[i], &currLen); + if (data[i]) { + totalLength += currLen + strlen(extraNames[i]) * 2 + 1; // 2 format |type1|...|type1|type2|...|type2| + } + } + if (totalLength == 0) { + return 0; + } + + extraInfo->data = (char *)calloc(1, totalLength); + APPSPAWN_CHECK(extraInfo->data != NULL, return -1, "Failed to alloc mem for extra"); + currLen = 0; + for (uint32_t i = 0; i < nameCount; i++) { + if (data[i] == NULL) { + continue; + } + int len = snprintf_s(extraInfo->data + currLen, totalLength - currLen, totalLength - currLen - 1, + "%s%s%s", extraNames[i], data[i], extraNames[i]); + if (len <= 0) { + free(extraInfo->data); + extraInfo->data = NULL; + return 0; + } + currLen += len; + } + extraInfo->totalLength = currLen; + extraInfo->savedLength = currLen; + APPSPAWN_LOGV("extraInfo %{public}s", extraInfo->data); + return 0; +} + +int ChangeAppSpawnMsg2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty) +{ + APPSPAWN_CHECK_ONLY_EXPER(message != NULL && appProperty != NULL, return -1); + int ret = 0; + do { + appProperty->property.code = (AppOperateType)message->msgHeader.msgType; + ret = strcpy_s(appProperty->property.processName, APP_LEN_PROC_NAME, message->msgHeader.processName); + APPSPAWN_CHECK(ret == 0, break, "Failed to copy processName"); + ret = DecodeAppSpawnMsg(message); + APPSPAWN_CHECK(ret == 0, break, "Failed to decode message"); + AppSpawnMsgFlags *msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_MSG_FLAGS); + appProperty->property.flags = msgFlags ? *(uint32_t *)msgFlags->flags : 0; + + msgFlags = (AppSpawnMsgFlags *)GetAppSpawnMsgInfo(message, TLV_PERMISSION); + appProperty->property.mountPermissionFlags = msgFlags ? *(uint32_t *)msgFlags->flags : 0; + + AppSpawnMsgBundleInfo *bundleInfo = (AppSpawnMsgBundleInfo *)GetAppSpawnMsgInfo(message, TLV_BUNDLE_INFO); + if (bundleInfo != NULL) { + ret = strcpy_s(appProperty->property.bundleName, APP_LEN_BUNDLE_NAME, bundleInfo->bundleName); + APPSPAWN_CHECK(ret == 0, break, "Failed to copy bundle name"); + appProperty->property.bundleIndex = (int32_t)bundleInfo->bundleIndex; + } + AppSpawnMsgDomainInfo *domainInfo = (AppSpawnMsgDomainInfo *)GetAppSpawnMsgInfo(message, TLV_DOMAIN_INFO); + if (domainInfo != NULL) { + ret = strcpy_s(appProperty->property.apl, sizeof(appProperty->property.apl), domainInfo->apl); + APPSPAWN_CHECK(ret == 0, break, "Failed to copy apl"); + appProperty->property.hapFlags = domainInfo->hapFlags; + } + AppSpawnMsgOwnerId *owner = (AppSpawnMsgOwnerId *)GetAppSpawnMsgInfo(message, TLV_OWNER_INFO); + if (owner != NULL) { + ret = strcpy_s(appProperty->property.ownerId, sizeof(appProperty->property.ownerId), owner->ownerId); + APPSPAWN_CHECK(ret == 0, break, "Failed to copy ownerId"); + } + AppSpawnMsgAccessToken *token = (AppSpawnMsgAccessToken *)GetAppSpawnMsgInfo(message, TLV_ACCESS_TOKEN_INFO); + appProperty->property.accessTokenIdEx = token ? token->accessTokenIdEx : 0; + + AppSpawnMsgInternetInfo *info = (AppSpawnMsgInternetInfo *)GetAppSpawnMsgInfo(message, TLV_INTERNET_INFO); + if (info != NULL) { + appProperty->property.allowInternet = info->allowInternet; + appProperty->property.setAllowInternet = info->setAllowInternet; + } + char *renderCmd = (char *)GetAppSpawnMsgExtInfo(message, MSG_EXT_NAME_RENDER_CMD, NULL); + if (renderCmd != NULL) { + ret = strcpy_s(appProperty->property.renderCmd, sizeof(appProperty->property.renderCmd), renderCmd); + APPSPAWN_CHECK(ret == 0, break, "Failed to copy renderCmd"); + } + ret = ChangeAppSpawnMsgExt2Property(message, appProperty); + } while (0); + DeleteAppSpawnMsg(message); + return ret; +} \ No newline at end of file diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index e5a39402..6f081885 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -50,7 +50,7 @@ // ide-asan #ifndef ASAN_DETECTOR -static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetAsanEnabledEnv(struct AppSpawnContent *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; if (appProperty->code == SPAWN_NATIVE_PROCESS) { @@ -82,7 +82,7 @@ static int SetAsanEnabledEnv(struct AppSpawnContent_ *content, AppSpawnClient *c } #endif -static void SetGwpAsanEnabled(struct AppSpawnContent_ *content, AppSpawnClient *client) +static void SetGwpAsanEnabled(struct AppSpawnContent *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; char debugValue[10] = {0}; @@ -98,7 +98,7 @@ static void SetGwpAsanEnabled(struct AppSpawnContent_ *content, AppSpawnClient * } } -static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client, +static int SetProcessName(struct AppSpawnContent *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen) { AppSpawnClientExt *appPropertyExt = (AppSpawnClientExt *)client; @@ -134,7 +134,7 @@ static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *clie return 0; } -static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetKeepCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) { AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; // set keep capabilities when user not root. @@ -145,7 +145,7 @@ static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient return 0; } -static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetCapabilities(struct AppSpawnContent *content, AppSpawnClient *client) { // init cap struct __user_cap_header_struct cap_header; @@ -186,7 +186,7 @@ static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *cli return 0; } -static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *client) +static void InitDebugParams(struct AppSpawnContent *content, AppSpawnClient *client) { #ifndef APPSPAWN_TEST AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; @@ -230,7 +230,7 @@ static void ClearEnvironment(AppSpawnContent *content, AppSpawnClient *client) return; } -int SetXpmConfig(struct AppSpawnContent_ *content, AppSpawnClient *client) +int SetXpmConfig(struct AppSpawnContent *content, AppSpawnClient *client) { #ifdef CODE_SIGNATURE_ENABLE // nwebspawn no permission set xpm config @@ -256,7 +256,7 @@ int SetXpmConfig(struct AppSpawnContent_ *content, AppSpawnClient *client) return 0; } -static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int SetUidGid(struct AppSpawnContent *content, AppSpawnClient *client) { #ifdef GRAPHIC_PERMISSION_CHECK AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; @@ -298,7 +298,7 @@ static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) return 0; } -static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int32_t SetFileDescriptors(struct AppSpawnContent *content, AppSpawnClient *client) { #ifndef APPSPAWN_TEST // close stdin stdout stderr @@ -417,7 +417,7 @@ static void Free(char **argv, ExtraInfo *extraInfo) #ifdef ASAN_DETECTOR #define WRAP_VALUE_MAX_LENGTH 96 -static int GetWrapBundleNameValue(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int GetWrapBundleNameValue(struct AppSpawnContent *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; char wrapBundleNameKey[WRAP_VALUE_MAX_LENGTH] = {0}; @@ -465,7 +465,7 @@ static int EncodeAppClient(AppSpawnClient *client, char *param, int32_t originLe return 0; } -static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client) +static int ColdStartApp(struct AppSpawnContent *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; APPSPAWN_LOGI("ColdStartApp::appName %{public}s", appProperty->processName); @@ -489,12 +489,9 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client #endif ret = strcpy_s(argv[0], APP_LEN_PROC_NAME, appSpawnPath); APPSPAWN_CHECK(ret >= 0, break, "Invalid strcpy"); - ret = -1; - if (content->isNweb) { - argv[START_INDEX] = strdup(NWEBSPAWN_COLDSTART_KEY); - } else { - argv[START_INDEX] = strdup(APPSPAWN_COLDSTART_KEY); - } + (content->isNweb) ? (argv[START_INDEX] = strdup(NWEBSPAWN_COLDSTART_KEY)) : + (argv[START_INDEX] = strdup(APPSPAWN_COLDSTART_KEY)); + APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup"); argv[FD_INDEX] = strdup(buffer); APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup"); @@ -515,9 +512,7 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client #else ret = -1; #endif - if (ret) { - APPSPAWN_LOGE("Failed to execv, errno = %{public}d", errno); - } + APPSPAWN_CHECK_ONLY_LOG(ret == 0, "Failed to execv, errno = %{public}d", errno) } argv[0] = NULL; Free(argv, &appProperty->extraInfo); diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index bfdeaf05..945008b0 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -16,7 +16,6 @@ #include "appspawn_service.h" #include "appspawn_adapter.h" #include "appspawn_server.h" -#include "appspawn_msg.h" #include #include @@ -50,7 +49,6 @@ #define USER_ID_SIZE 4 static AppSpawnContentExt *g_appSpawnContent = NULL; -static const uint32_t EXTRAINFO_TOTAL_LENGTH_MAX = 32 * 1024; static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2) { @@ -140,6 +138,11 @@ static void OnClose(const TaskHandle taskHandle) APPSPAWN_CHECK(client != NULL, return, "Invalid client"); APPSPAWN_LOGI("OnClose %{public}d processName = %{public}s", client->client.id, client->property.processName); + if (client->receiverCtx.incompleteMsg) { + DeleteAppSpawnMsg(client->receiverCtx.incompleteMsg); + client->receiverCtx.incompleteMsg = NULL; + client->receiverCtx.msgRecvLen = 0; + } if (client->property.extraInfo.data != NULL) { free(client->property.extraInfo.data); client->property.extraInfo.totalLength = 0; @@ -161,14 +164,15 @@ static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle } } -static int SendResponse(AppSpawnClientExt *client, const char *buff, size_t buffSize) +static int SendResponse(AppSpawnClientExt *client, int result, pid_t pid) { - uint32_t bufferSize = buffSize; + uint32_t bufferSize = sizeof(AppSpawnResponseMsg); BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize); - char *buffer = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize); - int ret = memcpy_s(buffer, bufferSize, buff, buffSize); - APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize"); - return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize); + AppSpawnResponseMsg *buffer = (AppSpawnResponseMsg *)LE_GetBufferInfo(handle, NULL, &bufferSize); + APPSPAWN_CHECK(buffer != NULL, return -1, "Failed to get buffer"); + buffer->result.result = result; + buffer->result.pid = pid; + return LE_Send(LE_GetDefaultLoop(), client->stream, handle, bufferSize); } #ifndef APPSPAWN_TEST @@ -436,41 +440,6 @@ static void CheckColdAppEnabled(AppSpawnClientExt *appProperty) } } -static bool ReceiveRequestDataToExtraInfo(const TaskHandle taskHandle, AppSpawnClientExt *client, - const uint8_t *buffer, uint32_t buffLen) -{ - if (client->property.extraInfo.totalLength) { - ExtraInfo *extraInfo = &client->property.extraInfo; - if (extraInfo->savedLength == 0) { - extraInfo->data = (char *)malloc(extraInfo->totalLength); - APPSPAWN_CHECK(extraInfo->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: malloc extraInfo failed %{public}u", extraInfo->totalLength); - } - - uint32_t saved = extraInfo->savedLength; - uint32_t total = extraInfo->totalLength; - char *data = extraInfo->data; - - APPSPAWN_LOGI("Receiving extraInfo: (%{public}u saved + %{public}u incoming) / %{public}u total", - saved, buffLen, total); - - APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: too many data for extraInfo %{public}u ", buffLen); - - int ret = memcpy_s(data + saved, buffLen, buffer, buffLen); - APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: memcpy extraInfo failed"); - - extraInfo->savedLength += buffLen; - if (extraInfo->savedLength < extraInfo->totalLength) { - return false; - } - extraInfo->data[extraInfo->totalLength - 1] = 0; - return true; - } - return true; -} - static int CheckRequestMsgValid(AppSpawnClientExt *client) { if (client->property.extraInfo.totalLength >= EXTRAINFO_TOTAL_LENGTH_MAX) { @@ -487,44 +456,6 @@ static int CheckRequestMsgValid(AppSpawnClientExt *client) return -1; } -APPSPAWN_STATIC bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client, - const uint8_t *buffer, uint32_t buffLen) -{ - APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: Invalid buff, bufferLen:%{public}d", buffLen); - - // 1. receive AppParamter - if (client->property.extraInfo.totalLength == 0) { - APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: Invalid buffLen %{public}u", buffLen); - - int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property)); - APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "ReceiveRequestData: memcpy failed %{public}d:%{public}u", ret, buffLen); - - // reset extraInfo - client->property.extraInfo.savedLength = 0; - client->property.extraInfo.data = NULL; - - // update buffer - buffer += sizeof(client->property); - buffLen -= sizeof(client->property); - ret = CheckRequestMsgValid(client); - APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return false, "Invalid request msg"); - } - - // 2. check whether extraInfo exist - if (client->property.extraInfo.totalLength == 0) { // no extraInfo - APPSPAWN_LOGV("ReceiveRequestData: no extraInfo"); - return true; - } else if (buffLen == 0) { - APPSPAWN_LOGV("ReceiveRequestData: waiting for extraInfo"); - return false; - } - return ReceiveRequestDataToExtraInfo(taskHandle, client, buffer, buffLen); -} - static int HandleMessage(AppSpawnClientExt *appProperty) { // create pipe @@ -558,35 +489,29 @@ static int HandleMessage(AppSpawnClientExt *appProperty) info->uid = appProperty->property.uid; ProcessAppAdd(g_appSpawnContent, info); } - SendResponse(appProperty, (char *)&appProperty->pid, sizeof(appProperty->pid)); + SendResponse(appProperty, 0, appProperty->pid); } else { - SendResponse(appProperty, (char *)&result, sizeof(result)); + SendResponse(appProperty, result, 0); } return 0; } -static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) +static int ProcessRecvMsg(const TaskHandle taskHandle, AppSpawnClientExt *appProperty) { - AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle); - APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return, "alloc client Failed"); - - if (!ReceiveRequestData(taskHandle, appProperty, buffer, buffLen)) { - return; + if (CheckRequestMsgValid(appProperty)) { + return -1; } - if (g_appSpawnContent->content.isNweb) { // get render process termination status, only nwebspawn need this logic. if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) { int ret = GetProcessTerminationStatus(&appProperty->client); RemoveAppInfo(appProperty->property.pid); - SendResponse(appProperty, (char *)&ret, sizeof(ret)); - return; + SendResponse(appProperty, ret, 0); + return 0; } } APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0, - LE_CloseTask(LE_GetDefaultLoop(), taskHandle); - return, "Invalid property %{public}u", appProperty->property.gidCount); + return -1, "Invalid property %{public}u", appProperty->property.gidCount); // special handle bundle name medialibrary and scanner HandleSpecial(appProperty); @@ -596,9 +521,48 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, } appProperty->pid = 0; CheckColdAppEnabled(appProperty); - int ret = HandleMessage(appProperty); - if (ret != 0) { - LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return HandleMessage(appProperty); +} + +static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle); + APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "alloc client Failed"); + APPSPAWN_CHECK(buffLen < MAX_MSG_TOTAL_LENGTH, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Message too long %{public}u", buffLen); + + uint32_t reminder = 0; + uint32_t currLen = 0; + AppSpawnMsgNode *message = appProperty->receiverCtx.incompleteMsg; // incomplete msg + appProperty->receiverCtx.incompleteMsg = NULL; + int ret = 0; + do { + ret = GetAppSpawnMsgFromBuffer(buffer + currLen, buffLen - currLen, + &message, &appProperty->receiverCtx.msgRecvLen, &reminder); + APPSPAWN_CHECK_ONLY_EXPER(ret == 0, break); + + if (appProperty->receiverCtx.msgRecvLen != message->msgHeader.msgLen) { // recv complete msg + appProperty->receiverCtx.incompleteMsg = message; + message = NULL; + break; + } + appProperty->receiverCtx.msgRecvLen = 0; + // change msg to app property and free message + ret = ChangeAppSpawnMsg2Property(message, appProperty); + message = NULL; + if (ret == 0) { + ret = ProcessRecvMsg(taskHandle, appProperty); + } + if (ret != 0) { + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + break; + } + currLen += buffLen - reminder; + } while (reminder > 0); + + if (message) { + DeleteAppSpawnMsg(message); } } @@ -634,6 +598,8 @@ APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskH client->property.extraInfo.totalLength = 0; client->property.extraInfo.savedLength = 0; client->property.extraInfo.data = NULL; + client->receiverCtx.msgRecvLen = 0; + client->receiverCtx.incompleteMsg = NULL; APPSPAWN_LOGI("OnConnection client fd %{public}d Id %{public}d", LE_GetSocketFd(stream), client->client.id); return stream; } @@ -645,7 +611,7 @@ static int OnConnection(const LoopHandle loopHandle, const TaskHandle server) return 0; } -static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result) +static void NotifyResToParent(struct AppSpawnContent *content, AppSpawnClient *client, int result) { AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; int fd = appProperty->fd[1]; diff --git a/standard/appspawn_service.h b/standard/appspawn_service.h index 5c943f22..845bb5b1 100644 --- a/standard/appspawn_service.h +++ b/standard/appspawn_service.h @@ -18,7 +18,9 @@ #include #include -#include "appspawn_msg.h" +#include "interfaces/innerkits/include/appspawn_msg.h" +#include "interfaces/innerkits_new/include/appspawn.h" +#include "interfaces/innerkits_new/module_engine/include/appspawn_msg.h" #include "appspawn_server.h" #include "init_hashmap.h" #include "loop_event.h" @@ -47,15 +49,30 @@ extern bool may_init_gwp_asan(bool forceInit); #define EXTRA_INFO_INDEX 5 #define NULL_INDEX 6 #define PARAM_BUFFER_LEN 128 + +typedef struct TagAppSpawnMsgNode { + AppSpawnMsg msgHeader; + uint32_t tlvCount; + uint32_t *tlvOffset; + uint8_t *buffer; +} AppSpawnMsgNode; + +typedef struct TagAppSpawnMsgReceiverCtx { + uint32_t nextMsgId; + uint32_t msgRecvLen; + AppSpawnMsgNode *incompleteMsg; +} AppSpawnMsgReceiverCtx; + typedef struct { AppSpawnClient client; TaskHandle stream; int32_t fd[2]; // 2 fd count + AppSpawnMsgReceiverCtx receiverCtx; AppParameter property; pid_t pid; } AppSpawnClientExt; -typedef struct AppInfo_ { +typedef struct AppInfo { HashNode node; pid_t pid; AppOperateType code; @@ -63,7 +80,7 @@ typedef struct AppInfo_ { char name[0]; } AppInfo, AppSpawnAppInfo; -typedef struct AppSpawnContentExt_ { +typedef struct AppSpawnContentExt { AppSpawnContent content; uint32_t flags; TaskHandle server; @@ -95,6 +112,11 @@ do { \ (clientExt)->property.setAllowInternet, (clientExt)->property.allowInternet); \ } while (0) +int GetAppSpawnMsgFromBuffer(const uint8_t *buffer, uint32_t bufferLen, + AppSpawnMsgNode **outMsg, uint32_t *msgRecvLen, uint32_t *reminder); +int ChangeAppSpawnMsg2Property(AppSpawnMsgNode *message, AppSpawnClientExt *appProperty); +void DeleteAppSpawnMsg(AppSpawnMsgNode *msgNode); + #ifdef __cplusplus } #endif diff --git a/standard/main.c b/standard/main.c index 3c5be0f6..8942d417 100644 --- a/standard/main.c +++ b/standard/main.c @@ -15,7 +15,6 @@ #include #include #include "appspawn_adapter.h" -#include "appspawn_msg.h" #include "appspawn_server.h" #include "appspawn_service.h" #include "securec.h" diff --git a/test/BUILD.gn b/test/BUILD.gn index c0e1dc95..5d04b538 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -24,7 +24,10 @@ group("moduletest") { group("unittest") { if (!defined(ohos_lite)) { testonly = true - deps = [ "unittest:AppSpawn_ut" ] + deps = [ + "unittest:AppSpawn_ut", + "unittest/app_spawn_client_test:AppSpawn_client_ut", + ] deps += [ "unittest/hnp_test:HnpTest" ] } else { testonly = true diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index b6b6ce0e..422f0ddb 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -15,18 +15,45 @@ import("//base/startup/appspawn/appspawn.gni") import("//build/test.gni") ohos_executable("AppSpawnTest") { - sources = [ "${appspawn_path}/test/moduletest/appspawn_test_cmd.cpp" ] + sources = [ + "${appspawn_path}/test/moduletest/appspawn_test_cmder.cpp", + "${appspawn_path}/test/moduletest/appspawn_test_main.cpp", + "${appspawn_path}/util/src/appspawn_utils.c", + ] - configs = [ "${appspawn_path}:appspawn_config" ] + include_dirs = [ + "${appspawn_path}", + "${appspawn_path}/common", + "${appspawn_path}/standard", + "${appspawn_path}/modules/modulemgr", + "${appspawn_path}/modules/ace_adapter", + "${appspawn_path}/modules/common", + "${appspawn_path}/modules/sandbox", + "${appspawn_path}/test/moduletest/threadpool", + "${appspawn_innerkits_path}/include", + "${appspawn_innerkits_path}/client", + "${appspawn_innerkits_path}/permission", + "${appspawn_innerkits_path}/module_engine/include", + "${appspawn_path}/test/mock", + "${appspawn_path}/test/unittest", + "${appspawn_path}/util/include", + ] - deps = [ "${appspawn_path}/interfaces/innerkits:appspawn_socket_client" ] + deps = [ + "${appspawn_innerkits_path}/client:appspawn_client", + "${appspawn_path}/test/moduletest/threadpool:libappspawn_threadpool", + ] external_deps = [ + "cJSON:cjson", "c_utils:utils", + "config_policy:configpolicy_util", "hilog:libhilog", "init:libbegetutil", "zlib:libz", ] + subsystem_name = "${subsystem_name}" + part_name = "${part_name}" } ohos_moduletest("AppSpawnModuleTest") { @@ -35,39 +62,49 @@ ohos_moduletest("AppSpawnModuleTest") { sources = [ "${appspawn_path}/test/moduletest/appspawn_client_test.cpp", "${appspawn_path}/test/moduletest/appspawn_module_test.cpp", + "${appspawn_path}/test/moduletest/appspawn_test_cmder.cpp", + "${appspawn_path}/util/src/appspawn_utils.c", ] include_dirs = [ - "//commonlibrary/c_utils/base/include", - "//third_party/zlib/contrib/minizip", - "//third_party/zlib", - ] - - configs = [ - "${appspawn_path}:appspawn_config", - "${ability_runtime_path}/services/appmgr:appmgr_config", + "${appspawn_path}", + "${appspawn_path}/common", + "${appspawn_path}/standard", + "${appspawn_path}/modules/modulemgr", + "${appspawn_path}/modules/ace_adapter", + "${appspawn_path}/modules/common", + "${appspawn_path}/modules/sandbox", + "${appspawn_path}/test/moduletest/threadpool", + "${appspawn_innerkits_path}/include", + "${appspawn_innerkits_path}/client", + "${appspawn_innerkits_path}/permission", + "${appspawn_innerkits_path}/module_engine/include", + "${appspawn_path}/test/mock", + "${appspawn_path}/test/unittest", + "${appspawn_path}/util/include", ] deps = [ - "${ability_runtime_path}/services/appmgr:libappms", - "${appspawn_path}/interfaces/innerkits:appspawn_socket_client", + "${appspawn_innerkits_path}/client:appspawn_client", "//third_party/googletest:gtest_main", ] external_deps = [ - "bundle_framework:appexecfwk_base", + "cJSON:cjson", "c_utils:utils", + "config_policy:configpolicy_util", "hilog:libhilog", "init:libbegetutil", ] + subsystem_name = "${subsystem_name}" + part_name = "${part_name}" } group("moduletest") { testonly = true - - deps = [ ":AppSpawnModuleTest" ] + deps = [ + ":AppSpawnModuleTest", + ":AppSpawnTest", + ] deps += [ "hnp_sample:hnpsample" ] - if (appspawn_test_cmd) { - deps += [ ":AppSpawnTest" ] - } } diff --git a/test/moduletest/appspawn_client_test.cpp b/test/moduletest/appspawn_client_test.cpp index d1e64371..775ce5f3 100644 --- a/test/moduletest/appspawn_client_test.cpp +++ b/test/moduletest/appspawn_client_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -13,18 +13,17 @@ * limitations under the License. */ -#include "appspawn_test_client.h" - -#include "gtest/gtest.h" +#include "appspawn.h" +#include "appspawn_utils.h" #include "securec.h" +#include +using namespace testing; using namespace testing::ext; -using namespace OHOS; namespace OHOS { namespace AppSpawn { - -class AppSpawnClientTest : public testing::Test, public AppSpawnTestClient { +class AppSpawnClientTest : public testing::Test { public: static void SetUpTestCase() {} static void TearDownTestCase() {} @@ -32,317 +31,68 @@ public: void TearDown() {} }; -HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_1, TestSize.Level0) +static AppSpawnReqMsgHandle CreateMsg(AppSpawnClientHandle handle, const char *bundleName) { - int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); - EXPECT_EQ(ret, 0); + AppSpawnReqMsgHandle reqHandle = 0; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, bundleName, &reqHandle); + APPSPAWN_CHECK(ret == 0, return 0, "Failed to create req %{public}s", bundleName); + do { + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, bundleName); + APPSPAWN_CHECK(ret == 0, break, "Failed to create req %{public}s", bundleName); - 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_LT(ret, 0); - if (pid > 0) { - kill(pid, SIGKILL); - } - // close client - ClientClose(); + AppDacInfo dacInfo = {}; + dacInfo.uid = 20010029; // 20010029 test data + dacInfo.gid = 20010029; // 20010029 test data + dacInfo.gidCount = 2; // 2 count + dacInfo.gidTable[0] = 20010029; // 20010029 test data + dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data + (void)strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), "test-app-name"); + ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo); + APPSPAWN_CHECK(ret == 0, break, "Failed to add dac %{public}s", APPSPAWN_SERVER_NAME); + + AppSpawnReqMsgSetAppFlag(reqHandle, static_cast(10)); // 10 test + + ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678); // 12345678 + APPSPAWN_CHECK(ret == 0, break, "Failed to add access token %{public}s", APPSPAWN_SERVER_NAME); + + static const char *permissions[] = { + "ohos.permission.READ_IMAGEVIDEO", + "ohos.permission.FILE_CROSS_APP", + "ohos.permission.ACTIVATE_THEME_PACKAGE", + "ohos.permission.GET_WALLPAPER", + }; + size_t count = sizeof(permissions) / sizeof(permissions[0]); + for (size_t i = 0; i < count; i++) { + ret = AppSpawnReqMsgAddPermission(reqHandle, permissions[i]); + APPSPAWN_CHECK(ret == 0, break, "Failed to create req %{public}s", bundleName); + } + return reqHandle; + } while (0); + AppSpawnReqMsgFree(reqHandle); + return INVALID_REQ_HANDLE; } -HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_2, TestSize.Level0) +static AppSpawnClientHandle CreateClient(const char *serviceName) { - 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(); + AppSpawnClientHandle clientHandle = NULL; + int ret = AppSpawnClientInit(serviceName, &clientHandle); + APPSPAWN_CHECK(ret == 0, return nullptr, "Failed to create client %{public}s", serviceName); + return clientHandle; } -// 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) +HWTEST(AppSpawnClientTest, AppSpawn_Client_test001, TestSize.Level0) { - APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3"); - int ret = ClientCreateSocket("/dev/unix/socket/AppSpawn"); - EXPECT_EQ(ret, 0); + AppSpawnClientHandle clientHandle = CreateClient(APPSPAWN_SERVER_NAME); + ASSERT_EQ(clientHandle != NULL, 1); + AppSpawnReqMsgHandle reqHandle = CreateMsg(clientHandle, "ohos.samples.clock"); + ASSERT_EQ(reqHandle != INVALID_REQ_HANDLE, 1); - 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.extraInfo.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); + AppSpawnResult result = {}; + int ret = AppSpawnClientSendMsg(clientHandle, reqHandle, &result); + if (ret == 0 && result.pid > 0) { + kill(result.pid, SIGKILL); } - // close client - ClientClose(); -} - -// has env data,read json from etc -static const std::string g_envJsonStr = "|AppEnv|{" - "\"test.name1\": \"test.value1\"," - "\"test.name2\": \"test.value2\"" -"}|AppEnv|"; - -HWTEST_F(AppSpawnClientTest, AppSpawn_Client_AppSpawn_3_1, TestSize.Level0) -{ - APPSPAWN_LOGI("AppSpawn_Client_AppSpawn_3_1 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"); - - printf("AppSpawn_Client_AppSpawn_3_1 env %zu %s \n", g_envJsonStr.size(), g_envJsonStr.c_str()); - request.extraInfo.totalLength = g_envJsonStr.size(); - std::vector data(sizeof(request) + g_envJsonStr.size()); - memcpy_s(data.data(), sizeof(request), &request, sizeof(request)); - memcpy_s(data.data() + sizeof(request), g_envJsonStr.size(), g_envJsonStr.data(), g_envJsonStr.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_3_1 end"); -} - -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.extraInfo.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.extraInfo.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_LT(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_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(); + AppSpawnClientDestroy(clientHandle); } } // namespace AppSpawn -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/test/moduletest/appspawn_module_test.cpp b/test/moduletest/appspawn_module_test.cpp old mode 100644 new mode 100755 index 3f60946e..bd2295e0 --- a/test/moduletest/appspawn_module_test.cpp +++ b/test/moduletest/appspawn_module_test.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Copyright (c) 2024 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 @@ -13,20 +13,22 @@ * limitations under the License. */ +#include #include #include -#include +#include "appspawn.h" +#include "appspawn_msg.h" -#include "gtest/gtest.h" -#include "app_spawn_client.h" +#include "appspawn_utils.h" #include "hilog/log.h" #include "securec.h" +#include "appspawn_test_cmder.h" +#include + +using namespace testing; using namespace testing::ext; -using namespace OHOS; -using namespace OHOS::AppExecFwk; -using namespace OHOS::HiviewDFX; namespace OHOS { namespace AppSpawn { @@ -36,27 +38,26 @@ namespace AppSpawn { #define LOG_TAG "AppSpawnMST" namespace { -const bool CHECK_OK = true; -const bool CHECK_ERROR = false; -const int32_t DEFAULT_PID = 0; -const int32_t FILE_PATH_SIZE = 50; -const int32_t CMD_SIZE = 50; -const int32_t BUFFER_SIZE = 512; -const int32_t BASE_TYPE = 10; -const int32_t CONNECT_RETRY_DELAY = 50 * 1000; -const int32_t CONNECT_RETRY_MAX_TIMES = 5; -const int32_t UID_POSITION_MOVE = 5; -const int32_t GID_POSITION_MOVE = 5; -const int32_t GROUPS_POSITION_MOVE = 8; -const char *DELIMITER_SPACE = " "; -const char *DELIMITER_NEWLINE = "\n"; + const bool CHECK_OK = true; + const bool CHECK_ERROR = false; + const int32_t DEFAULT_PID = 0; + const int32_t FILE_PATH_SIZE = 50; + const int32_t CMD_SIZE = 50; + const int32_t BUFFER_SIZE = 512; + const int32_t BASE_TYPE = 10; + const int32_t CONNECT_RETRY_DELAY = 50 * 1000; + const int32_t CONNECT_RETRY_MAX_TIMES = 5; + const int32_t UID_POSITION_MOVE = 5; + const int32_t GID_POSITION_MOVE = 5; + const int32_t GROUPS_POSITION_MOVE = 8; + const char *DELIMITER_SPACE = " "; + const char *DELIMITER_NEWLINE = "\n"; -char buffer[BUFFER_SIZE] = {"\0"}; -int32_t newPid = 0; -int32_t retryCount = 0; + char buffer[BUFFER_SIZE] = {"\0"}; + int32_t retryCount = 0; } // namespace -bool checkFileIsExists(const char *filepath) +bool CheckFileIsExists(const char *filepath) { retryCount = 0; while ((access(filepath, F_OK) != 0) && (retryCount < CONNECT_RETRY_MAX_TIMES)) { @@ -70,7 +71,7 @@ bool checkFileIsExists(const char *filepath) return CHECK_ERROR; } -bool readFileInfo(char *buffer, const int32_t &pid, const char *fileName) +bool ReadFileInfo(char *buffer, const int32_t &pid, const char *fileName) { // Set file path char filePath[FILE_PATH_SIZE]; @@ -78,7 +79,7 @@ bool readFileInfo(char *buffer, const int32_t &pid, const char *fileName) HILOG_ERROR(LOG_CORE, "filePath sprintf_s fail ."); return CHECK_ERROR; } - if (!checkFileIsExists(filePath)) { + if (!CheckFileIsExists(filePath)) { HILOG_ERROR(LOG_CORE, "file %{public}s is not exists .", fileName); return CHECK_ERROR; } @@ -101,9 +102,9 @@ bool readFileInfo(char *buffer, const int32_t &pid, const char *fileName) return CHECK_OK; } -bool checkUid(const int32_t &pid, const AppSpawnStartMsg ¶ms) +bool CheckUid(const int32_t &pid, const int newUid) { - if (readFileInfo(buffer, pid, "status")) { + if (ReadFileInfo(buffer, pid, "status")) { // Move to Uid position char *uidPtr = strstr(buffer, "Uid:"); if (uidPtr == nullptr) { @@ -113,18 +114,18 @@ bool checkUid(const int32_t &pid, const AppSpawnStartMsg ¶ms) if (strlen(uidPtr) > UID_POSITION_MOVE) { uidPtr = uidPtr + UID_POSITION_MOVE; } - int32_t uid = (int32_t)strtol(uidPtr, NULL, BASE_TYPE); - HILOG_INFO(LOG_CORE, "new proc(%{public}d) uid = %{public}d, setUid=%{public}d.", pid, uid, params.uid); - if (uid == params.uid) { + int32_t uid = static_cast(strtol(uidPtr, NULL, BASE_TYPE)); + HILOG_INFO(LOG_CORE, "new proc(%{public}d) uid = %{public}d, setUid=%{public}d.", pid, uid, newUid); + if (uid == newUid) { return CHECK_OK; } } return CHECK_ERROR; } -bool checkGid(const int32_t &pid, const AppSpawnStartMsg ¶ms) +bool CheckGid(const int32_t &pid, const int newGid) { - if (readFileInfo(buffer, pid, "status")) { + if (ReadFileInfo(buffer, pid, "status")) { // Move to Gid position char *gidPtr = strstr(buffer, "Gid:"); if (gidPtr == nullptr) { @@ -138,17 +139,18 @@ bool checkGid(const int32_t &pid, const AppSpawnStartMsg ¶ms) HILOG_ERROR(LOG_CORE, "get Gid info failed."); return CHECK_ERROR; } - int32_t gid = (int32_t)strtol(gidPtr, NULL, BASE_TYPE); - HILOG_INFO(LOG_CORE, "new proc(%{public}d) gid = %{public}d, setGid=%{public}d.", pid, gid, params.gid); - if (gid == params.gid) { + int32_t gid = static_cast(strtol(gidPtr, NULL, BASE_TYPE)); + HILOG_INFO(LOG_CORE, "new proc(%{public}d) gid = %{public}d, setGid=%{public}d.", pid, gid, newGid); + if (gid == newGid) { return CHECK_OK; } } return CHECK_ERROR; } -std::size_t getGids(const int32_t &pid, std::vector &gids) + +std::size_t GetGids(const int32_t &pid, std::vector &gids) { - if (readFileInfo(buffer, pid, "status")) { + if (ReadFileInfo(buffer, pid, "status")) { // Move to Groups position char *groupsPtr = strstr(buffer, "Groups"); if (groupsPtr == nullptr || strlen(groupsPtr) > BUFFER_SIZE) { @@ -180,31 +182,31 @@ std::size_t getGids(const int32_t &pid, std::vector &gids) return gids.size(); } -bool checkGids(const int32_t &pid, const AppSpawnStartMsg ¶ms) +bool CheckGids(const int32_t &pid, const std::vector newGids) { // Get Gids std::vector gids; - std::size_t gCount = getGids(pid, gids); - if ((gCount == params.gids.size()) && (gids == params.gids)) { + std::size_t gCount = GetGids(pid, gids); + if ((gCount == newGids.size()) && (gids == newGids)) { return CHECK_OK; } return CHECK_ERROR; } -bool checkGidsCount(const int32_t &pid, const AppSpawnStartMsg ¶ms) +bool CheckGidsCount(const int32_t &pid, const std::vector newGids) { // Get GidsCount std::vector gids; - std::size_t gCount = getGids(pid, gids); - if (gCount == params.gids.size()) { + std::size_t gCount = GetGids(pid, gids); + if (gCount == newGids.size()) { return CHECK_OK; } return CHECK_ERROR; } -bool checkProcName(const int32_t &pid, const AppSpawnStartMsg ¶ms) +bool CheckProcName(const int32_t &pid, const std::string &newProcessName) { FILE *fp = nullptr; char cmd[CMD_SIZE]; @@ -212,7 +214,7 @@ bool checkProcName(const int32_t &pid, const AppSpawnStartMsg ¶ms) HILOG_ERROR(LOG_CORE, "cmd sprintf_s fail ."); return CHECK_ERROR; } - if(strlen(cmd) > CMD_SIZE) { + if (strlen(cmd) > CMD_SIZE) { HILOG_ERROR(LOG_CORE, " cmd length is too long ."); return CHECK_ERROR; } @@ -229,14 +231,13 @@ bool checkProcName(const int32_t &pid, const AppSpawnStartMsg ¶ms) break; } } - GTEST_LOG_(INFO) << "strcmp" - << " :" << strcmp(params.procName.c_str(), procName) << "."; + GTEST_LOG_(INFO) << "strcmp" << " :" << strcmp(newProcessName.c_str(), procName) << "."; - if (params.procName.compare(0, params.procName.size(), procName, params.procName.size()) == 0) { + if (newProcessName.compare(0, newProcessName.size(), procName, newProcessName.size()) == 0) { pclose(fp); return CHECK_OK; } - HILOG_ERROR(LOG_CORE, " procName=%{public}s, params.procName=%{public}s.", procName, params.procName.c_str()); + HILOG_ERROR(LOG_CORE, " procName=%{public}s, newProcessName=%{public}s.", procName, newProcessName.c_str()); } else { HILOG_ERROR(LOG_CORE, "Getting procName failed."); } @@ -244,7 +245,8 @@ bool checkProcName(const int32_t &pid, const AppSpawnStartMsg ¶ms) return CHECK_ERROR; } -bool checkProcessIsDestroyed(const int32_t &pid) + +bool CheckProcessIsDestroyed(const int32_t &pid) { char filePath[FILE_PATH_SIZE]; if (sprintf_s(filePath, sizeof(filePath), "/proc/%d", pid) <= 0) { @@ -252,7 +254,7 @@ bool checkProcessIsDestroyed(const int32_t &pid) return CHECK_ERROR; } - if (checkFileIsExists(filePath)) { + if (CheckFileIsExists(filePath)) { HILOG_ERROR(LOG_CORE, "File %{public}d is not exists .", pid); return CHECK_ERROR; } @@ -260,7 +262,7 @@ bool checkProcessIsDestroyed(const int32_t &pid) return CHECK_OK; } -bool checkAppspawnPID() +bool CheckAppspawnPID() { FILE *fp = nullptr; fp = popen("pidof appspawn", "r"); @@ -315,48 +317,231 @@ public: static void TearDownTestCase(); void SetUp(); void TearDown(); + + const std::string defaultAppInfo1 = "{ \ + \"msg-type\": 0, \ + \"msg-flags\": [ 3 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ + }"; + + const std::string defaultAppInfo2 = "{ \ + \"msg-type\": 0, \ + \"msg-flags\": [ 3 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [ 20010043 ],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ + }"; + + const std::string defaultAppInfo3 = "{ \ + \"msg-type\": 1, \ + \"msg-flags\": [ 3 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ + }"; + + const std::string defaultAppInfo4 = "{ \ + \"msg-type\": 1, \ + \"msg-flags\": [ 3 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [ 20010043, 20010044 ],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ + }"; + + const std::string defaultAppInfo5 = "{ \ + \"msg-type\": 1, \ + \"msg-flags\": [ 3 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [ 20010043 ],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ + }"; }; void AppSpawnModuleTest::SetUpTestCase() { - if (!checkAppspawnPID()) { + if (!CheckAppspawnPID()) { EXPECT_EQ(startAppspawn(), CHECK_OK); } } void AppSpawnModuleTest::TearDownTestCase() { - if (checkAppspawnPID()) { + if (CheckAppspawnPID()) { EXPECT_EQ(stopAppspawn(), CHECK_OK); } } void AppSpawnModuleTest::SetUp() { - newPid = 0; auto ret = memset_s(buffer, sizeof(buffer), 0x00, BUFFER_SIZE); if (ret != EOK) { HILOG_ERROR(LOG_CORE, "memset_s is failed."); } } -void AppSpawnModuleTest::TearDown() -{} +void AppSpawnModuleTest::TearDown() {} /* - * Feature: AppSpawn - * Function: Listen - * SubFunction: Message listener - * FunctionPoints: Process start message monitoring - * EnvConditions: AppSpawn main process has started. - * The socket server has been established. - * CaseDescription: 1. Query the process of appspawn through the ps command - */ +* Feature: AppSpawn +* Function: Listen +* SubFunction: Message listener +* FunctionPoints: Process start message monitoring +* EnvConditions: AppSpawn main process has started. +* The socket server has been established. +* CaseDescription: 1. Query the process of appspawn through the ps command +*/ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_001, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_listen_001 start"); - EXPECT_EQ(CHECK_OK, checkAppspawnPID()); + EXPECT_EQ(CHECK_OK, CheckAppspawnPID()); HILOG_INFO(LOG_CORE, "AppSpawn_HF_listen_001 end"); } @@ -373,15 +558,19 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_001, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_002, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_listen_002 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo1.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_listen_002 end"); } @@ -398,21 +587,18 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_002, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_fork_001, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_fork_001 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-fork_001", "soPath", 0, "system_core", "moduleTestProcessName-fork_001"}; - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo1.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_fork_001 end"); } @@ -429,22 +615,20 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_fork_001, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_fork_002, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_fork_002 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-fork_002", "soPath", 0, "system_core", "moduleTestProcessName-fork_002"}; - GTEST_LOG_(INFO) << "AppSpawn_HF_fork_002 start " << params.procName.size(); - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo3.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_fork_002 end"); } @@ -461,23 +645,22 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_fork_002, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_001, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_001 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_001", "soPath", 0, "system_core", "moduleTestProcessName-setUid_001"}; - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - EXPECT_EQ(CHECK_OK, checkUid(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo1.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + EXPECT_EQ(CHECK_OK, CheckUid(result.pid, 20010043)); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_001 end"); } @@ -489,34 +672,33 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_001, TestSize.Level0) * EnvConditions: AppSpawn main process has started. * The socket server has been established. * CaseDescription: 1. Establish a socket client and connect with the Appspawn server - * 2. Send the message and the message format is correct, the message type is APP_TYPE_DEFAULT + * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE */ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_002, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_002 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_002", "soPath", 0, "system_core", "moduleTestProcessName-setUid_002"}; - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo3.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + EXPECT_EQ(CHECK_OK, CheckGid(result.pid, 20010043)); - EXPECT_EQ(CHECK_OK, checkGid(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_002 end"); } /* * Feature: AppSpawn - * Function: SetUid + * Function: CheckGid * SubFunction: Set child process permissions * FunctionPoints: Set the permissions of the child process to increase the priority of the new process * EnvConditions: AppSpawn main process has started. @@ -524,32 +706,64 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_002, TestSize.Level0) * CaseDescription: 1. Establish a socket client and connect with the Appspawn server * 2. Send the message and the message format is correct, the message type is APP_TYPE_DEFAULT */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_003, TestSize.Level0) +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGid_001, TestSize.Level0) { - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_003 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_003", "soPath", 0, "system_core", "moduleTestProcessName-setUid_003"}; + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGid_001 start"); - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo4.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + EXPECT_EQ(CHECK_OK, CheckGid(result.pid, 20010043)); - EXPECT_EQ(CHECK_OK, checkGids(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_003 end"); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGid_001 end"); } /* * Feature: AppSpawn - * Function: SetUid + * Function: CheckGid + * SubFunction: Set child process permissions + * FunctionPoints: Set the permissions of the child process to increase the priority of the new process + * EnvConditions: AppSpawn main process has started. + * The socket server has been established. + * CaseDescription: 1. Establish a socket client and connect with the Appspawn server + * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE + */ +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGid_002, TestSize.Level0) +{ + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGid_002 start"); + + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo2.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + EXPECT_EQ(CHECK_OK, CheckGid(result.pid, 20010043)); + + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGid_002 end"); +} + +/* + * Feature: AppSpawn + * Function: CheckGids * SubFunction: Set child process permissions * FunctionPoints: Set the permissions of the child process to increase the priority of the new process * EnvConditions: AppSpawn main process has started. @@ -557,32 +771,33 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_003, TestSize.Level0) * CaseDescription: 1. Establish a socket client and connect with the Appspawn server * 2. Send the message and the message format is correct, the message type is APP_TYPE_DEFAULT */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_004, TestSize.Level0) +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGids_001, TestSize.Level0) { - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_004 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_004", "soPath", 0, "system_core", "moduleTestProcessName-setUid_004"}; + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGids_001 start"); - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo2.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; - EXPECT_EQ(CHECK_OK, checkGidsCount(newPid, params)); + std::vector gids = {20010043}; + EXPECT_EQ(CHECK_OK, CheckGids(result.pid, gids)); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_004 end"); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_001 end"); } /* * Feature: AppSpawn - * Function: SetUid + * Function: CheckGids * SubFunction: Set child process permissions * FunctionPoints: Set the permissions of the child process to increase the priority of the new process * EnvConditions: AppSpawn main process has started. @@ -590,32 +805,67 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_004, TestSize.Level0) * CaseDescription: 1. Establish a socket client and connect with the Appspawn server * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_005, TestSize.Level0) +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGids_002, TestSize.Level0) { - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_005 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_005", "soPath", 0, "system_core", "moduleTestProcessName-setUid_005"}; + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGids_002 start"); - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo5.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; - EXPECT_EQ(CHECK_OK, checkUid(newPid, params)); + std::vector gids = { 20010043 }; + EXPECT_EQ(CHECK_OK, CheckGids(result.pid, gids)); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_005 end"); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGids_002 end"); } /* * Feature: AppSpawn - * Function: SetUid + * Function: CheckGidsCount + * SubFunction: Set child process permissions + * FunctionPoints: Set the permissions of the child process to increase the priority of the new process + * EnvConditions: AppSpawn main process has started. + * The socket server has been established. + * CaseDescription: 1. Establish a socket client and connect with the Appspawn server + * 2. Send the message and the message format is correct, the message type is APP_TYPE_DEFAULT + */ +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGidsCount_001, TestSize.Level0) +{ + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGidsCount_001 start"); + + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo2.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + + std::vector gids = {20010043 }; + EXPECT_EQ(CHECK_OK, CheckGidsCount(result.pid, gids)); + + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGidsCount_001 end"); +} + +/* + * Feature: AppSpawn + * Function: CheckGidsCount * SubFunction: Set child process permissions * FunctionPoints: Set the permissions of the child process to increase the priority of the new process * EnvConditions: AppSpawn main process has started. @@ -623,93 +873,27 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_005, TestSize.Level0) * CaseDescription: 1. Establish a socket client and connect with the Appspawn server * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_006, TestSize.Level0) +HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_checkGidsCount_002, TestSize.Level0) { - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_006 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_006", "soPath", 0, "system_core", "moduleTestProcessName-setUid_006"}; + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGidsCount_002 start"); - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo5.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + std::vector gids = {20010043}; + EXPECT_EQ(CHECK_OK, CheckGidsCount(result.pid, gids)); - EXPECT_EQ(CHECK_OK, checkGid(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_006 end"); -} - -/* - * Feature: AppSpawn - * Function: SetUid - * SubFunction: Set child process permissions - * FunctionPoints: Set the permissions of the child process to increase the priority of the new process - * EnvConditions: AppSpawn main process has started. - * The socket server has been established. - * CaseDescription: 1. Establish a socket client and connect with the Appspawn server - * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE - */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_007, TestSize.Level0) -{ - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_007 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_007", "soPath", 0, "system_core", "moduleTestProcessName-setUid_007"}; - - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - - EXPECT_EQ(CHECK_OK, checkGids(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_007 end"); -} - -/* - * Feature: AppSpawn - * Function: SetUid - * SubFunction: Set child process permissions - * FunctionPoints: Set the permissions of the child process to increase the priority of the new process - * EnvConditions: AppSpawn main process has started. - * The socket server has been established. - * CaseDescription: 1. Establish a socket client and connect with the Appspawn server - * 2. Send the message and the message format is correct, the message type is APP_TYPE_NATIVE - */ -HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_008, TestSize.Level0) -{ - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_008 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setUid_008", "soPath", 0, "system_core", "moduleTestProcessName-setUid_008"}; - - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - - EXPECT_EQ(CHECK_OK, checkGidsCount(newPid, params)); - - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); - HILOG_INFO(LOG_CORE, "AppSpawn_HF_setUid_008 end"); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } + HILOG_INFO(LOG_CORE, "AppSpawn_HF_checkGidsCount_002 end"); } /* @@ -725,24 +909,23 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setUid_008, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setProcName_001, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_setProcName_001 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setProcName_001", "soPath", 0, "system_core", "moduleTestProcessName-setProcName_001"}; - - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo1.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; // Check new app proc name - EXPECT_EQ(CHECK_OK, checkProcName(newPid, params)); + EXPECT_EQ(CHECK_OK, CheckProcName(result.pid, "com.example.myapplication")); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_setProcName_001 end"); } @@ -759,24 +942,22 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setProcName_001, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setProcName_002, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_setProcName_002 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-setProcName_002", "soPath", 0, "system_core", "moduleTestProcessName-setProcName_002"}; - - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo4.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; // Check new app proc name - EXPECT_EQ(CHECK_OK, checkProcName(newPid, params)); + EXPECT_EQ(CHECK_OK, CheckProcName(result.pid, "com.example.myapplication")); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_setProcName_002 end"); } @@ -791,27 +972,26 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_setProcName_002, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_recycleProc_001, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_recycleProc_001 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-recycleProc_001", "soPath", 0, "system_core", "moduleTestProcessName-recycleProc_001"}; + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo4.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - - EXPECT_EQ(ERR_OK, kill(newPid, SIGKILL)); - newPid = DEFAULT_PID; + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; // Check Process Is Destroyed - EXPECT_EQ(CHECK_OK, checkProcessIsDestroyed(newPid)); + EXPECT_EQ(CHECK_OK, CheckProcessIsDestroyed(result.pid)); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_recycleProc_001 end"); } @@ -826,27 +1006,25 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_recycleProc_001, TestSize.Level0) HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_recycleProc_002, TestSize.Level0) { HILOG_INFO(LOG_CORE, "AppSpawn_HF_recycleProc_002 start"); - std::unique_ptr appSpawnClient = std::make_unique(); - std::shared_ptr appSpawnSocket = std::make_shared(); - appSpawnClient->SetSocket(appSpawnSocket); - EXPECT_EQ(ERR_OK, appSpawnClient->OpenConnection()); - AppSpawnStartMsg params = {10003, 10004, {10003, 10004}, - "processName-recycleProc_002", "soPath", 0, "system_core", "moduleTestProcessName-recycleProc_002"}; - - appSpawnClient->StartProcess(params, newPid); - // 0 < newPid, new process fork success - GTEST_LOG_(INFO) << "newPid :" << newPid << "."; - EXPECT_LT(DEFAULT_PID, newPid); - - EXPECT_EQ(ERR_OK, kill(newPid, SIGKILL)); - newPid = DEFAULT_PID; + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + AppSpawnReqMsgHandle reqHandle; + AppSpawnResult result; + commander.CreateMsg(reqHandle, defaultAppInfo1.c_str()); + int ret = AppSpawnClientSendMsg(commander.GetClientHandle(), reqHandle, &result); + EXPECT_EQ(0, ret); + EXPECT_EQ(0, result.result); + EXPECT_NE(0, result.pid); + GTEST_LOG_(INFO) << "newPid :" << result.pid << "."; + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; // Check Process Is Destroyed - EXPECT_EQ(CHECK_OK, checkProcessIsDestroyed(newPid)); + EXPECT_EQ(CHECK_OK, CheckProcessIsDestroyed(result.pid)); - EXPECT_EQ(ERR_OK, appSpawnSocket->OpenAppSpawnConnection()); - appSpawnClient->CloseConnection(); - EXPECT_EQ(SpawnConnectionState::STATE_NOT_CONNECT, appSpawnClient->QueryConnectionState()); + if (result.pid > 0) { + EXPECT_EQ(0, kill(result.pid, SIGKILL)); + result.pid = DEFAULT_PID; + } HILOG_INFO(LOG_CORE, "AppSpawn_HF_recycleProc_002 end"); } } // namespace AppSpawn diff --git a/test/moduletest/appspawn_test_client.h b/test/moduletest/appspawn_test_client.h deleted file mode 100644 index 9ed0c8a6..00000000 --- a/test/moduletest/appspawn_test_client.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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->extraInfo.totalLength = 0; - request->extraInfo.savedLength = 0; - request->extraInfo.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()); - ret += strcpy_s(request->ownerId, sizeof(request->ownerId), 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 deleted file mode 100644 index eeaadb11..00000000 --- a/test/moduletest/appspawn_test_cmd.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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/moduletest/appspawn_test_cmder.cpp b/test/moduletest/appspawn_test_cmder.cpp new file mode 100755 index 00000000..dbdf8122 --- /dev/null +++ b/test/moduletest/appspawn_test_cmder.cpp @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2024 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_cmder.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "appspawn.h" +#include "appspawn_msg.h" +#include "appspawn_utils.h" +#include "command_lexer.h" +#include "cJSON.h" +#include "securec.h" +#include "thread_manager.h" + +#define MAX_THREAD 10 +#define MAX_SEND 200 +#define PTY_PATH_SIZE 128 + +namespace OHOS { +namespace AppSpawnModuleTest { +static const std::string g_defaultAppInfo = "{ \ + \"msg-type\": 0, \ + \"msg-flags\": [1, 2 ], \ + \"process-name\" : \"com.example.myapplication\", \ + \"dac-info\" : { \ + \"uid\" : 20010043, \ + \"gid\" : 20010043,\ + \"gid-table\" : [],\ + \"user-name\" : \"\" \ + },\ + \"access-token\" : {\ + \"accessTokenIdEx\" : 537854093\ + },\ + \"permission\" : [\ + \"ohos.permission.READ_IMAGEVIDEO\",\ + \"ohos.permission.FILE_CROSS_APP\",\ + \"ohos.permission.ACTIVATE_THEME_PACKAGE\"\ + ],\ + \"internet-permission\" : {\ + \"set-allow-internet\" : 0,\ + \"allow-internet\" : 0\ + },\ + \"bundle-info\" : {\ + \"bundle-index\" : 0,\ + \"bundle-name\" : \"com.example.myapplication\" \ + },\ + \"owner-id\" : \"\",\ + \"render-cmd\" : \"1234567890\",\ + \"domain-info\" : {\ + \"hap-flags\" : 0,\ + \"apl\" : \"system_core\"\ + },\ + \"ext-info\" : [\ + {\ + \"name\" : \"test\",\ + \"value\" : \"4444444444444444444\" \ + } \ + ]\ +}"; + +static const char *APPSPAWN_TEST_USAGE = "usage: AppSpawnTest \n" + "options list:\n" + " --help list available commands\n" + " --file xx file path with app info\n" + " --thread xx use multi-thread to send message\n" + " --type xx send msg type \n" + " --pid xx render terminate pid\n" + " --mode nwebspawn send message to nwebspawn service\n"; + +int AppSpawnTestCommander::ProcessArgs(int argc, char *const argv[]) +{ + int sendMsg = 0; + msgType_ = MAX_TYPE_INVALID; + for (int32_t i = 0; i < argc; i++) { + if (argv[i] == nullptr) { + continue; + } + if (strcmp(argv[i], "--file") == 0 && ((i + 1) < argc)) { // test file + i++; + testFileName_ = argv[i]; + sendMsg = 1; + } else if (strcmp(argv[i], "--thread") == 0 && ((i + 1) < argc)) { // use thread + i++; + threadCount_ = atoi(argv[i]); + if (threadCount_ > MAX_THREAD) { + threadCount_ = MAX_THREAD; + } + sendMsg = 1; + } else if (strcmp(argv[i], "--mode") == 0 && ((i + 1) < argc)) { + i++; + appSpawn_ = strcmp(argv[i], "nwebspawn") == 0 ? 0 : 1; + sendMsg = 1; + } else if (strcmp(argv[i], "--type") == 0 && ((i + 1) < argc)) { + i++; + msgType_ = atoi(argv[i]); + sendMsg = 1; + } else if (strcmp(argv[i], "--pid") == 0 && ((i + 1) < argc)) { + i++; + msgType_ = MSG_GET_RENDER_TERMINATION_STATUS; + terminatePid_ = atoi(argv[i]); + sendMsg = 1; + } else if (strcmp(argv[i], "--help") == 0) { + printf("%s\n", APPSPAWN_TEST_USAGE); + return 1; + } else if (strcmp(argv[i], "--send") == 0 || strcmp(argv[i], "send") == 0) { + sendMsg = 1; + } + } + if (sendMsg == 0) { + printf("%s\n", APPSPAWN_TEST_USAGE); + return 1; + } + return 0; +} + +uint32_t AppSpawnTestCommander::GetUint32ArrayFromJson(const cJSON *json, + const char *name, uint32_t dataArray[], uint32_t maxCount) +{ + APPSPAWN_CHECK(json != NULL, return 0, "Invalid json"); + APPSPAWN_CHECK(name != NULL, return 0, "Invalid name"); + APPSPAWN_CHECK(dataArray != NULL, return 0, "Invalid dataArray"); + APPSPAWN_CHECK(cJSON_IsObject(json), return 0, "json is not object."); + cJSON *array = cJSON_GetObjectItemCaseSensitive(json, name); + APPSPAWN_CHECK_ONLY_EXPER(array != NULL, return 0); + APPSPAWN_CHECK(cJSON_IsArray(array), return 0, "json is not object."); + + uint32_t count = 0; + uint32_t arrayLen = cJSON_GetArraySize(array); + for (int i = 0; i < arrayLen; i++) { + cJSON *item = cJSON_GetArrayItem(array, i); + uint32_t value = (uint32_t)cJSON_GetNumberValue(item); + if (count < maxCount) { + dataArray[count++] = value; + } + } + return count; +} + +int AppSpawnTestCommander::AddBundleInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle) +{ + cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "bundle-info"); + APPSPAWN_CHECK_ONLY_EXPER(config, return 0); + + uint32_t bundleIndex = GetIntValueFromJsonObj(config, "bundle-index", 0); + char *bundleName = GetStringFromJsonObj(config, "bundle-name"); + int ret = AppSpawnReqMsgSetBundleInfo(reqHandle, bundleIndex, bundleName); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add bundle info req %{public}s", bundleName); + return 0; +} + +int AppSpawnTestCommander::GetDacInfoFromJson(const cJSON *appInfoConfig, AppDacInfo &info) +{ + cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "dac-info"); + APPSPAWN_CHECK_ONLY_EXPER(config, return 0); + + info.uid = GetIntValueFromJsonObj(config, "uid", 0); + info.gid = GetIntValueFromJsonObj(config, "gid", 0); + info.gidCount = GetUint32ArrayFromJson(config, "gid-table", info.gidTable, APP_MAX_GIDS); + char *userName = GetStringFromJsonObj(config, "user-name"); + if (userName != nullptr) { + return strcpy_s(info.userName, sizeof(info.userName), userName); + } + return 0; +} + +int AppSpawnTestCommander::GetInternetPermissionInfoFromJson( + const cJSON *appInfoConfig, AppSpawnMsgInternetInfo &info) +{ + cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "internet-permission"); + APPSPAWN_CHECK_ONLY_EXPER(config, return 0); + + info.setAllowInternet = GetIntValueFromJsonObj(config, "set-allow-internet", 0); + info.allowInternet = GetIntValueFromJsonObj(config, "allow-internet", 0); + return 0; +} + +int AppSpawnTestCommander::GetAccessTokenFromJson(const cJSON *appInfoConfig, AppSpawnMsgAccessToken &info) +{ + cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "access-token"); + APPSPAWN_CHECK_ONLY_EXPER(config, return 0); + + info.accessTokenIdEx = GetIntValueFromJsonObj(config, "accessTokenIdEx", 0); + return 0; +} + +int AppSpawnTestCommander::AddDomainInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle) +{ + cJSON *config = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "domain-info"); + APPSPAWN_CHECK_ONLY_EXPER(config, return 0); + + uint32_t hapFlags = GetIntValueFromJsonObj(config, "hap-flags", 0); + char *apl = GetStringFromJsonObj(config, "apl"); + int ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, hapFlags, apl); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to domain info"); + return 0; +} + +int AppSpawnTestCommander::AddExtTlv(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle) +{ + cJSON *configs = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "ext-info"); + APPSPAWN_CHECK_ONLY_EXPER(configs, return 0); + + int ret = 0; + uint32_t count = cJSON_GetArraySize(configs); + for (unsigned int j = 0; j < count; j++) { + cJSON *config = cJSON_GetArrayItem(configs, j); + + char *name = GetStringFromJsonObj(config, "name"); + char *value = GetStringFromJsonObj(config, "value"); + APPSPAWN_LOGV("ext-info %{public}s %{public}s", name, value); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, name, value); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add ext name %{public}s", name); + } + + // 添加一个二进制的扩展元素 + AppDacInfo dacInfo{}; + dacInfo.uid = 101; // 101 test data + dacInfo.gid = 101; // 101 test data + dacInfo.gidTable[0] = 101; // 101 test data + dacInfo.gidCount = 1; + (void)strcpy_s(dacInfo.userName, sizeof(dacInfo.userName), processName_.c_str()); + ret = AppSpawnReqMsgAddExtInfo(reqHandle, "app-dac-info", reinterpret_cast(&dacInfo), sizeof(dacInfo)); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add ext name app-info"); + return ret; +} + +int AppSpawnTestCommander::BuildMsgFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle) +{ + int ret = AddBundleInfoFromJson(appInfoConfig, reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str()); + + ret = AddDomainInfoFromJson(appInfoConfig, reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str()); + + AppDacInfo dacInfo = {}; + ret = GetDacInfoFromJson(appInfoConfig, dacInfo); + APPSPAWN_LOGE("*************, %d", dacInfo.gidCount); + APPSPAWN_LOGE("*************, %d", dacInfo.uid); + ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add dac %{public}s", processName_.c_str()); + + AppSpawnMsgAccessToken token = {}; + ret = GetAccessTokenFromJson(appInfoConfig, token); + ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, token.accessTokenIdEx); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to add access token %{public}s", processName_.c_str()); + + cJSON *obj = cJSON_GetObjectItemCaseSensitive(appInfoConfig, "permission"); + if (obj != nullptr && cJSON_IsArray(obj)) { + int count = cJSON_GetArraySize(obj); + for (int i = 0; i < count; i++) { + char *value = cJSON_GetStringValue(cJSON_GetArrayItem(obj, i)); + APPSPAWN_LOGV("permission %{public}s ", value); + ret = AppSpawnReqMsgAddPermission(reqHandle, value); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to permission %{public}s", value); + } + } + + AppSpawnMsgInternetInfo internetInfo = {}; + ret = GetInternetPermissionInfoFromJson(appInfoConfig, internetInfo); + ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle, + internetInfo.allowInternet, internetInfo.setAllowInternet); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to internet info %{public}s", processName_.c_str()); + + std::string ownerId = GetStringFromJsonObj(appInfoConfig, "owner-id"); + if (!ownerId.empty()) { + ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, ownerId.c_str()); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to ownerid %{public}s", processName_.c_str()); + } + + std::string renderCmd = GetStringFromJsonObj(appInfoConfig, "render-cmd"); + if (!renderCmd.empty()) { + ret = AppSpawnReqMsgAddStringInfo(reqHandle, MSG_EXT_NAME_RENDER_CMD, renderCmd.c_str()); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to add renderCmd %{public}s", renderCmd.c_str()); + } + return AddExtTlv(appInfoConfig, reqHandle); +} + +int AppSpawnTestCommander::CreateOtherMsg(AppSpawnReqMsgHandle &reqHandle, pid_t pid) +{ + if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) { + int ret = AppSpawnTerminateMsgCreate(pid, &reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to termination message req %{public}s", processName_.c_str()); + } + if (msgType_ == MSG_DUMP) { + int ret = AppSpawnReqMsgCreate(static_cast(msgType_), processName_.c_str(), &reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to dump req %{public}s", processName_.c_str()); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, "pty-name", ptyName_.c_str()); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to add ptyName_ %{public}s", ptyName_.c_str()); + } + return 0; +} + +int AppSpawnTestCommander::CreateMsg(AppSpawnReqMsgHandle &reqHandle, const char *defaultConfig) +{ + int ret = APPSPAWN_SYSTEM_ERROR; + if (clientHandle_ == NULL) { + const char *name = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME; + ret = AppSpawnClientInit(name, &clientHandle_); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to create client %{public}s", name); + } + reqHandle = INVALID_REQ_HANDLE; + if (appInfoConfig_) { + cJSON_Delete(appInfoConfig_); + appInfoConfig_ = nullptr; + } + if (!testFileName_.empty()) { + appInfoConfig_ = GetJsonObjFromFile(testFileName_.c_str()); + if (appInfoConfig_ == nullptr) { + printf("Failed to load file %s, so use default info \n", testFileName_.c_str()); + } + } + if (appInfoConfig_ == nullptr) { + appInfoConfig_ = cJSON_Parse(defaultConfig); + } + if (appInfoConfig_ == nullptr) { + printf("Invalid app info \n"); + return APPSPAWN_SYSTEM_ERROR; + } + processName_ = GetStringFromJsonObj(appInfoConfig_, "process-name"); + if (processName_.empty()) { + processName_ = "com.example.myapplication"; + } + if (msgType_ == MAX_TYPE_INVALID) { + msgType_ = GetIntValueFromJsonObj(appInfoConfig_, "msg-type", MSG_APP_SPAWN); + } + if (msgType_ == MSG_DUMP) { + return CreateOtherMsg(reqHandle, 0); + } else if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) { + pid_t pid = GetIntValueFromJsonObj(appInfoConfig_, "pid", 0); + return CreateOtherMsg(reqHandle, pid); + } + ret = AppSpawnReqMsgCreate(static_cast(msgType_), processName_.c_str(), &reqHandle); + APPSPAWN_CHECK(ret == 0, return ret, "Failed to create req %{public}s", processName_.c_str()); + + uint32_t msgFlags[64] = {}; + uint32_t count = GetUint32ArrayFromJson(appInfoConfig_, "msg-flags", msgFlags, ARRAY_LENGTH(msgFlags)); + for (uint32_t j = 0; j < count; j++) { + (void)AppSpawnReqMsgSetAppFlag(reqHandle, static_cast(msgFlags[j])); + } + ret = BuildMsgFromJson(appInfoConfig_, reqHandle); + APPSPAWN_CHECK(ret == 0, AppSpawnReqMsgFree(reqHandle); + return ret, "Failed to build req %{public}s", processName_.c_str()); + return ret; +} + +int AppSpawnTestCommander::SendMsg() +{ + const char *server = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME; + printf("Send msg to server '%s' \n", server); + AppSpawnReqMsgHandle reqHandle = INVALID_REQ_HANDLE; + int ret = 0; + if (msgType_ == MSG_DUMP) { + while (!dumpFlags) { + usleep(20000); // 20000 + } + ret = CreateOtherMsg(reqHandle, 0); + } else if (msgType_ == MSG_GET_RENDER_TERMINATION_STATUS) { + ret = CreateOtherMsg(reqHandle, terminatePid_); + } else { + ret = CreateMsg(reqHandle, g_defaultAppInfo.c_str()); + } + AppSpawnResult result = {ret, 0}; + if (ret == 0) { + ret = AppSpawnClientSendMsg(clientHandle_, reqHandle, &result); + } + switch (msgType_) { + case MSG_APP_SPAWN: + if (result.result == 0) { + printf("Spawn app %s success, pid %d \n", processName_.c_str(), result.pid); + } else { + printf("Spawn app %s fail, result 0x%x \n", processName_.c_str(), result.result); + } + break; + case MSG_SPAWN_NATIVE_PROCESS: + if (result.result == 0) { + printf("Spawn native app %s success, pid %d \n", processName_.c_str(), result.pid); + } else { + printf("Spawn native app %s fail, result 0x%x \n", processName_.c_str(), result.result); + } + break; + case MSG_GET_RENDER_TERMINATION_STATUS: + printf("Terminate app %s success, pid %d status 0x%x \n", processName_.c_str(), result.pid, result.result); + break; + default: + printf("Dump server %s result %d \n", server, ret); + break; + } + msgType_ = MAX_TYPE_INVALID; + terminatePid_ = 0; + printf("Please input cmd: \n"); + return 0; +} + +int AppSpawnTestCommander::StartSendMsg() +{ + int ret = 0; + printf("Start send msg thread count %d file name %s \n", threadCount_, testFileName_.c_str()); + if (threadCount_ == 1) { + SendMsg(); + } else { + ThreadTaskHandle taskHandle = 0; + ret = ThreadMgrAddTask(threadMgr_, &taskHandle); + APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task "); + for (uint32_t index = 0; index < threadCount_; index++) { + ThreadMgrAddExecutor(threadMgr_, taskHandle, TaskExecutorProc, reinterpret_cast(this)); + } + TaskSyncExecute(threadMgr_, taskHandle); + } + return 0; +} + +void AppSpawnTestCommander::TaskExecutorProc(ThreadTaskHandle handle, const ThreadContext *context) +{ + AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context); + testCmder->SendMsg(); +} + +void AppSpawnTestCommander::SendTaskFinish(ThreadTaskHandle handle, const ThreadContext *context) +{ + APPSPAWN_LOGV("SendTaskFinish %{public}u \n", handle); +} + +static std::vector g_args; +static int HandleSplitString(const char *str, void *context) +{ + APPSPAWN_LOGV("HandleSplitString %{public}s ", str); + std::string value = str; + g_args.push_back(value); + return 0; +} + +int AppSpawnTestCommander::ProcessInputCmd(std::string &cmd) +{ + g_args.clear(); + int ret = StringSplit(cmd.c_str(), " ", nullptr, HandleSplitString); + std::vector options; + for (const auto &arg : g_args) { + if (!arg.empty()) { + options.push_back(const_cast(arg.c_str())); + } + } + (void)ProcessArgs(options.size(), options.data()); + StartSendMsg(); + return ret; +} + +void AppSpawnTestCommander::InputThread(ThreadTaskHandle handle, const ThreadContext *context) +{ + AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context); + char buffer[1024] = {0}; // 1024 test buffer max len + fd_set fds; + printf("Please input cmd: \n"); + while (1) { + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + int ret = select(STDIN_FILENO + 1, &fds, nullptr, nullptr, nullptr); + if (ret <= 0) { + if (testCmder->exit_) { + break; + } + continue; + } + ssize_t rlen = read(STDIN_FILENO, buffer, sizeof(buffer) - 1); + if (rlen <= 1) { + continue; + } + buffer[rlen - 1] = 0; + printf("Recv command: '%s' \n", buffer); + if (strncmp("quit", buffer, strlen("quit")) == 0) { + testCmder->exit_ = 1; + break; + } + if (strncmp("send", buffer, 4) == 0) { // 4 strlen("send") + std::string cmd(buffer); + testCmder->ProcessInputCmd(cmd); + printf("Please input cmd: \n"); + } + } +} + +void AppSpawnTestCommander::DumpThread(ThreadTaskHandle handle, const ThreadContext *context) +{ + AppSpawnTestCommander *testCmder = AppSpawnTestCommander::ConvertTo(context); + printf("Start dump thread \n"); + char buffer[10240] = {0}; // 1024 test buffer max len + fd_set fds; + while (1) { + testCmder->dumpFlags = 1; + FD_ZERO(&fds); + FD_SET(testCmder->ptyFd_, &fds); + int ret = select(testCmder->ptyFd_ + 1, &fds, nullptr, nullptr, nullptr); + if (ret <= 0) { + if (testCmder->exit_) { + break; + } + continue; + } + if (!FD_ISSET(testCmder->ptyFd_, &fds)) { + continue; + } + ssize_t rlen = read(testCmder->ptyFd_, buffer, sizeof(buffer) - 1); + while (rlen > 0) { + buffer[rlen] = '\0'; + printf("%s", buffer); + fflush(stdout); + rlen = read(testCmder->ptyFd_, buffer, sizeof(buffer) - 1); + } + } +} + +int AppSpawnTestCommander::Run() +{ + int ret = 0; + const char *name = appSpawn_ ? APPSPAWN_SERVER_NAME : NWEBSPAWN_SERVER_NAME; + if (clientHandle_ == NULL) { + ret = AppSpawnClientInit(name, &clientHandle_); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to create client %{public}s", name); + } + + InitPtyInterface(); + + ret = CreateThreadMgr(5, &threadMgr_); // 5 max thread + APPSPAWN_CHECK(ret == 0, return -1, "Failed to create thread manager"); + + ret = ThreadMgrAddTask(threadMgr_, &inputHandle_); + APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task for thread "); + ThreadMgrAddExecutor(threadMgr_, inputHandle_, InputThread, this); + TaskExecute(threadMgr_, inputHandle_, SendTaskFinish, this); + + ret = ThreadMgrAddTask(threadMgr_, &dumpHandle_); + APPSPAWN_CHECK(ret == 0, return 0, "Failed to add task for thread "); + ThreadMgrAddExecutor(threadMgr_, dumpHandle_, DumpThread, this); + TaskExecute(threadMgr_, dumpHandle_, SendTaskFinish, this); + + StartSendMsg(); + + APPSPAWN_LOGV("Finish send msg \n"); + while (!exit_) { + usleep(200000); // 200000 200ms + } + ThreadMgrCancelTask(threadMgr_, inputHandle_); + ThreadMgrCancelTask(threadMgr_, dumpHandle_); + DestroyThreadMgr(threadMgr_); + threadMgr_ = nullptr; + inputHandle_ = 0; + dumpHandle_ = 0; + AppSpawnClientDestroy(clientHandle_); + clientHandle_ = nullptr; + return 0; +} + +int AppSpawnTestCommander::InitPtyInterface() +{ + // open master pty and get slave pty + int pfd = open("/dev/ptmx", O_RDWR | O_CLOEXEC | O_NOCTTY | O_NONBLOCK); + APPSPAWN_CHECK(pfd >= 0, return -1, "Failed open pty err=%d", errno); + APPSPAWN_CHECK(grantpt(pfd) >= 0, close(pfd); return -1, "Failed to call grantpt"); + APPSPAWN_CHECK(unlockpt(pfd) >= 0, close(pfd); return -1, "Failed to call unlockpt"); + char ptsbuffer[PTY_PATH_SIZE] = {0}; + int ret = ptsname_r(pfd, ptsbuffer, sizeof(ptsbuffer)); + APPSPAWN_CHECK(ret >= 0, close(pfd); + return -1, "Failed to get pts name err=%d", errno); + APPSPAWN_LOGI("ptsbuffer is %s", ptsbuffer); + APPSPAWN_CHECK(chmod(ptsbuffer, S_IRWXU | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) == 0, close(pfd); + return -1, "Failed to chmod %s, err=%d", ptsbuffer, errno); + ptyFd_ = pfd; + ptyName_ = std::string(ptsbuffer); + return 0; +} +} // namespace AppSpawnModuleTest +} // namespace OHOS diff --git a/test/moduletest/appspawn_test_cmder.h b/test/moduletest/appspawn_test_cmder.h new file mode 100755 index 00000000..5b2a31a4 --- /dev/null +++ b/test/moduletest/appspawn_test_cmder.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2024 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_TEST_CMD_H +#define APPSPAWN_TEST_CMD_H + +#include +#include +#include +#include +#include + +#include "appspawn.h" +#include "appspawn_msg.h" +#include "appspawn_utils.h" +#include "cJSON.h" +#include "securec.h" +#include "thread_manager.h" + +typedef struct TagThreadContext { +} ThreadContext; + +__attribute__((always_inline)) inline char *GetStringFromJsonObj(const cJSON *json, const char *key) +{ + APPSPAWN_CHECK_ONLY_EXPER(key != NULL && json != NULL, NULL); + APPSPAWN_CHECK(cJSON_IsObject(json), return NULL, "json is not object %{public}s %s", key, cJSON_Print(json)); + cJSON *obj = cJSON_GetObjectItemCaseSensitive(json, key); + APPSPAWN_CHECK_ONLY_EXPER(obj != NULL, return NULL); + APPSPAWN_CHECK(cJSON_IsString(obj), return NULL, "json is not string %{public}s %s", key, cJSON_Print(obj)); + return cJSON_GetStringValue(obj); +} + +__attribute__((always_inline)) inline bool GetBoolValueFromJsonObj(const cJSON *json, const char *key, bool def) +{ + char *value = GetStringFromJsonObj(json, key); + APPSPAWN_CHECK_ONLY_EXPER(value != NULL, return def); + + if (strcmp(value, "true") == 0 || strcmp(value, "ON") == 0 || strcmp(value, "True") == 0) { + return true; + } + return false; +} + +__attribute__((always_inline)) inline uint32_t GetIntValueFromJsonObj(const cJSON *json, const char *key, uint32_t def) +{ + APPSPAWN_CHECK(json != NULL, return def, "Invalid json"); + APPSPAWN_CHECK(cJSON_IsObject(json), return def, "json is not object."); + return cJSON_GetNumberValue(cJSON_GetObjectItemCaseSensitive(json, key)); +} + +namespace OHOS { +namespace AppSpawnModuleTest { +class AppSpawnTestCommander : public ThreadContext { +public: + AppSpawnTestCommander() + { + exit_ = 0; + appSpawn_ = 1; + dumpFlags = 0; + msgType_ = 0; + } + ~AppSpawnTestCommander() + { + if (ptyFd_ != -1) { + (void)close(ptyFd_); + ptyFd_ = -1; + } + if (appInfoConfig_) { + cJSON_Delete(appInfoConfig_); + appInfoConfig_ = nullptr; + } + } + + int ProcessArgs(int argc, char *const argv[]); + int Run(); + + int CreateOtherMsg(AppSpawnReqMsgHandle &reqHandle, pid_t pid); + int CreateMsg(AppSpawnReqMsgHandle &reqHandle, const char *defaultConfig); + int StartSendMsg(); + int SendMsg(); + AppSpawnClientHandle GetClientHandle() { return clientHandle_; } +private: + std::vector split(const std::string &str, const std::string &pattern); + int InitPtyInterface(); + int ProcessInputCmd(std::string &cmd); + int AddExtTlv(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle); + int BuildMsgFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle); + int AddBundleInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle); + int GetDacInfoFromJson(const cJSON *appInfoConfig, AppDacInfo &info); + int GetInternetPermissionInfoFromJson(const cJSON *appInfoConfig, AppSpawnMsgInternetInfo &info); + int GetAccessTokenFromJson(const cJSON *appInfoConfig, AppSpawnMsgAccessToken &info); + int AddDomainInfoFromJson(const cJSON *appInfoConfig, AppSpawnReqMsgHandle reqHandle); + uint32_t GetUint32ArrayFromJson(const cJSON *json, const char *name, uint32_t dataArray[], uint32_t maxCount); + static AppSpawnTestCommander *ConvertTo(const ThreadContext *context) + { + return const_cast(reinterpret_cast(context)); + } + static void TaskExecutorProc(ThreadTaskHandle handle, const ThreadContext *context); + static void SendTaskFinish(ThreadTaskHandle handle, const ThreadContext *context); + static void InputThread(ThreadTaskHandle handle, const ThreadContext *context); + static void DumpThread(ThreadTaskHandle handle, const ThreadContext *context); + + int ptyFd_{-1}; + uint32_t dumpFlags : 1; + uint32_t exit_ : 1; + uint32_t appSpawn_ : 1; + uint32_t msgType_; + pid_t terminatePid_; + uint32_t threadCount_{1}; + std::string ptyName_{}; + std::string testFileName_{}; + std::string processName_{}; + cJSON *appInfoConfig_ { nullptr}; + AppSpawnClientHandle clientHandle_{nullptr}; + ThreadMgr threadMgr_{nullptr}; + ThreadTaskHandle inputHandle_{0}; + ThreadTaskHandle dumpHandle_{0}; +}; +} // namespace AppSpawnModuleTest +} // namespace OHOS +#endif // APPSPAWN_TEST_CMD_H \ No newline at end of file diff --git a/test/moduletest/appspawn_test_main.cpp b/test/moduletest/appspawn_test_main.cpp new file mode 100755 index 00000000..ee3a2c98 --- /dev/null +++ b/test/moduletest/appspawn_test_main.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "appspawn.h" +#include "appspawn_msg.h" +#include "appspawn_utils.h" +#include "appspawn_test_cmder.h" +#include "command_lexer.h" +#include "cJSON.h" +#include "securec.h" +#include "thread_manager.h" + +int main(int argc, char *const argv[]) +{ + if (argc <= 0) { + return 0; + } + + OHOS::AppSpawnModuleTest::AppSpawnTestCommander commander; + int ret = commander.ProcessArgs(argc, argv); + if (ret == 0) { + commander.Run(); + } + return 0; +} \ No newline at end of file diff --git a/test/moduletest/threadpool/BUILD.gn b/test/moduletest/threadpool/BUILD.gn new file mode 100755 index 00000000..990695e7 --- /dev/null +++ b/test/moduletest/threadpool/BUILD.gn @@ -0,0 +1,37 @@ +# Copyright (c) 2024 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. + +import("//base/startup/appspawn/appspawn.gni") +import("//build/ohos.gni") + +config("appspawn_threadpool") { + include_dirs = [ "." ] +} + +ohos_source_set("libappspawn_threadpool") { + sources = [ "thread_manager.c" ] + include_dirs = [ + ".", + "${appspawn_path}/util/include", + "${appspawn_path}/common", + ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "init:libbegetutil", + ] + public_configs = [ ":appspawn_threadpool" ] + subsystem_name = "${subsystem_name}" + part_name = "${part_name}" +} diff --git a/test/moduletest/threadpool/thread_manager.c b/test/moduletest/threadpool/thread_manager.c new file mode 100755 index 00000000..b0cebf77 --- /dev/null +++ b/test/moduletest/threadpool/thread_manager.c @@ -0,0 +1,544 @@ +/* + * Copyright (c) 2024 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 "thread_manager.h" + +#include +#include +#include + +#include "appspawn_utils.h" +#include "list.h" + +typedef struct { + atomic_uint threadExit; + uint32_t index; + pthread_t threadId; +} ThreadNode; + +typedef struct { + pthread_mutex_t mutex; // 保护执行队列 + pthread_cond_t cond; // 线程等待条件 + ListNode taskList; // 任务队列,任务还没有启动 + ListNode waitingTaskQueue; // 启动的任务,排队等待执行 + ListNode executingTaskQueue; // 正在执行 + ListNode executorQueue; // 执行节点,保存 TaskExecuteNode + uint32_t executorCount; + uint32_t maxThreadCount; + uint32_t currTaskId; + struct timespec lastAdjust; + uint32_t validThreadCount; + ThreadNode threadNode[1]; // 线程信息,控制线程的退出和结束 +} ThreadManager; + +typedef struct { + uint32_t taskId; + ListNode node; + ListNode executorList; + uint32_t totalTask; + atomic_uint taskFlags; // 表示任务是否被取消,各线程检查后决定任务线程是否结束 + atomic_uint finishTaskCount; + const ThreadContext *context; + TaskFinishProcessor finishProcess; + pthread_mutex_t mutex; // 保护执行队列 + pthread_cond_t cond; // 同步执行时,等待确认 +} TaskNode; + +typedef struct { + ListNode node; // 保存sub task到对应的task,方便管理 + ListNode executeNode; // 等待处理的任务节点 + TaskNode *task; + const ThreadContext *context; + TaskExecutor executor; +} TaskExecuteNode; + +static ThreadManager *g_threadManager = NULL; + +static void *ManagerThreadProc(void *args); +static void *ThreadExecute(void *args); + +static void SetCondAttr(pthread_cond_t *cond) +{ + pthread_condattr_t attr; + pthread_condattr_init(&attr); + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC); + pthread_cond_init(cond, &attr); + pthread_condattr_destroy(&attr); +} + +static void ConvertToTimespec(int time, struct timespec *tm) +{ + struct timespec start; + clock_gettime(CLOCK_MONOTONIC, &start); + uint64_t ns = time; + ns *= APPSPAWN_MSEC_TO_NSEC; + ns += start.tv_sec * APPSPAWN_SEC_TO_NSEC + start.tv_nsec; + tm->tv_sec = ns / APPSPAWN_SEC_TO_NSEC; + tm->tv_nsec = ns % APPSPAWN_SEC_TO_NSEC; +} + +static TaskExecuteNode *PopTaskExecutor(ThreadManager *mgr) +{ + TaskExecuteNode *executor = NULL; + pthread_mutex_lock(&mgr->mutex); + ListNode *node = mgr->executorQueue.next; + if (node != &mgr->executorQueue) { + OH_ListRemove(node); + OH_ListInit(node); + executor = ListEntry(node, TaskExecuteNode, executeNode); + mgr->executorCount--; + } + pthread_mutex_unlock(&mgr->mutex); + return executor; +} + +static int AddExecutor(ThreadManager *mgr, const TaskNode *task) +{ + ListNode *node = task->executorList.next; + while (node != &task->executorList) { + TaskExecuteNode *executor = ListEntry(node, TaskExecuteNode, node); + APPSPAWN_LOGV("AddExecutor task: %{public}u executorCount: %{public}u executor: %{public}p %{public}u", + task->taskId, mgr->executorCount, executor, executor->task->taskId); + + // 插入尾部执行 + pthread_mutex_lock(&mgr->mutex); + OH_ListRemove(&executor->executeNode); + OH_ListInit(&executor->executeNode); + OH_ListAddTail(&mgr->executorQueue, &executor->executeNode); + mgr->executorCount++; + pthread_mutex_unlock(&mgr->mutex); + + node = node->next; + } + return 0; +} + +static void RunExecutor(ThreadManager *mgr, ThreadNode *threadNode, uint32_t maxCount) +{ + APPSPAWN_LOGV("RunExecutor in thread: %{public}d executorCount: %{public}u ", + threadNode->index, mgr->executorCount); + TaskExecuteNode *executor = PopTaskExecutor(mgr); + uint32_t count = 0; + while (executor != NULL && !threadNode->threadExit) { + APPSPAWN_LOGV("RunExecutor task: %{public}u executor: %{public}p", executor->task->taskId, executor); + atomic_fetch_add(&executor->task->finishTaskCount, 1); + executor->executor(executor->task->taskId, executor->context); + count++; + if (count >= maxCount) { + break; + } + executor = PopTaskExecutor(mgr); + } + APPSPAWN_LOGV("RunExecutor executorCount: %{public}u end", mgr->executorCount); +} + +static int TaskCompareTaskId(ListNode *node, void *data) +{ + TaskNode *task = ListEntry(node, TaskNode, node); + return task->taskId - *(uint32_t *)data; +} + +static TaskNode *GetTask(ThreadManager *mgr, ListNode *queue, uint32_t taskId) +{ + ListNode *node = NULL; + pthread_mutex_lock(&mgr->mutex); + node = OH_ListFind(queue, &taskId, TaskCompareTaskId); + pthread_mutex_unlock(&mgr->mutex); + if (node == NULL) { + return NULL; + } + return ListEntry(node, TaskNode, node); +} + +static void DeleteTask(TaskNode *task) +{ + APPSPAWN_LOGV("DeleteTask task: %{public}u ", task->taskId); + + if (!ListEmpty(task->node)) { + return; + } + OH_ListRemoveAll(&task->executorList, NULL); + pthread_cond_destroy(&task->cond); + pthread_mutex_destroy(&task->mutex); + free(task); +} + +static TaskNode *PopTask(ThreadManager *mgr, ListNode *queue) +{ + TaskNode *task = NULL; + pthread_mutex_lock(&mgr->mutex); + ListNode *node = queue->next; + if (node != queue) { + OH_ListRemove(node); + OH_ListInit(node); + task = ListEntry(node, TaskNode, node); + } + pthread_mutex_unlock(&mgr->mutex); + return task; +} + +static void PushTask(ThreadManager *mgr, TaskNode *task, ListNode *queue) +{ + pthread_mutex_lock(&mgr->mutex); + OH_ListAddTail(queue, &task->node); + pthread_cond_broadcast(&mgr->cond); + pthread_mutex_unlock(&mgr->mutex); +} + +static void SafeRemoveTask(ThreadManager *mgr, TaskNode *task) +{ + pthread_mutex_lock(&mgr->mutex); + OH_ListRemove(&task->node); + OH_ListInit(&task->node); + pthread_mutex_unlock(&mgr->mutex); + + ListNode *node = task->executorList.next; + while (node != &task->executorList) { + OH_ListRemove(node); + OH_ListInit(node); + TaskExecuteNode *executor = ListEntry(node, TaskExecuteNode, node); + pthread_mutex_lock(&mgr->mutex); + if (!ListEmpty(executor->executeNode)) { + OH_ListRemove(&executor->executeNode); + OH_ListInit(&executor->executeNode); + mgr->executorCount--; + } + pthread_mutex_unlock(&mgr->mutex); + free(executor); + + node = task->executorList.next; + } +} + +static void ExecuteTask(ThreadManager *mgr) +{ + TaskNode *task = PopTask(mgr, &mgr->waitingTaskQueue); + if (task == NULL) { + return; + } + + APPSPAWN_LOGV("ExecuteTask task: %{public}u ", task->taskId); + AddExecutor(mgr, task); + PushTask(mgr, task, &mgr->executingTaskQueue); + return; +} + +static void CheckTaskComplete(ThreadManager *mgr) +{ + TaskNode *task = PopTask(mgr, &mgr->executingTaskQueue); + if (task == NULL) { + return; + } + if (task->totalTask <= atomic_load(&task->finishTaskCount)) { + if (task->finishProcess != NULL) { + task->finishProcess(task->taskId, task->context); + DeleteTask(task); + return; + } + pthread_mutex_lock(&task->mutex); + pthread_cond_signal(&task->cond); + pthread_mutex_unlock(&task->mutex); + return; + } + PushTask(mgr, task, &mgr->executingTaskQueue); + return; +} + +static void TaskQueueDestroyProc(ListNode *node) +{ + OH_ListRemove(node); + TaskNode *task = ListEntry(node, TaskNode, node); + DeleteTask(task); +} + +int CreateThreadMgr(uint32_t maxThreadCount, ThreadMgr *instance) +{ + if (g_threadManager != NULL) { + *instance = (ThreadMgr)g_threadManager; + return 0; + } + + ThreadManager *mgr = (ThreadManager *)malloc(sizeof(ThreadManager) + maxThreadCount * sizeof(ThreadNode)); + APPSPAWN_CHECK(mgr != NULL, return -1, "Failed to create thread manager"); + + mgr->executorCount = 0; + mgr->currTaskId = 0; + mgr->validThreadCount = 0; + mgr->maxThreadCount = maxThreadCount; + OH_ListInit(&mgr->taskList); + OH_ListInit(&mgr->waitingTaskQueue); + OH_ListInit(&mgr->executingTaskQueue); + OH_ListInit(&mgr->executorQueue); + pthread_mutex_init(&mgr->mutex, NULL); + SetCondAttr(&mgr->cond); + + for (uint32_t index = 0; index < maxThreadCount + 1; index++) { + mgr->threadNode[index].index = index; + mgr->threadNode[index].threadId = INVALID_THREAD_ID; + atomic_init(&mgr->threadNode[index].threadExit, 0); + } + g_threadManager = mgr; + int ret = pthread_create(&mgr->threadNode[0].threadId, NULL, ManagerThreadProc, (void *)&mgr->threadNode[0]); + if (ret != 0) { + APPSPAWN_LOGE("Failed to create thread for manager"); + g_threadManager = NULL; + free(mgr); + return -1; + } + *instance = (ThreadMgr)mgr; + APPSPAWN_LOGV("Create thread manager success maxThreadCount: %{public}u", maxThreadCount); + return 0; +} + +int DestroyThreadMgr(ThreadMgr instance) +{ + APPSPAWN_LOGV("DestroyThreadMgr"); + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + + for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) { + if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) { + atomic_store(&mgr->threadNode[index].threadExit, 1); + APPSPAWN_LOGV("DestroyThreadMgr index %{public}d %{public}d", index, mgr->threadNode[index].threadExit); + } + } + pthread_mutex_lock(&mgr->mutex); + pthread_cond_broadcast(&mgr->cond); + pthread_mutex_unlock(&mgr->mutex); + for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) { + if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) { + pthread_join(mgr->threadNode[index].threadId, NULL); + APPSPAWN_LOGV("DestroyThreadMgr index %{public}d end", index); + } + } + + pthread_mutex_lock(&mgr->mutex); + OH_ListRemoveAll(&mgr->taskList, TaskQueueDestroyProc); + OH_ListRemoveAll(&mgr->waitingTaskQueue, TaskQueueDestroyProc); + OH_ListRemoveAll(&mgr->executingTaskQueue, TaskQueueDestroyProc); + OH_ListRemoveAll(&mgr->executorQueue, TaskQueueDestroyProc); + pthread_mutex_unlock(&mgr->mutex); + + pthread_cond_destroy(&mgr->cond); + pthread_mutex_destroy(&mgr->mutex); + return 0; +} + +int ThreadMgrAddTask(ThreadMgr instance, ThreadTaskHandle *taskHandle) +{ + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + TaskNode *task = (TaskNode *)malloc(sizeof(TaskNode)); + APPSPAWN_CHECK(task != NULL, return -1, "Failed to create thread task"); + + task->context = NULL; + task->finishProcess = NULL; + task->totalTask = 0; + atomic_init(&task->taskFlags, 0); + atomic_init(&task->finishTaskCount, 0); + OH_ListInit(&task->node); + OH_ListInit(&task->executorList); + pthread_mutex_init(&task->mutex, NULL); + SetCondAttr(&task->cond); + + pthread_mutex_lock(&mgr->mutex); + task->taskId = mgr->currTaskId++; + OH_ListAddTail(&mgr->taskList, &task->node); + pthread_mutex_unlock(&mgr->mutex); + *taskHandle = task->taskId; + APPSPAWN_LOGV("Create thread task success task id: %{public}u", task->taskId); + return 0; +} + +int ThreadMgrAddExecutor(ThreadMgr instance, + ThreadTaskHandle taskHandle, TaskExecutor executor, const ThreadContext *context) +{ + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle); + APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle); + + TaskExecuteNode *node = (TaskExecuteNode *)malloc(sizeof(TaskExecuteNode)); + APPSPAWN_CHECK(node != NULL, return -1, "Failed to create thread executor for task %{public}u", taskHandle); + node->task = task; + OH_ListInit(&node->node); + OH_ListInit(&node->executeNode); + node->context = context; + node->executor = executor; + task->totalTask++; + OH_ListAddTail(&task->executorList, &node->node); + return 0; +} + +int ThreadMgrCancelTask(ThreadMgr instance, ThreadTaskHandle taskHandle) +{ + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle); + if (task != NULL) { + SafeRemoveTask(mgr, task); + DeleteTask(task); + return 0; + } + task = GetTask(mgr, &mgr->waitingTaskQueue, taskHandle); + if (task != NULL) { + SafeRemoveTask(mgr, task); + DeleteTask(task); + return 0; + } + task = GetTask(mgr, &mgr->executingTaskQueue, taskHandle); + if (task != NULL) { + SafeRemoveTask(mgr, task); + DeleteTask(task); + return 0; + } + return 0; +} + +int TaskSyncExecute(ThreadMgr instance, ThreadTaskHandle taskHandle) +{ + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle); + APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle); + + pthread_mutex_lock(&task->mutex); + OH_ListRemove(&task->node); + OH_ListInit(&task->node); + OH_ListAddTail(&mgr->waitingTaskQueue, &task->node); + pthread_cond_broadcast(&mgr->cond); + pthread_mutex_unlock(&task->mutex); + APPSPAWN_LOGV("TaskSyncExecute task: %{public}u", task->taskId); + struct timespec abstime; + int ret = 0; + do { + ConvertToTimespec(60 * 1000, &abstime); // wait 60 * 1000 60s + pthread_mutex_lock(&task->mutex); + ret = pthread_cond_timedwait(&task->cond, &task->mutex, &abstime); + pthread_mutex_unlock(&task->mutex); + APPSPAWN_LOGV("TaskSyncExecute success task id: %{public}u ret: %{public}d", task->taskId, ret); + } while (ret == ETIMEDOUT); + + DeleteTask(task); + return ret; +} + +int TaskExecute(ThreadMgr instance, + ThreadTaskHandle taskHandle, TaskFinishProcessor process, const ThreadContext *context) +{ + ThreadManager *mgr = (ThreadManager *)instance; + APPSPAWN_CHECK(mgr != NULL, return -1, "Invalid thread manager"); + TaskNode *task = GetTask(mgr, &mgr->taskList, taskHandle); + APPSPAWN_CHECK(task != NULL, return -1, "Invalid thread task %{public}u", taskHandle); + + task->finishProcess = process; + task->context = context; + pthread_mutex_lock(&mgr->mutex); + OH_ListRemove(&task->node); + OH_ListInit(&task->node); + OH_ListAddTail(&mgr->waitingTaskQueue, &task->node); + pthread_cond_broadcast(&mgr->cond); + pthread_mutex_unlock(&mgr->mutex); + APPSPAWN_LOGV("TaskExecute task: %{public}u", task->taskId); + return 0; +} + +static void CheckAndCreateNewThread(ThreadManager *mgr) +{ + if (mgr->maxThreadCount <= mgr->validThreadCount) { + return; + } + if (mgr->executorCount <= mgr->validThreadCount) { + return; + } + APPSPAWN_LOGV("CheckAndCreateNewThread maxThreadCount: %{public}u validThreadCount: %{public}u %{public}u", + mgr->maxThreadCount, mgr->validThreadCount, mgr->executorCount); + + uint32_t totalThread = mgr->maxThreadCount; + if (mgr->executorCount <= mgr->maxThreadCount) { + totalThread = mgr->executorCount; + } + + for (uint32_t index = 0; index < mgr->maxThreadCount + 1; index++) { + if (mgr->threadNode[index].threadId != INVALID_THREAD_ID) { + continue; + } + int ret = pthread_create(&mgr->threadNode[index].threadId, + NULL, ThreadExecute, (void *)&(mgr->threadNode[index])); + APPSPAWN_CHECK(ret == 0, return, "Failed to create thread for %{public}u", index); + APPSPAWN_LOGV("Create thread success index: %{public}u", mgr->threadNode[index].index); + mgr->validThreadCount++; + if (mgr->validThreadCount >= totalThread) { + return; + } + } + return; +} + +static void *ManagerThreadProc(void *args) +{ + ThreadManager *mgr = g_threadManager; + ThreadNode *threadNode = (ThreadNode *)args; + struct timespec abstime; + int ret = 0; + while (!threadNode->threadExit) { + pthread_mutex_lock(&mgr->mutex); + do { + uint32_t timeout = 60 * 1000; // 60 * 1000 60s + if (!ListEmpty(mgr->waitingTaskQueue)) { + break; + } + if (!ListEmpty(mgr->executingTaskQueue)) { + timeout = 500; // 500ms + } + ConvertToTimespec(timeout, &abstime); + ret = pthread_cond_timedwait(&mgr->cond, &mgr->mutex, &abstime); + if (!ListEmpty(mgr->executingTaskQueue) || ret == ETIMEDOUT) { + break; + } + if (threadNode->threadExit) { + break; + } + } while (1); + pthread_mutex_unlock(&mgr->mutex); + + ExecuteTask(mgr); + CheckAndCreateNewThread(mgr); + + if (mgr->validThreadCount == 0) { + RunExecutor(mgr, threadNode, 5); // 5 max thread + } + CheckTaskComplete(mgr); + } + return 0; +} + +static void *ThreadExecute(void *args) +{ + ThreadManager *mgr = g_threadManager; + ThreadNode *threadNode = (ThreadNode *)args; + struct timespec abstime; + int ret = 0; + while (!threadNode->threadExit) { + pthread_mutex_lock(&mgr->mutex); + while (ListEmpty(mgr->executorQueue) && !threadNode->threadExit) { + ConvertToTimespec(60 * 1000, &abstime); // 60 * 1000 60s + ret = pthread_cond_timedwait(&mgr->cond, &mgr->mutex, &abstime); + } + pthread_mutex_unlock(&mgr->mutex); + APPSPAWN_LOGV("bbbb threadNode->threadExit %{public}d", threadNode->threadExit); + RunExecutor(mgr, threadNode, 1); + } + return NULL; +} diff --git a/test/moduletest/threadpool/thread_manager.h b/test/moduletest/threadpool/thread_manager.h new file mode 100755 index 00000000..1ee30bb5 --- /dev/null +++ b/test/moduletest/threadpool/thread_manager.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 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_MODULE_THREAD_MGR_H +#define APPSPAWN_MODULE_THREAD_MGR_H +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define INVALID_THREAD_ID 0 +#define INVALID_TASK_HANDLE 0 + +typedef uint32_t ThreadTaskHandle; +typedef void *ThreadMgr; +typedef struct TagThreadContext ThreadContext; + +typedef void (*TaskFinishProcessor)(ThreadTaskHandle handle, const ThreadContext *context); +typedef void (*TaskExecutor)(ThreadTaskHandle handle, const ThreadContext *context); + +int CreateThreadMgr(uint32_t maxThreadCount, ThreadMgr *mgr); +int DestroyThreadMgr(ThreadMgr instance); +int ThreadMgrAddTask(ThreadMgr mgr, ThreadTaskHandle *taskHandle); +int ThreadMgrAddExecutor(ThreadMgr mgr, + ThreadTaskHandle taskHandle, TaskExecutor executor, const ThreadContext *context); +int ThreadMgrCancelTask(ThreadMgr mgr, ThreadTaskHandle taskHandle); +int TaskSyncExecute(ThreadMgr mgr, ThreadTaskHandle taskHandle); // 同步执行 +int TaskExecute(ThreadMgr mgr, ThreadTaskHandle taskHandle, TaskFinishProcessor process, const ThreadContext *context); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_MODULE_THREAD_MGR_H diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 56dea3b2..e85178bb 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -36,13 +36,16 @@ config("utest_config") { } include_dirs = [ + "${appspawn_path}", "${appspawn_path}/test/unittest", "${appspawn_path}/test/mock/include", "${appspawn_path}/common", "${appspawn_path}/standard", "${appspawn_path}/adapter", "${appspawn_path}/adapter/sysevent", + "${appspawn_path}/modules/sandbox", "${appspawn_path}/interfaces/innerkits/include", + "${appspawn_path}/interfaces/innerkits_new/include", "${appspawn_path}/util/include", "//commonlibrary/c_utils/base/include", "ability_runtime_kits_path/appkit/native/app/include", @@ -98,6 +101,7 @@ if (!defined(ohos_lite)) { "${appspawn_path}/interfaces/innerkits/client/appspawn_socket.cpp", "${appspawn_path}/interfaces/innerkits/client/client_socket.cpp", "${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp", + "${appspawn_path}/standard/appspawn_msgmgr.c", "${appspawn_path}/standard/appspawn_process.c", "${appspawn_path}/standard/appspawn_service.c", "${appspawn_path}/util/src/command_lexer.cpp", @@ -128,6 +132,7 @@ if (!defined(ohos_lite)) { "ace_engine:ace_forward_compatibility", "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", + "cJSON:cjson", "c_utils:utils", "config_policy:configpolicy_util", "eventhandler:libeventhandler", diff --git a/test/unittest/app_spawn_client_test/BUILD.gn b/test/unittest/app_spawn_client_test/BUILD.gn new file mode 100755 index 00000000..15344c3a --- /dev/null +++ b/test/unittest/app_spawn_client_test/BUILD.gn @@ -0,0 +1,75 @@ +# Copyright (c) 2024 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. + +import("//base/startup/appspawn/appspawn.gni") +import("//build/test.gni") + +ohos_unittest("AppSpawn_client_ut") { + module_out_path = "${module_output_path}" + deps = [] + defines = [ + "clone=CloneStub", + "bind=BindStub", + "listen=ListenStub", + "lchown=LchownStub", + "lchmod=LchmodStub", + "getsockopt=GetsockoptStub", + "setgroups=SetgroupsStub", + "setresuid=SetresuidStub", + "setresgid=SetresgidStub", + "capset=CapsetStub", + "dlopen=DlopenStub", + "dlsym=DlsymStub", + "dlclose=DlcloseStub", + "waitpid=WaitpidStub", + "HapContext=HapContextStub", + "APPSPAWN_TEST", + "OHOS_DEBUG", + "GRAPHIC_PERMISSION_CHECK", + ] + include_dirs = [ + "${appspawn_path}", + "${appspawn_path}/test/unittest", + "${appspawn_path}/common", + "${appspawn_path}/standard", + "${appspawn_path}/adapter", + "${appspawn_path}/adapter/sysevent", + "${appspawn_path}/modules/sandbox", + "${appspawn_path}/interfaces/innerkits_new/include", + "${appspawn_path}/interfaces/innerkits_new/client", + "${appspawn_path}/interfaces/innerkits_new/permission", + "${appspawn_path}/util/include", + "${appspawn_path}/interfaces/innerkits_new/module_engine/include", + "//third_party/json/include", + ] + sources = [ + "${appspawn_path}/interfaces/innerkits_new/client/appspawn_client.c", + "${appspawn_path}/interfaces/innerkits_new/client/appspawn_msg.c", + "${appspawn_path}/interfaces/innerkits_new/permission/appspawn_mount_permission.c", + "${appspawn_path}/modules/sandbox/appspawn_permission.c", + "${appspawn_path}/util/src/appspawn_utils.c", + ] + + sources += [ "${appspawn_path}/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp" ] + + deps += [ + "//third_party/cJSON:cjson", + "//third_party/selinux:libselinux", + ] + external_deps = [ + "c_utils:utils", + "config_policy:configpolicy_util", + "hilog:libhilog", + "init:libbegetutil", + ] +} diff --git a/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp b/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp new file mode 100755 index 00000000..1c7e49be --- /dev/null +++ b/test/unittest/app_spawn_client_test/app_spawn_interface_test.cpp @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2024-2024 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appspawn.h" +#include "appspawn_hook.h" +#include "appspawn_mount_permission.h" +#include "appspawn_service.h" +#include "appspawn_utils.h" +#include "securec.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +class AppSpawnInterfaceTest : public testing::Test { +public: + static void SetUpTestCase() {} + static void TearDownTestCase() {} + void SetUp() {} + void TearDown() {} +}; + +/** + * @brief 测试接口:AppSpawnClientInit + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_001, TestSize.Level0) +{ + int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, nullptr); + EXPECT_EQ(APPSPAWN_ARG_INVALID, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_002, TestSize.Level0) +{ + int ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, nullptr); + EXPECT_EQ(APPSPAWN_ARG_INVALID, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_003, TestSize.Level0) +{ + int ret = AppSpawnClientInit("test", nullptr); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_004, TestSize.Level0) +{ + int ret = AppSpawnClientInit(nullptr, nullptr); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Init_005, TestSize.Level0) +{ + AppSpawnClientHandle handle; + int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &handle); + EXPECT_EQ(0, ret); +} + +/** + * @brief 测试接口:AppSpawnClientDestroy + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_001, TestSize.Level0) +{ + AppSpawnClientHandle handle; + int ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &handle); + EXPECT_EQ(0, ret); + ret = AppSpawnClientDestroy(handle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_002, TestSize.Level0) +{ + AppSpawnClientHandle handle; + int ret = AppSpawnClientInit(NWEBSPAWN_SERVER_NAME, &handle); + EXPECT_EQ(0, ret); + ret = AppSpawnClientDestroy(handle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Destroy_003, TestSize.Level0) +{ + int ret = AppSpawnClientDestroy(nullptr); + EXPECT_EQ(APPSPAWN_SYSTEM_ERROR, ret); +} + +/** + * @brief 测试接口:AppSpawnClientSendMsg + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_001, TestSize.Level0) +{ + int ret = 0; + AppSpawnReqMsgHandle reqHandle = nullptr; + ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(nullptr, reqHandle, &result); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_002, TestSize.Level0) +{ + int ret = 0; + AppSpawnClientHandle clientHandle = nullptr; + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + EXPECT_EQ(0, ret); + AppSpawnResult result = {}; + ret = AppSpawnClientSendMsg(clientHandle, nullptr, &result); + EXPECT_NE(0, ret); + AppSpawnClientDestroy(clientHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Send_Msg_003, TestSize.Level0) +{ + int ret = 0; + AppSpawnClientHandle clientHandle = nullptr; + ret = AppSpawnClientInit(APPSPAWN_SERVER_NAME, &clientHandle); + EXPECT_EQ(0, ret); + AppSpawnReqMsgHandle reqHandle = nullptr; + ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + ret = AppSpawnClientSendMsg(clientHandle, reqHandle, nullptr); + EXPECT_NE(0, ret); + AppSpawnClientDestroy(clientHandle); +} + +/** + * @brief 测试接口:AppSpawnReqMsgCreate + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_002, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_GET_RENDER_TERMINATION_STATUS, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_003, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_SPAWN_NATIVE_PROCESS, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_DUMP, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_005, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MAX_TYPE_INVALID, "com.ohos.myapplication", &reqHandle); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_006, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication::@#$%^&*()test", &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_008, TestSize.Level0) +{ + char buffer[255]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_009, TestSize.Level0) +{ + char buffer[257]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_010, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, nullptr, &reqHandle); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_011, TestSize.Level0) +{ + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", nullptr); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_012, TestSize.Level0) +{ + const char *testMsg = "testMsg"; + char *p = const_cast(testMsg); + AppSpawnReqMsgHandle handle = reinterpret_cast(p); + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &handle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_013, TestSize.Level0) +{ + char buffer[128]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Create_014, TestSize.Level0) +{ + char buffer[129]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, buffer, &reqHandle); + EXPECT_EQ(0, ret); +} +/** + * @brief 测试接口:AppSpawnReqMsgFree + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_Free_001, TestSize.Level0) +{ + AppSpawnReqMsgFree(nullptr); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetBundleInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, "com.ohos.myapplication"); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_002, TestSize.Level0) +{ + int ret = AppSpawnReqMsgSetBundleInfo(nullptr, 0, "com.ohos.myapplication"); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_005, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 1, "com.ohos.myapplication"); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_ReqMsgSetBundleInfo_006, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, -1, "com.ohos.myapplication"); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_007, TestSize.Level0) +{ + char buffer[255]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_008, TestSize.Level0) +{ + char buffer[257]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer); + EXPECT_NE(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_009, TestSize.Level0) +{ + char buffer[128]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_ReqMsgSetBundleInfo_010, TestSize.Level0) +{ + char buffer[129]; + (void)memset_s(buffer, sizeof(buffer), 'A', sizeof(buffer)); + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetBundleInfo(reqHandle, 0, buffer); + EXPECT_EQ(0, ret); + AppSpawnReqMsgFree(reqHandle); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetAppDacInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_001, TestSize.Level0) +{ + AppDacInfo dacInfo; + dacInfo.uid = 20010029; // 20010029 test data + dacInfo.gid = 20010029; // 20010029 test data + dacInfo.gidCount = 2; // 2 count + dacInfo.gidTable[0] = 20010029; // 20010029 test data + dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, &dacInfo); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_002, TestSize.Level0) +{ + AppDacInfo dacInfo; + dacInfo.uid = 20010029; // 20010029 test data + dacInfo.gid = 20010029; // 20010029 test data + dacInfo.gidCount = 2; // 2 count + dacInfo.gidTable[0] = 20010029; // 20010029 test data + dacInfo.gidTable[1] = 20010029 + 1; // 20010029 test data + int ret = AppSpawnReqMsgSetAppDacInfo(nullptr, &dacInfo); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Msg_App_Dac_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppDacInfo(reqHandle, nullptr); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetAppDomainInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, "system_core"); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_002, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, "system_core"); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Domain_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppDomainInfo(reqHandle, 1, nullptr); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetAppInternetPermissionInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Permission_Info_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppInternetPermissionInfo(reqHandle, 102, 102); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Permission_Info_002, TestSize.Level0) +{ + int ret = AppSpawnReqMsgSetAppInternetPermissionInfo(nullptr, 102, 102); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetAppAccessToken + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Access_Token_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppAccessToken(reqHandle, 12345678); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Access_Token_002, TestSize.Level0) +{ + int ret = AppSpawnReqMsgSetAppAccessToken(nullptr, 12345678); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgSetAppOwnerId + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, "ohos.permission.FILE_ACCESS_MANAGER"); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_002, TestSize.Level0) +{ + int ret = AppSpawnReqMsgSetAppOwnerId(nullptr, "ohos.permission.FILE_ACCESS_MANAGER"); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Set_App_Owner_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgSetAppOwnerId(reqHandle, nullptr); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgAddPermission + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgAddPermission(reqHandle, "ohos.permission.READ_IMAGEVIDEO"); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_002, TestSize.Level0) +{ + int ret = AppSpawnReqMsgAddPermission(nullptr, "ohos.permission.READ_IMAGEVIDEO"); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Permission_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgAddPermission(reqHandle, nullptr); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgAddExtInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + const char *testData = "ssssssssssssss sssssssss ssssssss"; + ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1", + reinterpret_cast(const_cast(testData)), strlen(testData)); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_002, TestSize.Level0) +{ + const char *testData = "ssssssssssssss sssssssss ssssssss"; + int ret = AppSpawnReqMsgAddExtInfo(nullptr, "tlv-name-1", + reinterpret_cast(const_cast(testData)), strlen(testData)); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + const char *testData = "ssssssssssssss sssssssss ssssssss"; + ret = AppSpawnReqMsgAddExtInfo(reqHandle, nullptr, + reinterpret_cast(const_cast(testData)), strlen(testData)); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_Ext_Info_005, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + const char *testData = "ssssssssssssss sssssssss ssssssss"; + ret = AppSpawnReqMsgAddExtInfo(reqHandle, "tlv-name-1", nullptr, strlen(testData)); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:AppSpawnReqMsgAddStringInfo + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_001, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + const char *testData = "ssssssssssssss sssssssss ssssssss"; + ret = AppSpawnReqMsgAddStringInfo(reqHandle, "test", testData); + EXPECT_EQ(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_002, TestSize.Level0) +{ + const char *testData = "ssssssssssssss sssssssss ssssssss"; + int ret = AppSpawnReqMsgAddStringInfo(nullptr, "test", testData); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_004, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + const char *testData = "ssssssssssssss sssssssss ssssssss"; + ret = AppSpawnReqMsgAddStringInfo(reqHandle, nullptr, testData); + EXPECT_NE(0, ret); +} + +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_Add_String_Info_005, TestSize.Level0) +{ + AppSpawnReqMsgHandle reqHandle = nullptr; + int ret = AppSpawnReqMsgCreate(MSG_APP_SPAWN, "com.ohos.myapplication", &reqHandle); + EXPECT_EQ(0, ret); + ret = AppSpawnReqMsgAddStringInfo(reqHandle, "test", nullptr); + EXPECT_NE(0, ret); +} + +/** + * @brief 测试接口:GetPermissionByIndex + * + */ +HWTEST(AppSpawnInterfaceTest, App_Spawn_Interface_GetPermissionByIndex_005, TestSize.Level0) +{ + int32_t maxIndex = GetMaxPermissionIndex(); + for (int i = 0; i < maxIndex; i++) { + EXPECT_NE(GetPermissionByIndex(i), nullptr); + } + + EXPECT_EQ(GetPermissionByIndex(maxIndex), nullptr); + EXPECT_EQ(GetPermissionByIndex(-1), nullptr); + + int32_t index = GetPermissionIndex("ohos.permission.ACCESS_BUNDLE_DIR"); + int ret = index >= 0 && index < maxIndex ? 0 : -1; + EXPECT_EQ(0, ret); +} +} 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 2cb56fdd..e6f79f83 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 @@ -249,7 +249,7 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_10, TestSize.Level0) HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_012, TestSize.Level0) { GTEST_LOG_(INFO) << "App_Spawn_Sandbox_012 start"; - AppSpawnContent_ appContent = {0}; + AppSpawnContent appContent = {0}; AppSpawnClient appClient = {0}; pid_t pid = -1; AppSandboxArg *sandboxArg = (AppSandboxArg *)malloc(sizeof(AppSandboxArg)); 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 878b8062..e9e2b8a9 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 @@ -50,8 +50,6 @@ using nlohmann::json; extern "C" { #endif TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags); -bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *appProperty, - const uint8_t *buffer, uint32_t buffLen); void AddAppInfo(pid_t pid, const char *processName, AppOperateType code); void SignalHandler(const struct signalfd_siginfo *siginfo); int GetCgroupPath(const AppSpawnAppInfo *appInfo, char *buffer, uint32_t buffLen); @@ -59,6 +57,95 @@ int GetCgroupPath(const AppSpawnAppInfo *appInfo, char *buffer, uint32_t buffLen } #endif +static bool ReceiveRequestDataToExtraInfo(const TaskHandle taskHandle, AppSpawnClientExt *client, + const uint8_t *buffer, uint32_t buffLen) +{ + if (client->property.extraInfo.totalLength) { + ExtraInfo *extraInfo = &client->property.extraInfo; + if (extraInfo->savedLength == 0) { + extraInfo->data = (char *)malloc(extraInfo->totalLength); + APPSPAWN_CHECK(extraInfo->data != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: malloc extraInfo failed %{public}u", extraInfo->totalLength); + } + + uint32_t saved = extraInfo->savedLength; + uint32_t total = extraInfo->totalLength; + char *data = extraInfo->data; + + APPSPAWN_LOGI("Receiving extraInfo: (%{public}u saved + %{public}u incoming) / %{public}u total", + saved, buffLen, total); + + APPSPAWN_CHECK((total - saved) >= buffLen, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: too many data for extraInfo %{public}u ", buffLen); + + int ret = memcpy_s(data + saved, buffLen, buffer, buffLen); + APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: memcpy extraInfo failed"); + + extraInfo->savedLength += buffLen; + if (extraInfo->savedLength < extraInfo->totalLength) { + return false; + } + extraInfo->data[extraInfo->totalLength - 1] = 0; + return true; + } + return true; +} + +static int CheckRequestMsgValid(AppSpawnClientExt *client) +{ + if (client->property.extraInfo.totalLength >= EXTRAINFO_TOTAL_LENGTH_MAX) { + APPSPAWN_LOGE("extrainfo total length invalid,len: %{public}d", client->property.extraInfo.totalLength); + return -1; + } + for (int i = 0; i < APP_LEN_PROC_NAME; i++) { + if (client->property.processName[i] == '\0') { + return 0; + } + } + + APPSPAWN_LOGE("processname invalid"); + return -1; +} + +bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *client, + const uint8_t *buffer, uint32_t buffLen) +{ + APPSPAWN_CHECK(buffer != NULL && buffLen > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: Invalid buff, bufferLen:%{public}d", buffLen); + + // 1. receive AppParamter + if (client->property.extraInfo.totalLength == 0) { + APPSPAWN_CHECK(buffLen >= sizeof(client->property), LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: Invalid buffLen %{public}u", buffLen); + + int ret = memcpy_s(&client->property, sizeof(client->property), buffer, sizeof(client->property)); + APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "ReceiveRequestData: memcpy failed %{public}d:%{public}u", ret, buffLen); + + // reset extraInfo + client->property.extraInfo.savedLength = 0; + client->property.extraInfo.data = NULL; + + // update buffer + buffer += sizeof(client->property); + buffLen -= sizeof(client->property); + ret = CheckRequestMsgValid(client); + APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return false, "Invalid request msg"); + } + + // 2. check whether extraInfo exist + if (client->property.extraInfo.totalLength == 0) { // no extraInfo + APPSPAWN_LOGV("ReceiveRequestData: no extraInfo"); + return true; + } else if (buffLen == 0) { + APPSPAWN_LOGV("ReceiveRequestData: waiting for extraInfo"); + return false; + } + return ReceiveRequestDataToExtraInfo(taskHandle, client, buffer, buffLen); +} + static int MakeDir(const char *dir, mode_t mode) { int rc = -1; @@ -152,7 +239,7 @@ void AppSpawnStandardTest::SetUp() void AppSpawnStandardTest::TearDown() {} -int32_t TestSetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) +int32_t TestSetAppSandboxProperty(struct AppSpawnContent *content, AppSpawnClient *client) { return 0; } @@ -590,7 +677,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0) AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", (char*)longProcName.c_str(), longProcNameLen, 1); content->loadExtendLib = LoadExtendLib; content->runChildProcessor = RunChildProcessor; - int ret = DoStartApp((AppSpawnContent_*)content, &clientExt->client, (char*)"", 0); + int ret = DoStartApp((AppSpawnContent*)content, &clientExt->client, (char*)"", 0); EXPECT_EQ(ret, 0); if (strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "moduleTestProcessName") != 0) { @@ -598,12 +685,12 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0) } ret = SetAppSandboxProperty(nullptr, nullptr); EXPECT_NE(ret, 0); - ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client); + ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client); EXPECT_EQ(ret, 0); // APP_NO_SANDBOX clientExt->property.flags |= APP_NO_SANDBOX; - ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client); + ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client); EXPECT_EQ(ret, 0); clientExt->property.flags &= ~APP_NO_SANDBOX; @@ -614,7 +701,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0) \"versions\":[\"v10001\", \"v10002\"] \ }"); clientExt->property.extraInfo.totalLength = strlen(clientExt->property.extraInfo.data); - ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client); + ret = SetAppSandboxProperty((AppSpawnContent*)content, &clientExt->client); EXPECT_EQ(ret, 0); free(content); diff --git a/test/unittest/hnp_test/BUILD.gn b/test/unittest/hnp_test/BUILD.gn index 7f462ac4..76c6e6fc 100644 --- a/test/unittest/hnp_test/BUILD.gn +++ b/test/unittest/hnp_test/BUILD.gn @@ -47,10 +47,9 @@ if (!defined(ohos_lite)) { defines = [ "APPSPAWN_TEST" ] - deps = [ "//third_party/cJSON:cjson" ] - external_deps = [ "bounds_checking_function:libsec_shared", + "cJSON:cjson", "hilog:libhilog", "zlib:shared_libz", ] diff --git a/util/include/appspawn_utils.h b/util/include/appspawn_utils.h new file mode 100755 index 00000000..c3b20c73 --- /dev/null +++ b/util/include/appspawn_utils.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2024 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_UTILS_H +#define APPSPAWN_UTILS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appspawn_server.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifndef APPSPAWN_TEST +#define APPSPAWN_STATIC static +#else +#define APPSPAWN_STATIC +#endif + +#ifndef APPSPAWN_BASE_DIR +#define APPSPAWN_BASE_DIR "" +#endif +#if defined(__MUSL__) +#define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/unix/socket/" +#else +#define APPSPAWN_SOCKET_DIR APPSPAWN_BASE_DIR "/dev/socket/" +#endif + +#define APPSPAWN_CHECK_EXIT "AppSpawnCheckUnexpectedExitCall" +#define UNUSED(x) (void)(x) + +#define APP_COLD_START 0x01 +#define APP_ASAN_DETECTOR 0x02 +#define APP_DEVELOPER_MODE 0x04 + +#define MAX_LEN_SHORT_NAME 16 +#define DEFAULT_UMASK 0002 +#define UID_BASE 200000 // 20010029 +#define DEFAULT_DIR_MODE 0711 +#define USER_ID_BUFFER_SIZE 32 + +#define APPSPAWN_SEC_TO_NSEC 1000000000 +#define APPSPAWN_MSEC_TO_NSEC 1000000 +#define APPSPAWN_USEC_TO_NSEC 1000 +#define APPSPAWN_SEC_TO_MSEC 1000 + +#define MAX_JSON_FILE_LEN 102400 + +#define CHECK_FLAGS_BY_INDEX(flags, index) ((((flags) >> (index)) & 0x1) == 0x1) +#ifndef ARRAY_LENGTH +#define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0])) +#endif + +#define INVALID_PERMISSION_INDEX (-1) + +typedef enum { + APPSPAWN_OK = 0, + APPSPAWN_SYSTEM_ERROR = 0xD000000, + APPSPAWN_ARG_INVALID, + APPSPAWN_MSG_INVALID, + APPSPAWN_MSG_TOO_LONG, + APPSPAWN_TLV_NOT_SUPPORT, + APPSPAWN_TLV_NONE, + APPSPAWN_SANDBOX_NONE, + APPSPAWN_SANDBOX_LOAD_FAIL, + APPSPAWN_SANDBOX_INVALID, + APPSPAWN_SANDBOX_MOUNT_FAIL, + APPSPAWN_SPAWN_TIMEOUT, + APPSPAWN_CHILD_CRASH, + APPSPAWN_NATIVE_NOT_SUPPORT, + APPSPAWN_ACCESS_TOKEN_INVALID, + APPSPAWN_PERMISSION_NOT_SUPPORT, + APPSPAWN_BUFFER_NOT_ENOUGH, + APPSPAWN_TIMEOUT, + APPSPAWN_FORK_FAIL, + APPSPAWN_NODE_EXIST, +} AppSpawnErrorCode; + +typedef struct cJSON cJSON; +typedef struct TagParseJsonContext ParseJsonContext; +typedef int (*ParseConfig)(const cJSON *root, ParseJsonContext *context); +int ParseJsonConfig(const char *path, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context); +cJSON *GetJsonObjFromFile(const char *jsonPath); + +uint8_t *Base64Decode(const char *data, uint32_t dataLen, uint32_t *outLen); +char *Base64Encode(const uint8_t *data, uint32_t len); +void AppSpawnDump(const char *fmt, ...); +void SetDumpToStream(FILE *stream); + +typedef int (*SplitStringHandle)(const char *str, void *context); +int32_t StringSplit(const char *str, const char *separator, void *context, SplitStringHandle handle); +char *GetLastStr(const char *str, const char *dst); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // APPSPAWN_UTILS_H diff --git a/util/include/env_utils.h b/util/include/env_utils.h index 8f6ac3c7..4e87426d 100644 --- a/util/include/env_utils.h +++ b/util/include/env_utils.h @@ -24,7 +24,7 @@ extern "C" { #endif // __cplusplus -int32_t SetEnvInfo(struct AppSpawnContent_ *content, AppSpawnClient *client); +int32_t SetEnvInfo(struct AppSpawnContent *content, AppSpawnClient *client); #ifdef __cplusplus } diff --git a/util/src/appspawn_utils.c b/util/src/appspawn_utils.c new file mode 100644 index 00000000..df68d971 --- /dev/null +++ b/util/src/appspawn_utils.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2024 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_utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appspawn_hook.h" +#include "cJSON.h" +#include "config_policy_utils.h" +#include "parameter.h" +#include "securec.h" + +int MakeDirRec(const char *path, mode_t mode, int lastPath) +{ + if (path == NULL || *path == '\0') { + return -1; + } + APPSPAWN_CHECK(path != NULL && *path != '\0', return -1, "Invalid path to create"); + char buffer[PATH_MAX] = {0}; + const char slash = '/'; + const char *p = path; + char *curPos = strchr(path, slash); + while (curPos != NULL) { + int len = curPos - p; + p = curPos + 1; + if (len == 0) { + curPos = strchr(p, slash); + continue; + } + int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to copy path"); + ret = mkdir(buffer, mode); + if (ret == -1 && errno != EEXIST) { + return errno; + } + curPos = strchr(p, slash); + } + if (lastPath) { + if (mkdir(path, mode) == -1 && errno != EEXIST) { + return errno; + } + } + return 0; +} + +static void CheckDirRecursive(const char *path) +{ + char buffer[PATH_MAX] = {0}; + const char slash = '/'; + const char *p = path; + char *curPos = strchr(path, slash); + while (curPos != NULL) { + int len = curPos - p; + p = curPos + 1; + if (len == 0) { + curPos = strchr(p, slash); + continue; + } + int ret = memcpy_s(buffer, PATH_MAX, path, p - path - 1); + APPSPAWN_CHECK(ret == 0, return, "Failed to copy path"); + ret = access(buffer, F_OK); + APPSPAWN_CHECK(ret == 0, return, "Dir not exit %{public}s errno: %{public}d", buffer, errno); + curPos = strchr(p, slash); + } + int ret = access(path, F_OK); + APPSPAWN_CHECK(ret == 0, return, "Dir not exit %{public}s errno: %{public}d", buffer, errno); + return; +} + +int SandboxMountPath(const MountArg *arg) +{ + APPSPAWN_CHECK(arg != NULL && arg->originPath != NULL && arg->destinationPath != NULL, + return APPSPAWN_ARG_INVALID, "Invalid arg "); + int ret = mount(arg->originPath, arg->destinationPath, arg->fsType, arg->mountFlags, arg->options); + if (ret != 0) { + if (arg->originPath != NULL && strstr(arg->originPath, "/data/app/el2/") != NULL) { + CheckDirRecursive(arg->originPath); + } + APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s", + errno, arg->originPath, arg->destinationPath); + return errno; + } + ret = mount(NULL, arg->destinationPath, NULL, arg->mountSharedFlag, NULL); + if (ret != 0) { + APPSPAWN_LOGW("errno is: %{public}d, bind mount %{public}s => %{public}s", + errno, arg->originPath, arg->destinationPath); + return errno; + } + return 0; +} + +static void TrimTail(char *buffer, uint32_t maxLen) +{ + int32_t index = maxLen - 1; + while (index > 0) { + if (isspace(buffer[index])) { + buffer[index] = '\0'; + index--; + continue; + } + break; + } +} + +int32_t StringSplit(const char *str, const char *separator, void *context, SplitStringHandle handle) +{ + APPSPAWN_CHECK(str != NULL && handle != NULL && separator != NULL, return APPSPAWN_ARG_INVALID, "Invalid arg "); + + int ret = 0; + char *tmp = (char *)str; + char buffer[PATH_MAX] = {0}; + uint32_t len = strlen(separator); + uint32_t index = 0; + while ((*tmp != '\0') && (index < (uint32_t)sizeof(buffer))) { + if (index == 0 && isspace(*tmp)) { + tmp++; + continue; + } + if (strncmp(tmp, separator, len) != 0) { + buffer[index++] = *tmp; + tmp++; + continue; + } + tmp += len; + buffer[index] = '\0'; + TrimTail(buffer, index); + index = 0; + + int result = handle(buffer, context); + if (result != 0) { + ret = result; + } + } + if (index > 0) { + buffer[index] = '\0'; + TrimTail(buffer, index); + index = 0; + int result = handle(buffer, context); + if (result != 0) { + ret = result; + } + } + return ret; +} + +char *GetLastStr(const char *str, const char *dst) +{ + char *end = (char *)str + strlen(str); + size_t len = strlen(dst); + while (end != str) { + if (isspace(*end)) { // clear space + *end = '\0'; + end--; + continue; + } + if (strncmp(end, dst, len) == 0) { + return end; + } + end--; + } + return NULL; +} + +static char *ReadFile(const char *fileName) +{ + char *buffer = NULL; + FILE *fd = NULL; + do { + struct stat fileStat; + if (stat(fileName, &fileStat) != 0 || + fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) { + return NULL; + } + APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s size %{public}u", fileName, (uint32_t)fileStat.st_size); + fd = fopen(fileName, "r"); + APPSPAWN_CHECK(fd != NULL, break, "Failed to open file %{public}s", fileName); + + buffer = (char*)malloc((size_t)(fileStat.st_size + 1)); + APPSPAWN_CHECK(buffer != NULL, break, "Failed to alloc mem %{public}s", fileName); + + int ret = fread(buffer, fileStat.st_size, 1, fd); + APPSPAWN_CHECK(ret == 1, break, "Failed to read %{public}s to buffer", fileName); + buffer[fileStat.st_size] = '\0'; + (void)fclose(fd); + return buffer; + } while (0); + + if (fd != NULL) { + (void)fclose(fd); + fd = NULL; + } + if (buffer != NULL) { + free(buffer); + } + return NULL; +} + +cJSON *GetJsonObjFromFile(const char *jsonPath) +{ + APPSPAWN_CHECK_ONLY_EXPER(jsonPath != NULL && *jsonPath != '\0', NULL); + char *buffer = ReadFile(jsonPath); + APPSPAWN_CHECK_ONLY_EXPER(buffer != NULL, NULL); + return cJSON_Parse(buffer); +} + +int ParseJsonConfig(const char *basePath, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context) +{ + // load sandbox config + char path[PATH_MAX] = {}; + CfgFiles *files = GetCfgFiles(basePath); + if (files == NULL) { + return APPSPAWN_SANDBOX_NONE; + } + int ret = 0; + for (int i = 0; i < MAX_CFG_POLICY_DIRS_CNT; ++i) { + if (files->paths[i] == NULL) { + continue; + } + int len = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", files->paths[i], fileName); + APPSPAWN_CHECK(len > 0 && (size_t)len < sizeof(path), ret = APPSPAWN_SANDBOX_INVALID; + continue, "Failed to format sandbox config file name %{public}s %{public}s", files->paths[i], fileName); + cJSON *root = GetJsonObjFromFile(path); + APPSPAWN_CHECK(root != NULL, ret = APPSPAWN_SANDBOX_INVALID; + continue, "Failed to load app data sandbox config %{public}s", path); + int rc = parseConfig(root, context); + if (rc != 0) { + ret = rc; + } + cJSON_Delete(root); + } + FreeCfgFiles(files); + return ret; +} + +static FILE *g_dumpToStream = NULL; +void SetDumpToStream(FILE *stream) +{ + g_dumpToStream = stream; +} diff --git a/util/src/env_utils.cpp b/util/src/env_utils.cpp index 00999d15..9250ef90 100644 --- a/util/src/env_utils.cpp +++ b/util/src/env_utils.cpp @@ -20,7 +20,7 @@ const std::string APPENVLIST_TYPE = "|AppEnv|"; -int32_t SetEnvInfo(struct AppSpawnContent_ *content, AppSpawnClient *client) +int32_t SetEnvInfo(struct AppSpawnContent *content, AppSpawnClient *client) { int ret = 0; OHOS::AppSpawn::ClientSocket::AppProperty *appProperty = &reinterpret_cast(client)->property; diff --git a/util/src/json_utils.cpp b/util/src/json_utils.cpp index 7c972ee7..45c2afef 100644 --- a/util/src/json_utils.cpp +++ b/util/src/json_utils.cpp @@ -13,13 +13,16 @@ * limitations under the License. */ -#include "json_utils.h" -#include "appspawn_server.h" - #include #include #include +#include "appspawn_server.h" +#include "cJSON.h" +#include "config_policy_utils.h" +#include "json_utils.h" +#include "appspawn_utils.h" + using namespace std; using namespace OHOS; @@ -55,4 +58,55 @@ bool JsonUtils::GetStringFromJson(const nlohmann::json &json, const std::string } } } // namespace AppSpawn -} // namespace OHOS \ No newline at end of file +} // namespace OHOS + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +cJSON *GetJsonObjFromFile(const char *jsonPath) +{ + std::ifstream jsonFileStream; + jsonFileStream.open(jsonPath, std::ios::in); + APPSPAWN_CHECK_ONLY_EXPER(jsonFileStream.is_open(), return nullptr); + std::ostringstream buf; + char ch; + while (buf && jsonFileStream.get(ch)) { + buf.put(ch); + } + jsonFileStream.close(); + return cJSON_Parse(buf.str().c_str()); +} + +int ParseJsonConfig(const char *basePath, const char *fileName, ParseConfig parseConfig, ParseJsonContext *context) +{ + // load sandbox config + CfgFiles *files = GetCfgFiles(basePath); + if (files == nullptr) { + return APPSPAWN_SANDBOX_NONE; + } + int ret = 0; + for (int i = 0; i < MAX_CFG_POLICY_DIRS_CNT; ++i) { + if (files->paths[i] == nullptr) { + continue; + } + std::string path = files->paths[i]; + path += fileName; + APPSPAWN_LOGI("LoadAppSandboxConfig %{public}s", path.c_str()); + + cJSON *root = GetJsonObjFromFile(path.c_str()); + APPSPAWN_CHECK(root != nullptr, ret = APPSPAWN_SANDBOX_INVALID; + continue, "Failed to load app data sandbox config %{public}s", path.c_str()); + int rc = parseConfig(root, context); + if (rc != 0) { + ret = rc; + } + cJSON_Delete(root); + } + FreeCfgFiles(files); + return ret; +} + +#ifdef __cplusplus +} +#endif // __cplusplus