Xwadd new msg to old property

Signed-off-by: zhongning5 <zhongning5@huawei.com>
This commit is contained in:
zhongning5 2024-04-01 19:30:15 +08:00
parent a9b2f799eb
commit 49dc924cc1
49 changed files with 4177 additions and 1237 deletions

View File

@ -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}"

View File

@ -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<AppSpawnClientExt *>(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;

View File

@ -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);

View File

@ -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<AppSpawnClientExt *>(client);

View File

@ -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"

View File

@ -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/",

View File

@ -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;

View File

@ -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)

View File

@ -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

View File

@ -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",

View File

@ -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;
}

View File

@ -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);

View File

@ -31,6 +31,9 @@
AppSpawnReqMsgSetFlags;
AppSpawnReqMsgAddStringInfo;
AppSpawnTerminateMsgCreate;
GetPermissionIndex;
GetMaxPermissionIndex;
GetPermissionByIndex;
local:
*;
};

View File

@ -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

View File

@ -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 {

View File

@ -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 <fstream>
#include <sstream>
#include <vector>
#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 <pthread.h>
#include <stdlib.h>
#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();
}

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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

View File

@ -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);

View File

@ -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;
}

View File

@ -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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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

View File

@ -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",
]

409
standard/appspawn_msgmgr.c Executable file
View File

@ -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 <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <unistd.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_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;
}

View File

@ -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);

View File

@ -16,7 +16,6 @@
#include "appspawn_service.h"
#include "appspawn_adapter.h"
#include "appspawn_server.h"
#include "appspawn_msg.h"
#include <fcntl.h>
#include <stdlib.h>
@ -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];

View File

@ -18,7 +18,9 @@
#include <unistd.h>
#include <stdbool.h>
#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

View File

@ -15,7 +15,6 @@
#include <signal.h>
#include <stdbool.h>
#include "appspawn_adapter.h"
#include "appspawn_msg.h"
#include "appspawn_server.h"
#include "appspawn_service.h"
#include "securec.h"

View File

@ -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

View File

@ -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" ]
}
}

View File

@ -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 <gtest/gtest.h>
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<const uint8_t *>(&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<AppFlagsIndex>(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<const uint8_t *>(&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<char *> 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<const uint8_t *>(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<char *> 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<const uint8_t *>(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<char> 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<char *> 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<const uint8_t *>(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<char> buf;
char ch;
while (jsonFileStream.get(ch)) {
buf.insert(buf.end(), ch);
}
jsonFileStream.close();
request.extraInfo.totalLength = buf.size();
std::vector<char *> 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<const uint8_t *>(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<const uint8_t *>(&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<const uint8_t *>(&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<const uint8_t *>(&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<const uint8_t *>(&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<const uint8_t *>(&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
} // namespace OHOS

858
test/moduletest/appspawn_module_test.cpp Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -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 <sstream>
#include <fstream>
#include <fcntl.h>
#include <unistd.h>
#include <cstdio>
#include <vector>
#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<ClientSocket>(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<uint8_t *>(buf);
const int maxLen = 5 * 1024;
while (curr < len) {
if ((len - curr) > maxLen) {
real = maxLen;
} else {
real = len - curr;
}
if (clientSocket_->WriteSocketMessage(static_cast<const void *>(buffer + curr), real) != real) {
return -1;
}
curr += real;
}
return 0;
}
int ClientRecvMsg(pid_t &pid)
{
pid = -1;
std::vector<uint8_t> data(sizeof(pid_t)); // 4 pid size
if (clientSocket_->ReadSocketMessage(data.data(), data.size()) == sizeof(pid_t)) {
int ret = *(reinterpret_cast<int *>(data.data()));
if (ret < 0) {
return ret;
}
pid = static_cast<pid_t>(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> clientSocket_ {};
};
} // namespace AppSpawn
} // namespace OHOS
#endif // APPSPAWN_CLIENT_TEST_H

View File

@ -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 <signal.h>
#include <unistd.h>
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<const uint8_t *>(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);
}

View File

@ -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 <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <string>
#include <termios.h>
#include <unistd.h>
#include <sys/stat.h>
#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 <options> \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<uint8_t *>(&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<AppSpawnMsgType>(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<AppSpawnMsgType>(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<AppFlagsIndex>(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<ThreadContext *>(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<std::string> 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<char *> options;
for (const auto &arg : g_args) {
if (!arg.empty()) {
options.push_back(const_cast<char *>(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

View File

@ -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 <cstdint>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <vector>
#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<std::string> 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<AppSpawnTestCommander *>(reinterpret_cast<const AppSpawnTestCommander *>(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

View File

@ -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 <cerrno>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <string>
#include <termios.h>
#include <unistd.h>
#include <sys/stat.h>
#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;
}

View File

@ -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}"
}

View File

@ -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 <errno.h>
#include <pthread.h>
#include <stdatomic.h>
#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;
}

View File

@ -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 <stdint.h>
#include <stdlib.h>
#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

View File

@ -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",

View File

@ -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",
]
}

View File

@ -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 <gtest/gtest.h>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <vector>
#include <iostream>
#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<char *>(testMsg);
AppSpawnReqMsgHandle handle = reinterpret_cast<AppSpawnReqMsgHandle>(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<uint8_t *>(const_cast<char *>(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<uint8_t *>(const_cast<char *>(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<uint8_t *>(const_cast<char *>(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);
}
}

View File

@ -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));

View File

@ -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);

View File

@ -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",
]

121
util/include/appspawn_utils.h Executable file
View File

@ -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 <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#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

View File

@ -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
}

259
util/src/appspawn_utils.c Normal file
View File

@ -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 <ctype.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#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;
}

View File

@ -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<AppSpawnClientExt *>(client)->property;

View File

@ -13,13 +13,16 @@
* limitations under the License.
*/
#include "json_utils.h"
#include "appspawn_server.h"
#include <cerrno>
#include <sstream>
#include <fstream>
#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
} // 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