mirror of
https://gitee.com/openharmony/startup_appspawn
synced 2024-11-27 01:00:38 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
a89a0f0dac
115
BUILD.gn
115
BUILD.gn
@ -35,6 +35,7 @@ config("appspawn_config") {
|
||||
"//foundation/communication/ipc/interfaces/innerkits/ipc_core/include",
|
||||
"//foundation/arkui/napi",
|
||||
"//third_party/libuv/include",
|
||||
"//third_party/selinux/libselinux/include/",
|
||||
]
|
||||
|
||||
if (build_selinux) {
|
||||
@ -43,15 +44,30 @@ config("appspawn_config") {
|
||||
}
|
||||
|
||||
ohos_executable("appspawn") {
|
||||
defines = []
|
||||
if (target_cpu == "arm64") {
|
||||
defines += [ "webview_arm64" ]
|
||||
}
|
||||
if (target_cpu == "x86_64") {
|
||||
defines += [ "webview_x86_64" ]
|
||||
}
|
||||
sources = [
|
||||
"${appspawn_path}/adapter/appspawn_ace.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_nweb.cpp",
|
||||
"${appspawn_path}/adapter/nwebspawn_lancher.cpp",
|
||||
"${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp",
|
||||
"${appspawn_path}/standard/main.c",
|
||||
"${appspawn_path}/util/src/json_utils.cpp",
|
||||
"${appspawn_path}/util/src/sandbox_utils.cpp",
|
||||
]
|
||||
if (asan_detector || is_asan) {
|
||||
defines = [ "ASAN_DETECTOR" ]
|
||||
defines += [ "ASAN_DETECTOR" ]
|
||||
}
|
||||
configs = [ ":appspawn_config" ]
|
||||
deps = [ "${appspawn_path}:appspawn_server" ]
|
||||
deps = [
|
||||
"${appspawn_path}:appspawn_server",
|
||||
"//third_party/selinux:libselinux",
|
||||
]
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"ability_runtime:app_manager",
|
||||
@ -65,7 +81,9 @@ ohos_executable("appspawn") {
|
||||
"init:libbegetutil",
|
||||
"resource_management:global_resmgr",
|
||||
]
|
||||
|
||||
if (build_selinux) {
|
||||
external_deps += [ "selinux_adapter:libhap_restorecon" ]
|
||||
}
|
||||
install_enable = true
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
@ -95,6 +113,7 @@ ohos_shared_library("appspawn_helper") {
|
||||
ohos_static_library("appspawn_server") {
|
||||
sources = [
|
||||
"${appspawn_path}/adapter/appspawn_adapter.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_nweb.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_sandbox.cpp",
|
||||
"${appspawn_path}/common/appspawn_server.c",
|
||||
"${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp",
|
||||
@ -116,15 +135,16 @@ ohos_static_library("appspawn_server") {
|
||||
ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ]
|
||||
deps = [
|
||||
":asan.options",
|
||||
"//foundation/communication/netmanager_base/services/netmanagernative/netsys_client:netsys_client",
|
||||
"//third_party/selinux:libselinux",
|
||||
]
|
||||
external_deps = [
|
||||
"access_token:libtoken_setproc",
|
||||
"access_token:libtokenid_sdk",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
"init:libbegetutil",
|
||||
"netmanager_base:netsys_client",
|
||||
]
|
||||
|
||||
if (!defined(global_parts_info) ||
|
||||
@ -159,86 +179,6 @@ ohos_prebuilt_etc("appspawn.rc") {
|
||||
part_name = "${part_name}"
|
||||
}
|
||||
|
||||
ohos_static_library("nwebspawn_server") {
|
||||
sources = [
|
||||
"${appspawn_path}/adapter/appspawn_adapter.cpp",
|
||||
"${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_process.c",
|
||||
"${appspawn_path}/standard/appspawn_service.c",
|
||||
"${appspawn_path}/util/src/json_utils.cpp",
|
||||
"${appspawn_path}/util/src/sandbox_utils.cpp",
|
||||
]
|
||||
defines = [
|
||||
"GRAPHIC_PERMISSION_CHECK",
|
||||
"INIT_AGENT",
|
||||
"NWEB_SPAWN",
|
||||
"APPSPAWN_CHECK_GID_UID",
|
||||
"APPSPAWN_LABEL=\"NWEBSPAWN\"",
|
||||
]
|
||||
include_dirs = [ "//third_party/selinux/libselinux/include/" ]
|
||||
configs = [ ":appspawn_config" ]
|
||||
ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ]
|
||||
deps = [
|
||||
"//foundation/communication/netmanager_base/services/netmanagernative/netsys_client:netsys_client",
|
||||
"//third_party/selinux:libselinux",
|
||||
]
|
||||
external_deps = [
|
||||
"access_token:libtoken_setproc",
|
||||
"access_token:libtokenid_sdk",
|
||||
"c_utils:utils",
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
"init:libbegetutil",
|
||||
]
|
||||
if (build_selinux) {
|
||||
external_deps += [ "selinux_adapter:libhap_restorecon" ]
|
||||
}
|
||||
|
||||
cflags = []
|
||||
if (build_seccomp) {
|
||||
cflags += [ "-DWITH_SECCOMP" ]
|
||||
external_deps += [ "init:seccomp" ]
|
||||
}
|
||||
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
}
|
||||
|
||||
ohos_executable("nwebspawn") {
|
||||
defines = [
|
||||
"NWEB_SPAWN",
|
||||
"APPSPAWN_LABEL=\"NWEBSPAWN\"",
|
||||
]
|
||||
if (target_cpu == "arm64") {
|
||||
defines += [ "webview_arm64" ]
|
||||
}
|
||||
if (target_cpu == "x86_64") {
|
||||
defines += [ "webview_x86_64" ]
|
||||
}
|
||||
sources = [
|
||||
"${appspawn_path}/adapter/appspawn_nweb.cpp",
|
||||
"${appspawn_path}/interfaces/innerkits/src/appspawn_mount_permission.cpp",
|
||||
"${appspawn_path}/standard/main.c",
|
||||
"${appspawn_path}/util/src/json_utils.cpp",
|
||||
"${appspawn_path}/util/src/sandbox_utils.cpp",
|
||||
]
|
||||
configs = [ ":appspawn_config" ]
|
||||
deps = [ "${appspawn_path}:nwebspawn_server" ]
|
||||
external_deps = [
|
||||
"config_policy:configpolicy_util",
|
||||
"hilog:libhilog",
|
||||
]
|
||||
if (build_selinux) {
|
||||
external_deps += [ "selinux_adapter:libhap_restorecon" ]
|
||||
}
|
||||
|
||||
install_enable = true
|
||||
subsystem_name = "${subsystem_name}"
|
||||
part_name = "${part_name}"
|
||||
}
|
||||
|
||||
ohos_prebuilt_etc("nwebspawn.rc") {
|
||||
source = "nwebspawn.cfg"
|
||||
relative_install_dir = "init"
|
||||
@ -249,9 +189,6 @@ ohos_prebuilt_etc("nwebspawn.rc") {
|
||||
group("nweb") {
|
||||
deps = []
|
||||
if (appspawn_support_nweb) {
|
||||
deps += [
|
||||
":nwebspawn",
|
||||
":nwebspawn.rc",
|
||||
]
|
||||
deps += [ ":nwebspawn.rc" ]
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ static void GetPreloadModules(const std::string &configName, std::set<std::strin
|
||||
|
||||
static void PreloadModule(void)
|
||||
{
|
||||
#ifndef APPSPAWN_TEST
|
||||
OHOS::AbilityRuntime::Runtime::Options options;
|
||||
options.lang = OHOS::AbilityRuntime::Runtime::Language::JS;
|
||||
options.loadAce = true;
|
||||
@ -71,6 +72,7 @@ static void PreloadModule(void)
|
||||
APPSPAWN_LOGE("LoadExtendLib: Failed to create runtime");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
std::set<std::string> modules = {};
|
||||
CfgFiles *files = GetCfgFiles("etc/appspawn");
|
||||
if (files == nullptr) {
|
||||
@ -89,10 +91,14 @@ static void PreloadModule(void)
|
||||
FreeCfgFiles(files);
|
||||
for (std::string moduleName : modules) {
|
||||
APPSPAWN_LOGI("moduleName %{public}s", moduleName.c_str());
|
||||
#ifndef APPSPAWN_TEST
|
||||
runtime->PreloadSystemModule(moduleName);
|
||||
#endif
|
||||
}
|
||||
#ifndef APPSPAWN_TEST
|
||||
// Save preloaded runtime
|
||||
OHOS::AbilityRuntime::Runtime::SavePreloaded(std::move(runtime));
|
||||
#endif
|
||||
}
|
||||
|
||||
void LoadExtendLib(AppSpawnContent *content)
|
||||
|
@ -17,9 +17,7 @@
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
#include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
#include "appspawn_service.h"
|
||||
#ifdef WITH_SELINUX
|
||||
@ -33,28 +31,28 @@
|
||||
const char* RENDERER_NAME = "renderer";
|
||||
#endif
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
#include "tokenid_kit.h"
|
||||
#include "access_token.h"
|
||||
|
||||
#define NWEBSPAWN_SERVER_NAME "nwebspawn"
|
||||
using namespace OHOS::Security::AccessToken;
|
||||
#endif
|
||||
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
#if NWEB_SPAWN
|
||||
TokenIdKit tokenIdKit;
|
||||
uint64_t tokenId = tokenIdKit.GetRenderTokenID(appProperty->property.accessTokenIdEx);
|
||||
if (tokenId == static_cast<uint64_t>(INVALID_TOKENID)) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::Failed to get render token id, renderTokenId =%{public}llu",
|
||||
static_cast<unsigned long long>(tokenId));
|
||||
return -1;
|
||||
int32_t ret = 0;
|
||||
uint64_t tokenId = 0;
|
||||
if (content->isNweb) {
|
||||
TokenIdKit tokenIdKit;
|
||||
tokenId = tokenIdKit.GetRenderTokenID(appProperty->property.accessTokenIdEx);
|
||||
if (tokenId == static_cast<uint64_t>(INVALID_TOKENID)) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::Failed to get render token id, renderTokenId =%{public}llu",
|
||||
static_cast<unsigned long long>(tokenId));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
tokenId = appProperty->property.accessTokenIdEx;
|
||||
}
|
||||
#else
|
||||
uint64_t tokenId = appProperty->property.accessTokenIdEx;
|
||||
#endif
|
||||
int32_t ret = SetSelfTokenID(tokenId);
|
||||
ret = SetSelfTokenID(tokenId);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::set access token id failed, ret = %{public}d", ret);
|
||||
return -1;
|
||||
@ -65,45 +63,48 @@ int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
int SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SELINUX
|
||||
#ifdef NWEB_SPAWN
|
||||
setcon("u:r:isolated_render:s0");
|
||||
#else
|
||||
UNUSED(content);
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
HapContext hapContext;
|
||||
HapDomainInfo hapDomainInfo;
|
||||
hapDomainInfo.apl = appProperty->property.apl;
|
||||
hapDomainInfo.packageName = appProperty->property.processName;
|
||||
hapDomainInfo.hapFlags = appProperty->property.hapFlags;
|
||||
if ((appProperty->property.flags & APP_DEBUGGABLE) != 0) {
|
||||
hapDomainInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE;
|
||||
}
|
||||
int32_t ret = hapContext.HapDomainSetcontext(hapDomainInfo);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::Failed to hap domain set context, errno = %{public}d %{public}s",
|
||||
errno, appProperty->property.apl);
|
||||
if (content->isNweb) {
|
||||
setcon("u:r:isolated_render:s0");
|
||||
} else {
|
||||
APPSPAWN_LOGV("AppSpawnServer::Success to hap domain set context, ret = %{public}d", ret);
|
||||
UNUSED(content);
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
HapContext hapContext;
|
||||
HapDomainInfo hapDomainInfo;
|
||||
hapDomainInfo.apl = appProperty->property.apl;
|
||||
hapDomainInfo.packageName = appProperty->property.processName;
|
||||
hapDomainInfo.hapFlags = appProperty->property.hapFlags;
|
||||
if ((appProperty->property.flags & APP_DEBUGGABLE) != 0) {
|
||||
hapDomainInfo.hapFlags |= SELINUX_HAP_DEBUGGABLE;
|
||||
}
|
||||
int32_t ret = hapContext.HapDomainSetcontext(hapDomainInfo);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::Failed to hap domain set context, errno = %{public}d %{public}s",
|
||||
errno, appProperty->property.apl);
|
||||
return -1;
|
||||
} else {
|
||||
APPSPAWN_LOGV("AppSpawnServer::Success to hap domain set context, ret = %{public}d", ret);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetUidGidFilter(struct AppSpawnContent_ *content)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
#ifdef NWEB_SPAWN
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
APPSPAWN_LOGE("Failed to set no new privs");
|
||||
bool ret = false;
|
||||
if (content->isNweb) {
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
APPSPAWN_LOGE("Failed to set no new privs");
|
||||
}
|
||||
ret = SetSeccompPolicyWithName(INDIVIDUAL, NWEBSPAWN_NAME);
|
||||
} else {
|
||||
ret = SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME);
|
||||
}
|
||||
|
||||
if (!SetSeccompPolicyWithName(INDIVIDUAL, NWEBSPAWN_NAME)) {
|
||||
#else
|
||||
if (!SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME)) {
|
||||
#endif
|
||||
if (!ret) {
|
||||
APPSPAWN_LOGE("Failed to set APPSPAWN seccomp filter and exit");
|
||||
#ifndef APPSPAWN_TEST
|
||||
_exit(0x7f);
|
||||
@ -117,13 +118,12 @@ void SetUidGidFilter(struct AppSpawnContent_ *content)
|
||||
int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
#ifdef NWEB_SPAWN
|
||||
const char *appName = RENDERER_NAME;
|
||||
SeccompFilterType type = INDIVIDUAL;
|
||||
#else
|
||||
const char *appName = APP_NAME;
|
||||
SeccompFilterType type = APP;
|
||||
#endif
|
||||
if (content->isNweb) {
|
||||
appName = RENDERER_NAME;
|
||||
type = INDIVIDUAL;
|
||||
}
|
||||
if (!SetSeccompPolicyWithName(type, appName)) {
|
||||
APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit", appName);
|
||||
#ifndef APPSPAWN_TEST
|
||||
|
@ -26,9 +26,11 @@ extern "C" {
|
||||
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void SetSelinuxCon(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(void);
|
||||
void SetUidGidFilter(struct AppSpawnContent_ *content);
|
||||
int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include "appspawn_service.h"
|
||||
#include "appspawn_adapter.h"
|
||||
|
||||
|
||||
struct RenderProcessNode {
|
||||
RenderProcessNode(time_t now, int exit):recordTime_(now), exitStatus_(exit) {}
|
||||
time_t recordTime_;
|
||||
@ -42,129 +44,63 @@ struct RenderProcessNode {
|
||||
namespace {
|
||||
constexpr int32_t RENDER_PROCESS_MAX_NUM = 16;
|
||||
std::map<int32_t, RenderProcessNode> g_renderProcessMap;
|
||||
void *g_nwebHandle = nullptr;
|
||||
std::mutex g_mutex;
|
||||
|
||||
#if defined(webview_arm64)
|
||||
const std::string RELATIVE_PATH_FOR_HAP = "NWeb.hap!/libs/arm64-v8a";
|
||||
const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm64";
|
||||
#elif defined(webview_x86_64)
|
||||
const std::string RELATIVE_PATH_FOR_HAP = "NWeb.hap!/libs/x86_64";
|
||||
const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/x86_64";
|
||||
#else
|
||||
const std::string RELATIVE_PATH_FOR_HAP = "NWeb.hap!/libs/armeabi-v7a";
|
||||
const std::string NWEB_HAP_LIB_PATH = "/data/storage/el1/bundle/nweb/libs/arm";
|
||||
#endif
|
||||
const std::string NWEB_HAP_PATH = "/system/app/com.ohos.nweb/";
|
||||
const std::string NWEB_HAP_PATH_1 = "/system/app/NWeb/";
|
||||
}
|
||||
|
||||
std::string GetNWebHapLibsPath()
|
||||
void LoadExtendLibNweb(AppSpawnContent *content)
|
||||
{
|
||||
std::string libPath;
|
||||
if (access(NWEB_HAP_PATH.c_str(), F_OK) == 0) {
|
||||
libPath = NWEB_HAP_PATH + RELATIVE_PATH_FOR_HAP;
|
||||
APPSPAWN_LOGI("get fix path, %{public}s", libPath.c_str());
|
||||
return libPath;
|
||||
}
|
||||
if (access(NWEB_HAP_PATH_1.c_str(), F_OK) == 0) {
|
||||
libPath = NWEB_HAP_PATH_1 + RELATIVE_PATH_FOR_HAP;
|
||||
APPSPAWN_LOGI("get fix path, %{public}s", libPath.c_str());
|
||||
return libPath;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
#ifdef __MUSL__
|
||||
void *LoadWithRelroFile(const std::string &lib, const std::string &nsName,
|
||||
const std::string &nsPath)
|
||||
void RunChildProcessorNweb(AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef webview_arm64
|
||||
const std::string nwebRelroPath =
|
||||
"/data/misc/shared_relro/libwebviewchromium64.relro";
|
||||
size_t nwebReservedSize = 1 * 1024 * 1024 * 1024;
|
||||
#else
|
||||
const std::string nwebRelroPath =
|
||||
"/data/misc/shared_relro/libwebviewchromium32.relro";
|
||||
size_t nwebReservedSize = 130 * 1024 * 1024;
|
||||
#endif
|
||||
if (unlink(nwebRelroPath.c_str()) != 0 && errno != ENOENT) {
|
||||
APPSPAWN_LOGI("LoadWithRelroFile unlink failed");
|
||||
}
|
||||
int relroFd =
|
||||
open(nwebRelroPath.c_str(), O_RDWR | O_TRUNC | O_CLOEXEC | O_CREAT,
|
||||
S_IRUSR | S_IRGRP | S_IROTH);
|
||||
if (relroFd < 0) {
|
||||
int tmpNo = errno;
|
||||
APPSPAWN_LOGE("LoadWithRelroFile open failed, error=[%{public}s]", strerror(tmpNo));
|
||||
return nullptr;
|
||||
}
|
||||
void *nwebReservedAddress = mmap(nullptr, nwebReservedSize, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (nwebReservedAddress == MAP_FAILED) {
|
||||
close(relroFd);
|
||||
int tmpNo = errno;
|
||||
APPSPAWN_LOGE("LoadWithRelroFile mmap failed, error=[%{public}s]", strerror(tmpNo));
|
||||
return nullptr;
|
||||
}
|
||||
Dl_namespace dlns;
|
||||
dlns_init(&dlns, nsName.c_str());
|
||||
dlns_create(&dlns, nsPath.c_str());
|
||||
dl_extinfo extinfo = {
|
||||
.flag = DL_EXT_WRITE_RELRO | DL_EXT_RESERVED_ADDRESS_RECURSIVE |
|
||||
DL_EXT_RESERVED_ADDRESS,
|
||||
.relro_fd = relroFd,
|
||||
.reserved_addr = nwebReservedAddress,
|
||||
.reserved_size = nwebReservedSize,
|
||||
};
|
||||
void *result =
|
||||
dlopen_ns_ext(&dlns, lib.c_str(), RTLD_NOW | RTLD_GLOBAL, &extinfo);
|
||||
close(relroFd);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
APPSPAWN_LOGI("RunChildProcessorNweb");
|
||||
void *webEngineHandle = nullptr;
|
||||
void *nwebRenderHandle = nullptr;
|
||||
|
||||
void LoadExtendLib(AppSpawnContent *content)
|
||||
{
|
||||
const std::string loadLibDir = GetNWebHapLibsPath();
|
||||
#ifdef __MUSL__
|
||||
Dl_namespace dlns;
|
||||
dlns_init(&dlns, "nweb_ns");
|
||||
dlns_create(&dlns, loadLibDir.c_str());
|
||||
#if defined(webview_x86_64)
|
||||
void *handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
dlns_create(&dlns, NWEB_HAP_LIB_PATH.c_str());
|
||||
|
||||
// preload libweb_engine
|
||||
webEngineHandle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
// load libnweb_render
|
||||
nwebRenderHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
#else
|
||||
void *handle = LoadWithRelroFile("libweb_engine.so", "nweb_ns", loadLibDir);
|
||||
if (handle == nullptr) {
|
||||
APPSPAWN_LOGE("dlopen_ns_ext failed, fallback to dlopen_ns");
|
||||
handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
}
|
||||
// preload libweb_engine
|
||||
const std::string engineLibDir = NWEB_HAP_LIB_PATH + "/libweb_engine.so";
|
||||
webEngineHandle = dlopen(engineLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
// load libnweb_render
|
||||
const std::string renderLibDir = NWEB_HAP_LIB_PATH + "/libnweb_render.so";
|
||||
nwebRenderHandle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
#endif
|
||||
#else
|
||||
const std::string engineLibDir = loadLibDir + "/libweb_engine.so";
|
||||
void *handle = dlopen(engineLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
#endif
|
||||
if (handle == nullptr) {
|
||||
if (webEngineHandle == nullptr) {
|
||||
APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, [%{public}s]", dlerror());
|
||||
} else {
|
||||
APPSPAWN_LOGI("Success to dlopen libweb_engine.so");
|
||||
}
|
||||
|
||||
#ifdef __MUSL__
|
||||
g_nwebHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
#else
|
||||
const std::string renderLibDir = loadLibDir + "/libnweb_render.so";
|
||||
g_nwebHandle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
#endif
|
||||
if (g_nwebHandle == nullptr) {
|
||||
if (nwebRenderHandle == nullptr) {
|
||||
APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, [%{public}s]", dlerror());
|
||||
return;
|
||||
} else {
|
||||
APPSPAWN_LOGI("Success to dlopen libnweb_render.so");
|
||||
}
|
||||
}
|
||||
|
||||
void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
using FuncType = void (*)(const char *cmd);
|
||||
|
||||
FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(g_nwebHandle, "NWebRenderMain"));
|
||||
FuncType funcNWebRenderMain = reinterpret_cast<FuncType>(dlsym(nwebRenderHandle, "NWebRenderMain"));
|
||||
if (funcNWebRenderMain == nullptr) {
|
||||
APPSPAWN_LOGI("webviewspawn dlsym ERROR=%{public}s", dlerror());
|
||||
return;
|
||||
|
@ -68,7 +68,13 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *
|
||||
if ((client->cloneFlags & CLONE_NEWNS) != CLONE_NEWNS) {
|
||||
return 0;
|
||||
}
|
||||
int ret = SandboxUtils::SetAppSandboxProperty(client);
|
||||
int ret = 0;
|
||||
if (content->isNweb) {
|
||||
ret = SandboxUtils::SetAppSandboxPropertyNweb(client);
|
||||
} else {
|
||||
ret = SandboxUtils::SetAppSandboxProperty(client);
|
||||
}
|
||||
|
||||
// free HspList
|
||||
if (clientExt->property.hspList.data != nullptr) {
|
||||
free(clientExt->property.hspList.data);
|
||||
|
53
adapter/nwebspawn_lancher.cpp
Normal file
53
adapter/nwebspawn_lancher.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2021-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 "nwebspawn_lancher.h"
|
||||
#include "appspawn_server.h"
|
||||
|
||||
#define NWEB_UID 3081
|
||||
#define NWEB_GID 3081
|
||||
#define CAP_NUM 2
|
||||
#define BITLEN32 32
|
||||
|
||||
pid_t NwebSpawnLanch()
|
||||
{
|
||||
pid_t ret = fork();
|
||||
if (ret == 0) {
|
||||
setcon("u:r:nwebspawn:s0");
|
||||
struct __user_cap_header_struct capHeader;
|
||||
capHeader.version = _LINUX_CAPABILITY_VERSION_3;
|
||||
capHeader.pid = 0;
|
||||
const uint64_t inheriTable = 0x2000c0;
|
||||
const uint64_t permitted = 0x2000c0;
|
||||
const uint64_t effective = 0x2000c0;
|
||||
struct __user_cap_data_struct capData[CAP_NUM] = {};
|
||||
for (int j = 0; j < CAP_NUM; ++j) {
|
||||
capData[0].inheritable = (__u32)(inheriTable);
|
||||
capData[1].inheritable = (__u32)(inheriTable >> BITLEN32);
|
||||
capData[0].permitted = (__u32)(permitted);
|
||||
capData[1].permitted = (__u32)(permitted >> BITLEN32);
|
||||
capData[0].effective = (__u32)(effective);
|
||||
capData[1].effective = (__u32)(effective >> BITLEN32);
|
||||
}
|
||||
capset(&capHeader, capData);
|
||||
|
||||
for (int i = 0; i <= CAP_LAST_CAP; ++i) {
|
||||
prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, i, 0, 0);
|
||||
}
|
||||
setuid(NWEB_UID);
|
||||
setgid(NWEB_GID);
|
||||
APPSPAWN_LOGI("nwebspawn fork success");
|
||||
}
|
||||
return ret;
|
||||
}
|
34
adapter/nwebspawn_lancher.h
Normal file
34
adapter/nwebspawn_lancher.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021-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 NWEBSPAWNLANCHER_CPP
|
||||
#define NWEBSPAWNLANCHER_CPP
|
||||
#include "selinux/selinux.h"
|
||||
#include <sys/capability.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <unistd.h>
|
||||
#include <sched.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
pid_t NwebSpawnLanch();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -73,6 +73,11 @@
|
||||
"sandbox-path" : "/vendor/lib",
|
||||
"sandbox-flags" : [ "bind", "rec" ],
|
||||
"check-action-status": "false"
|
||||
}, {
|
||||
"src-path" : "/vendor/etc/vulkan",
|
||||
"sandbox-path" : "/vendor/etc/vulkan",
|
||||
"sandbox-flags" : [ "bind", "rec" ],
|
||||
"check-action-status": "false"
|
||||
}, {
|
||||
"src-path" : "/data/app/el1/bundle/public/<PackageName>",
|
||||
"sandbox-path" : "/data/storage/el1/bundle",
|
||||
@ -335,6 +340,18 @@
|
||||
],
|
||||
"symbol-links" : []
|
||||
}],
|
||||
"com.ohos.amsdialog" : [{
|
||||
"sandbox-switch": "ON",
|
||||
"sandbox-root" : "/mnt/sandbox/<PackageName>",
|
||||
"mount-paths" : [{
|
||||
"src-path" : "/data/app/el1/bundle/public/",
|
||||
"sandbox-path" : "/data/bundles/",
|
||||
"sandbox-flags" : [ "bind", "rec" ],
|
||||
"check-action-status": "true"
|
||||
}
|
||||
],
|
||||
"symbol-links" : []
|
||||
}],
|
||||
"ohos.samples.ecg" : [{
|
||||
"sandbox-switch": "ON",
|
||||
"sandbox-root" : "/mnt/sandbox/<PackageName>",
|
||||
@ -366,6 +383,12 @@
|
||||
"sandbox-root" : "/mnt/sandbox/<PackageName>",
|
||||
"sandbox-shared" : "true",
|
||||
"mount-paths" : [{
|
||||
"src-path" : "/mnt/data/<currentUserId>",
|
||||
"sandbox-path" : "/mnt/data",
|
||||
"sandbox-flags" : [ "bind", "rec" ],
|
||||
"mount-shared-flag" : "true",
|
||||
"check-action-status": "true"
|
||||
}, {
|
||||
"src-path" : "/dev/fuse",
|
||||
"sandbox-path" : "/mnt/data/fuse",
|
||||
"sandbox-flags" : [ "MS_NOSUID", "MS_NODEV", "MS_NOEXEC", "MS_NOATIME", "MS_LAZYTIME" ],
|
||||
@ -385,7 +408,7 @@
|
||||
"check-action-status": "true"
|
||||
},
|
||||
{
|
||||
"src-path" : "/mnt/external",
|
||||
"src-path" : "/mnt/data/external",
|
||||
"sandbox-path" : "/mnt/external",
|
||||
"sandbox-flags" : [ "bind", "rec" ],
|
||||
"check-action-status": "true"
|
||||
@ -493,7 +516,7 @@
|
||||
"sandbox-flags": [ "bind", "rec" ]
|
||||
},
|
||||
{
|
||||
"src-path": "/mnt/external",
|
||||
"src-path": "/mnt/data/external",
|
||||
"sandbox-path": "/storage/External",
|
||||
"sandbox-flags": [ "bind", "rec" ]
|
||||
},
|
||||
@ -514,7 +537,7 @@
|
||||
{
|
||||
"sandbox-switch": "ON",
|
||||
"sandbox-root": "/mnt/sandbox/<PackageName>",
|
||||
"gids": [],
|
||||
"gids": [1008],
|
||||
"mount-paths": [
|
||||
{
|
||||
"src-path": "/storage/media/<currentUserId>/local/files/.thumbs/Photo",
|
||||
|
11
appspawn.cfg
11
appspawn.cfg
@ -1,4 +1,12 @@
|
||||
{
|
||||
"jobs" : [{
|
||||
"name" : "service:nwebspawn",
|
||||
"cmds" : [
|
||||
"mkdir /mnt/sandbox",
|
||||
"mkdir /mnt/sandbox/com.ohos.render/ 0711 nwebspawn nwebspawn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services" : [{
|
||||
"name" : "appspawn",
|
||||
"path" : ["/system/bin/appspawn",
|
||||
@ -11,6 +19,9 @@
|
||||
"sandbox" : 0,
|
||||
"start-mode" : "boot",
|
||||
"secon" : "u:r:appspawn:s0",
|
||||
"jobs" : {
|
||||
"on-start" : "service:nwebspawn"
|
||||
},
|
||||
"bootevents" : "bootevent.appspawn.started"
|
||||
}
|
||||
]
|
||||
|
@ -42,7 +42,9 @@
|
||||
"resource_management",
|
||||
"hitrace",
|
||||
"common_event_service",
|
||||
"hisysevent"
|
||||
"hisysevent",
|
||||
"security_component",
|
||||
"netmanager"
|
||||
],
|
||||
"third_party": [
|
||||
"bounds_checking_function",
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "beget_ext.h"
|
||||
#include "hilog/log.h"
|
||||
#include "securec.h"
|
||||
@ -48,6 +48,7 @@ typedef struct AppSpawnClient_ {
|
||||
typedef struct AppSpawnContent_ {
|
||||
char *longProcName;
|
||||
uint32_t longProcNameLen;
|
||||
bool isNweb;
|
||||
|
||||
// system
|
||||
void (*loadExtendLib)(struct AppSpawnContent_ *content);
|
||||
|
@ -23,7 +23,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__MUSL__) || defined(NWEB_SPAWN)
|
||||
#if defined(__MUSL__)
|
||||
#ifndef APPSPAWN_TEST
|
||||
#define SOCKET_DIR "/dev/unix/socket/"
|
||||
#else
|
||||
@ -33,13 +33,12 @@ extern "C" {
|
||||
#define SOCKET_DIR "/dev/socket/"
|
||||
#endif
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
#define APPSPAWN_SOCKET_NAME "NWebSpawn"
|
||||
#define APPSPAWN_SERVER_NAME "nwebspawn"
|
||||
#else
|
||||
|
||||
#define NWEBSPAWN_SOCKET_NAME "NWebSpawn"
|
||||
#define NWEBSPAWN_SERVER_NAME "nwebspawn"
|
||||
#define APPSPAWN_SOCKET_NAME "AppSpawn"
|
||||
#define APPSPAWN_SERVER_NAME "appspawn"
|
||||
#endif
|
||||
|
||||
|
||||
enum AppType {
|
||||
APP_TYPE_DEFAULT = 0, // JavaScript app
|
||||
|
@ -1,18 +1,13 @@
|
||||
{
|
||||
"jobs" : [{
|
||||
"name" : "service:nwebspawn",
|
||||
"cmds" : [
|
||||
"mkdir /mnt/sandbox",
|
||||
"mkdir /mnt/sandbox/com.ohos.render/ 0711 nwebspawn nwebspawn"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services" : [{
|
||||
"name" : "nwebspawn",
|
||||
"path" : ["/system/bin/nwebspawn",
|
||||
"--process-name com.ohos.appspawn.startup --start-flags daemon --type standard ",
|
||||
"--sandbox-switch on --bundle-name com.ohos.appspawn.startup --app-operate-type operate ",
|
||||
"--render-command command --app-launch-type singleton --app-visible true"],
|
||||
"uid" : "nwebspawn",
|
||||
"gid" : ["nwebspawn"],
|
||||
"caps" : ["SYS_ADMIN", "SETGID", "SETUID"],
|
||||
"socket" : [{
|
||||
"name" : "NWebSpawn",
|
||||
"family" : "AF_LOCAL",
|
||||
@ -24,13 +19,8 @@
|
||||
"option" : [
|
||||
]
|
||||
}],
|
||||
"uid" : "nwebspawn",
|
||||
"gid" : ["nwebspawn"],
|
||||
"caps" : ["SYS_ADMIN", "SETGID", "SETUID"],
|
||||
"jobs" : {
|
||||
"on-start" : "service:nwebspawn"
|
||||
},
|
||||
"ondemand" : true,
|
||||
"disabled" : 1,
|
||||
"secon" : "u:r:nwebspawn:s0"
|
||||
}
|
||||
]
|
||||
|
@ -157,7 +157,8 @@ static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *cli
|
||||
// set capabilities
|
||||
isRet = capset(&cap_header, &cap_data[0]) == -1;
|
||||
APPSPAWN_CHECK(!isRet, return -errno, "capset failed: %{public}d", errno);
|
||||
SetSelinuxCon(content, client);
|
||||
isRet = SetSelinuxCon(content, client) == -1;
|
||||
APPSPAWN_CHECK(!isRet, return -EPERM, "Failed to set selinux context");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -669,17 +670,17 @@ void SetContentFunction(AppSpawnContent *content)
|
||||
content->setKeepCapabilities = SetKeepCapabilities;
|
||||
content->setUidGid = SetUidGid;
|
||||
content->setXpmRegion = SetXpmRegion;
|
||||
content->setCapabilities = SetCapabilities;
|
||||
content->setFileDescriptors = SetFileDescriptors;
|
||||
content->setAppSandbox = SetAppSandboxProperty;
|
||||
content->setAppAccessToken = SetAppAccessToken;
|
||||
content->coldStartApp = ColdStartApp;
|
||||
content->setAsanEnabledEnv = SetAsanEnabledEnv;
|
||||
#ifdef ASAN_DETECTOR
|
||||
content->getWrapBundleNameValue = GetWrapBundleNameValue;
|
||||
#endif
|
||||
content->setSeccompFilter = SetSeccompFilter;
|
||||
content->setAppSandbox = SetAppSandboxProperty;
|
||||
content->setCapabilities = SetCapabilities;
|
||||
content->setUidGidFilter = SetUidGidFilter;
|
||||
content->setSeccompFilter = SetSeccompFilter;
|
||||
content->setAppAccessToken = SetAppAccessToken;
|
||||
content->handleInternetPermission = HandleInternetPermission;
|
||||
content->waitForDebugger = WaitForDebugger;
|
||||
}
|
||||
|
@ -93,13 +93,6 @@ APPSPAWN_STATIC void AddAppInfo(pid_t pid, const char *processName)
|
||||
APPSPAWN_LOGI("Add %{public}s, pid=%{public}d success", processName, pid);
|
||||
}
|
||||
|
||||
APPSPAWN_STATIC void ProcessTimer(const TimerHandle taskHandle, void *context)
|
||||
{
|
||||
UNUSED(context);
|
||||
APPSPAWN_LOGI("timeout stop appspawn");
|
||||
LE_StopLoop(LE_GetDefaultLoop());
|
||||
}
|
||||
|
||||
static AppInfo *GetAppInfo(pid_t pid)
|
||||
{
|
||||
HashNode *node = OH_HashMapGet(g_appSpawnContent->appMap, (const void *)&pid);
|
||||
@ -116,13 +109,6 @@ static void RemoveAppInfo(pid_t pid)
|
||||
if ((g_appSpawnContent->flags & FLAGS_ON_DEMAND) != FLAGS_ON_DEMAND) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_appSpawnContent->timer == NULL && OH_HashMapIsEmpty(g_appSpawnContent->appMap) != 0) {
|
||||
APPSPAWN_LOGI("Start time for appspawn");
|
||||
int ret = LE_CreateTimer(LE_GetDefaultLoop(), &g_appSpawnContent->timer, ProcessTimer, NULL);
|
||||
APPSPAWN_CHECK(ret == 0, return, "Failed to create time");
|
||||
LE_StartTimer(LE_GetDefaultLoop(), g_appSpawnContent->timer, APPSPAWN_EXIT_TIME, 1); // 60000 60s
|
||||
}
|
||||
}
|
||||
|
||||
static void KillProcess(const HashNode *node, const void *context)
|
||||
@ -196,11 +182,30 @@ static void HandleDiedPid(pid_t pid, uid_t uid, int status)
|
||||
ReportProcessExitInfo(appInfo->name, pid, uid, status);
|
||||
#endif
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
// delete app info
|
||||
RemoveAppInfo(pid);
|
||||
}
|
||||
|
||||
static void HandleDiedPidNweb(pid_t pid, uid_t uid, int status)
|
||||
{
|
||||
AppInfo *appInfo = GetAppInfo(pid);
|
||||
APPSPAWN_CHECK(appInfo != NULL, return, "Can not find app info for %{public}d", pid);
|
||||
if (WIFSIGNALED(status)) {
|
||||
APPSPAWN_LOGW("%{public}s with pid %{public}d exit with signal:%{public}d",
|
||||
appInfo->name, pid, WTERMSIG(status));
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
APPSPAWN_LOGW("%{public}s with pid %{public}d exit with code:%{public}d",
|
||||
appInfo->name, pid, WEXITSTATUS(status));
|
||||
}
|
||||
|
||||
#ifdef REPORT_EVENT
|
||||
ReportProcessExitInfo(appInfo->name, pid, uid, status);
|
||||
#endif
|
||||
|
||||
// nwebspawn will invoke waitpid and remove appinfo at GetProcessTerminationStatusInner when
|
||||
// GetProcessTerminationStatusInner is called before the parent process receives the SIGCHLD signal.
|
||||
RecordRenderProcessExitedStatus(pid, status);
|
||||
#endif
|
||||
|
||||
// delete app info
|
||||
RemoveAppInfo(pid);
|
||||
@ -229,6 +234,29 @@ APPSPAWN_STATIC void SignalHandler(const struct signalfd_siginfo *siginfo)
|
||||
}
|
||||
}
|
||||
|
||||
APPSPAWN_STATIC void SignalHandlerNweb(const struct signalfd_siginfo *siginfo)
|
||||
{
|
||||
APPSPAWN_LOGI("SignalHandler signum %{public}d", siginfo->ssi_signo);
|
||||
switch (siginfo->ssi_signo) {
|
||||
case SIGCHLD: { // delete pid from app map
|
||||
pid_t pid;
|
||||
int status;
|
||||
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
HandleDiedPidNweb(pid, siginfo->ssi_uid, status);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SIGTERM: { // appswapn killed, use kill without parameter
|
||||
OH_HashMapTraverse(g_appSpawnContent->appMap, KillProcess, NULL);
|
||||
LE_StopLoop(LE_GetDefaultLoop());
|
||||
break;
|
||||
}
|
||||
default:
|
||||
APPSPAWN_LOGI("SigHandler, unsupported signal %{public}d.", siginfo->ssi_signo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleSpecial(AppSpawnClientExt *appProperty)
|
||||
{
|
||||
// special handle bundle name medialibrary and scanner
|
||||
@ -239,8 +267,8 @@ static void HandleSpecial(AppSpawnClientExt *appProperty)
|
||||
for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) {
|
||||
if (strcmp(appProperty->property.bundleName, specialBundleNames[i]) == 0) {
|
||||
if (appProperty->property.gidCount < APP_MAX_GIDS) {
|
||||
appProperty->property.gidTable[appProperty->property.gidCount] = GID_USER_DATA_RW;
|
||||
appProperty->property.gidCount++;
|
||||
appProperty->property.gidTable[appProperty->property.gidCount++] = GID_USER_DATA_RW;
|
||||
appProperty->property.gidTable[appProperty->property.gidCount++] = GID_FILE_ACCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -452,16 +480,15 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
// 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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
@ -593,7 +620,14 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[])
|
||||
AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content;
|
||||
APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content");
|
||||
|
||||
LE_STATUS status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandler);
|
||||
LE_STATUS status;
|
||||
|
||||
if (content->isNweb) {
|
||||
status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandlerNweb);
|
||||
} else {
|
||||
status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandler);
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
(void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD);
|
||||
(void)LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM);
|
||||
@ -651,7 +685,11 @@ static int CreateAppSpawnServer(AppSpawnContentExt *appSpawnContent, const char
|
||||
ret = chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to chmod %{public}s, err %{public}d. ", path, errno);
|
||||
#ifndef APPSPAWN_CHECK_GID_UID
|
||||
ret = lchown(path, 0, 4000); // 4000 is appspawn gid
|
||||
if (appSpawnContent->content.isNweb) {
|
||||
ret = lchown(path, 3081, 3081); // 3081 is appspawn gid
|
||||
} else {
|
||||
ret = lchown(path, 0, 4000); // 4000 is appspawn gid
|
||||
}
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to lchown %{public}s, err %{public}d. ", path, errno);
|
||||
#endif
|
||||
APPSPAWN_LOGI("CreateAppSpawnServer path %{public}s fd %{public}d",
|
||||
@ -670,6 +708,11 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam
|
||||
(void)memset_s(&appSpawnContent->content, sizeof(appSpawnContent->content), 0, sizeof(appSpawnContent->content));
|
||||
appSpawnContent->content.longProcName = longProcName;
|
||||
appSpawnContent->content.longProcNameLen = longProcNameLen;
|
||||
if (strcmp(longProcName, NWEBSPAWN_SERVER_NAME) == 0) {
|
||||
appSpawnContent->content.isNweb = true;
|
||||
} else {
|
||||
appSpawnContent->content.isNweb = false;
|
||||
}
|
||||
appSpawnContent->timer = NULL;
|
||||
appSpawnContent->flags = 0;
|
||||
appSpawnContent->server = NULL;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#define APPSPAWN_SERVICE_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include "appspawn_msg.h"
|
||||
#include "appspawn_server.h"
|
||||
#include "init_hashmap.h"
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "securec.h"
|
||||
#include "init_param.h"
|
||||
#include "syspara/parameter.h"
|
||||
|
||||
#include "nwebspawn_lancher.h"
|
||||
#define APPSPAWN_PRELOAD "libappspawn_helper.z.so"
|
||||
|
||||
static void CheckPreload(char *const argv[])
|
||||
@ -54,6 +54,7 @@ int main(int argc, char *const argv[])
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
uint32_t argvSize = 0;
|
||||
int mode = 0;
|
||||
pid_t pid = 1;
|
||||
if ((argc > PARAM_INDEX) && (strcmp(argv[START_INDEX], "cold-start") == 0)) {
|
||||
argvSize = APP_LEN_PROC_NAME;
|
||||
mode = 1;
|
||||
@ -68,26 +69,45 @@ int main(int argc, char *const argv[])
|
||||
if (argvSize > APP_MSG_MAX_SIZE) {
|
||||
return -1;
|
||||
}
|
||||
pid = NwebSpawnLanch();
|
||||
int isRet = memset_s(argv[0], argvSize, 0, (size_t)argvSize) != EOK;
|
||||
APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset argv[0]");
|
||||
isRet = strncpy_s(argv[0], argvSize, APPSPAWN_SERVER_NAME, strlen(APPSPAWN_SERVER_NAME)) != EOK;
|
||||
if (pid == 0) {
|
||||
isRet = strncpy_s(argv[0], argvSize, NWEBSPAWN_SERVER_NAME, strlen(NWEBSPAWN_SERVER_NAME)) != EOK;
|
||||
} else {
|
||||
isRet = strncpy_s(argv[0], argvSize, APPSPAWN_SERVER_NAME, strlen(APPSPAWN_SERVER_NAME)) != EOK;
|
||||
}
|
||||
APPSPAWN_CHECK(!isRet, return -EINVAL, "strncpy_s appspawn server name error: %{public}d", errno);
|
||||
}
|
||||
|
||||
APPSPAWN_LOGI("AppSpawnCreateContent argc %{public}d mode %{public}d %{public}u", argc, mode, argvSize);
|
||||
AppSpawnContent *content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, argv[0], argvSize, mode);
|
||||
APPSPAWN_CHECK(content != NULL, return -1, "Invalid content for appspawn");
|
||||
APPSPAWN_CHECK(content->initAppSpawn != NULL, return -1, "Invalid content for appspawn");
|
||||
APPSPAWN_CHECK(content->runAppSpawn != NULL, return -1, "Invalid content for appspawn");
|
||||
if (pid == 0) {
|
||||
APPSPAWN_LOGI("NwebSpawnCreateContent argc %{public}d mode %{public}d %{public}u", argc, mode, argvSize);
|
||||
AppSpawnContent *content = AppSpawnCreateContent(NWEBSPAWN_SOCKET_NAME, argv[0], argvSize, mode);
|
||||
APPSPAWN_CHECK(content != NULL, return -1, "Invalid content for nwebspawn");
|
||||
APPSPAWN_CHECK(content->initAppSpawn != NULL, return -1, "Invalid content for nwebspawn");
|
||||
APPSPAWN_CHECK(content->runAppSpawn != NULL, return -1, "Invalid content for nwebspawn");
|
||||
|
||||
// set common operation
|
||||
content->loadExtendLib = LoadExtendLib;
|
||||
content->runChildProcessor = RunChildProcessor;
|
||||
content->initAppSpawn(content);
|
||||
if (mode == 0) {
|
||||
SystemSetParameter("bootevent.appspawn.started", "true");
|
||||
// set common operation
|
||||
content->loadExtendLib = LoadExtendLibNweb;
|
||||
content->runChildProcessor = RunChildProcessorNweb;
|
||||
content->initAppSpawn(content);
|
||||
content->runAppSpawn(content, argc, argv);
|
||||
} else {
|
||||
APPSPAWN_LOGI("AppSpawnCreateContent argc %{public}d mode %{public}d %{public}u", argc, mode, argvSize);
|
||||
AppSpawnContent *content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, argv[0], argvSize, mode);
|
||||
APPSPAWN_CHECK(content != NULL, return -1, "Invalid content for appspawn");
|
||||
APPSPAWN_CHECK(content->initAppSpawn != NULL, return -1, "Invalid content for appspawn");
|
||||
APPSPAWN_CHECK(content->runAppSpawn != NULL, return -1, "Invalid content for appspawn");
|
||||
|
||||
// set common operation
|
||||
content->loadExtendLib = LoadExtendLib;
|
||||
content->runChildProcessor = RunChildProcessor;
|
||||
content->initAppSpawn(content);
|
||||
if (mode == 0) {
|
||||
SystemSetParameter("bootevent.appspawn.started", "true");
|
||||
}
|
||||
content->runAppSpawn(content, argc, argv);
|
||||
}
|
||||
content->runAppSpawn(content, argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ config("utest_config") {
|
||||
|
||||
ohos_unittest("AppSpawn_ut") {
|
||||
module_out_path = "${module_output_path}"
|
||||
|
||||
deps = []
|
||||
defines = [
|
||||
"clone=CloneStub",
|
||||
"bind=BindStub",
|
||||
@ -92,6 +92,7 @@ ohos_unittest("AppSpawn_ut") {
|
||||
sources = [
|
||||
"${appspawn_path}/adapter/appspawn_ace.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_adapter.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_nweb.cpp",
|
||||
"${appspawn_path}/adapter/appspawn_sandbox.cpp",
|
||||
"${appspawn_path}/common/appspawn_server.c",
|
||||
"${appspawn_path}/interfaces/innerkits/client/appspawn_socket.cpp",
|
||||
@ -112,13 +113,14 @@ ohos_unittest("AppSpawn_ut") {
|
||||
]
|
||||
|
||||
configs = [ "//base/startup/appspawn/test/unittest:utest_config" ]
|
||||
|
||||
deps += [ "//third_party/selinux:libselinux" ]
|
||||
external_deps = [
|
||||
"ability_base:want",
|
||||
"ability_runtime:app_manager",
|
||||
"ability_runtime:appkit_native",
|
||||
"ability_runtime:runtime",
|
||||
"access_token:libtoken_setproc",
|
||||
"access_token:libtokenid_sdk",
|
||||
"bundle_framework:appexecfwk_base",
|
||||
"bundle_framework:appexecfwk_core",
|
||||
"c_utils:utils",
|
||||
|
@ -1058,33 +1058,32 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_33, TestSize.Level0)
|
||||
m_appProperty->uid = 1000;
|
||||
m_appProperty->gid = 1000;
|
||||
|
||||
const char *srcPath = "/data/app/el1";
|
||||
std::string path = srcPath;
|
||||
std::string path = "/data/app/el1";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path);
|
||||
|
||||
const char *srcPath1 = "/data/app/el2/100/base/ohos.test.bundle1";
|
||||
std::string path1 = srcPath1;
|
||||
std::string path1 = "/data/app/el2/100/base/ohos.test.bundle1";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path1);
|
||||
|
||||
const char *srcPath2 = "/data/app/el2/100/database/ohos.test.bundle2";
|
||||
std::string path2 = srcPath2;
|
||||
std::string path2 = "/data/app/el2/100/database/ohos.test.bundle2";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path2);
|
||||
|
||||
const char *srcPath3 = "/data/app/el2/100/test123/ohos.test.bundle3";
|
||||
std::string path3 = srcPath3;
|
||||
std::string path3 = "/data/app/el2/100/test123/ohos.test.bundle3";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path3);
|
||||
|
||||
const char *srcPath4 = "/data/serivce/el2/100/hmdfs/account/data/ohos.test.bundle4";
|
||||
std::string path4 = srcPath4;
|
||||
std::string path4 = "/data/serivce/el2/100/hmdfs/account/data/ohos.test.bundle4";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path4);
|
||||
|
||||
const char *srcPath5 = "/data/serivce/el2/100/hmdfs/non_account/data/ohos.test.bundle5";
|
||||
std::string path5 = srcPath5;
|
||||
std::string path5 = "/data/serivce/el2/100/hmdfs/non_account/data/ohos.test.bundle5";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path5);
|
||||
|
||||
const char *srcPath6 = "/data/serivce/el2/100/hmdfs/non_account/test/ohos.test.bundle6";
|
||||
std::string path6 = srcPath6;
|
||||
std::string path6 = "/data/serivce/el2/100/hmdfs/non_account/test/ohos.test.bundle6";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path6);
|
||||
|
||||
std::string path7 = "/data/app/el2/100/group/091a68a9-2cc9-4279-8849-28631b598975";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path7);
|
||||
|
||||
std::string path8 = "/data/app/el2/100/group/ce876162-fe69-45d3-aa8e-411a047af564";
|
||||
OHOS::AppSpawn::SandboxUtils::CheckAndPrepareSrcPath(m_appProperty, path8);
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
@ -1411,4 +1410,48 @@ HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_39, TestSize.Level0)
|
||||
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_39 end";
|
||||
}
|
||||
/**
|
||||
* @tc.name: App_Spawn_Sandbox_40
|
||||
* @tc.desc: load group info config SetAppSandboxProperty
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:issueI7FUPV
|
||||
* @tc.author:
|
||||
*/
|
||||
HWTEST(AppSpawnSandboxTest, App_Spawn_Sandbox_40, TestSize.Level0)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_40 start";
|
||||
ClientSocket::AppProperty *m_appProperty = GetAppProperty();
|
||||
m_appProperty->uid = 1100;
|
||||
m_appProperty->gid = 1100;
|
||||
m_appProperty->gidCount = 2;
|
||||
m_appProperty->flags |= 0x100;
|
||||
std::string sandboxPrefix = "/mnt/sandbox/testBundle";
|
||||
|
||||
if (strcpy_s(m_appProperty->bundleName, APP_LEN_BUNDLE_NAME, "testBundle") != 0) {
|
||||
GTEST_LOG_(INFO) << "SetAppSandboxProperty set bundleName" << std::endl;
|
||||
}
|
||||
{ // totalLength is 0
|
||||
m_appProperty->dataGroupInfoList = {};
|
||||
int ret = OHOS::AppSpawn::SandboxUtils::MountAllGroup(m_appProperty, sandboxPrefix);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
{ // data is nullptr
|
||||
m_appProperty->dataGroupInfoList = {1, nullptr};
|
||||
int ret = OHOS::AppSpawn::SandboxUtils::MountAllGroup(m_appProperty, sandboxPrefix);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
{ // success
|
||||
char dataGroupInfoListStr[] = "{ \
|
||||
\"dataGroupId\":[\"1234abcd5678efgh\", \"abcduiop1234\"], \
|
||||
\"dir\":[\"/data/app/el2/100/group/091a68a9-2cc9-4279-8849-28631b598975\", \
|
||||
\"/data/app/el2/100/group/ce876162-fe69-45d3-aa8e-411a047af564\"], \
|
||||
\"gid\":[\"20100001\", \"20100002\"] \
|
||||
}";
|
||||
m_appProperty->dataGroupInfoList = {strlen(dataGroupInfoListStr), dataGroupInfoListStr};
|
||||
int ret = OHOS::AppSpawn::SandboxUtils::MountAllGroup(m_appProperty, sandboxPrefix);
|
||||
EXPECT_EQ(0, ret);
|
||||
}
|
||||
m_appProperty->dataGroupInfoList = {};
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Sandbox_40 end";
|
||||
}
|
||||
} // namespace OHOS
|
@ -52,7 +52,6 @@ TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskHandle server, ui
|
||||
bool ReceiveRequestData(const TaskHandle taskHandle, AppSpawnClientExt *appProperty,
|
||||
const uint8_t *buffer, uint32_t buffLen);
|
||||
void AddAppInfo(pid_t pid, const char *processName);
|
||||
void ProcessTimer(const TimerHandle taskHandle, void *context);
|
||||
void SignalHandler(const struct signalfd_siginfo *siginfo);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
@ -123,6 +122,13 @@ static void CheckAndCreateDir(const char *fileName)
|
||||
free(path);
|
||||
}
|
||||
|
||||
static void ProcessTimer(const TimerHandle taskHandle, void *context)
|
||||
{
|
||||
UNUSED(context);
|
||||
APPSPAWN_LOGI("timeout stop appspawn");
|
||||
LE_StopLoop(LE_GetDefaultLoop());
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
class AppSpawnStandardTest : public testing::Test {
|
||||
public:
|
||||
@ -157,69 +163,6 @@ static void FreeHspList(HspList &hspList)
|
||||
hspList = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: App_Spawn_Standard_002
|
||||
* @tc.desc: fork app son process and set content.
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:issueI5NTX6
|
||||
* @tc.author:
|
||||
*/
|
||||
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_002, TestSize.Level0)
|
||||
{
|
||||
CheckAndCreateDir("/data/appspawn_ut/dev/unix/socket/");
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Standard_002 start";
|
||||
char longProcName[124] = "App_Spawn_Standard_002";
|
||||
int64_t longProcNameLen = 124; // 124 is str length
|
||||
AppSpawnClientExt* client = (AppSpawnClientExt*)malloc(sizeof(AppSpawnClientExt));
|
||||
client->client.id = 8; // 8 is client id
|
||||
client->client.flags = 0;
|
||||
client->client.cloneFlags = CLONE_NEWNS;
|
||||
client->fd[0] = 100; // 100 is fd
|
||||
client->fd[1] = 200; // 200 is fd
|
||||
client->property.uid = 10000; // 10000 is uid
|
||||
client->property.gid = 1000; // 1000 is gid
|
||||
client->property.gidCount = 1; // 1 is gidCount
|
||||
if (strcpy_s(client->property.processName, APP_LEN_PROC_NAME, "xxx.xxx.xxx") != 0) {
|
||||
GTEST_LOG_(INFO) << "strcpy_s failed";
|
||||
}
|
||||
if (strcpy_s(client->property.bundleName, APP_LEN_BUNDLE_NAME, "xxx.xxx.xxx") != 0) {
|
||||
GTEST_LOG_(INFO) << "strcpy_s failed";
|
||||
}
|
||||
if (strcpy_s(client->property.soPath, APP_LEN_SO_PATH, "xxx") != 0) {
|
||||
GTEST_LOG_(INFO) << "strcpy_s failed";
|
||||
}
|
||||
client->property.accessTokenId = 671201800; // 671201800 is accessTokenId
|
||||
if (strcpy_s(client->property.apl, APP_APL_MAX_LEN, "xxx") != 0) {
|
||||
GTEST_LOG_(INFO) << "strcpy_s failed";
|
||||
}
|
||||
if (strcpy_s(client->property.renderCmd, APP_RENDER_CMD_MAX_LEN, "xxx") != 0) {
|
||||
GTEST_LOG_(INFO) << "strcpy_s failed";
|
||||
}
|
||||
client->property.hspList = {0, 0, nullptr};
|
||||
|
||||
AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", longProcName, longProcNameLen, 1);
|
||||
content->loadExtendLib = LoadExtendLib;
|
||||
content->runChildProcessor = RunChildProcessor;
|
||||
SetContentFunction(content);
|
||||
|
||||
content->clearEnvironment(content, &client->client);
|
||||
EXPECT_EQ(content->setProcessName(content, &client->client, (char *)longProcName, longProcNameLen), 0);
|
||||
EXPECT_EQ(content->setKeepCapabilities(content, &client->client), 0);
|
||||
EXPECT_EQ(content->setUidGid(content, &client->client), 0);
|
||||
EXPECT_EQ(content->setCapabilities(content, &client->client), 0);
|
||||
EXPECT_EQ(content->setFileDescriptors(content, &client->client), 0);
|
||||
|
||||
// test invalid
|
||||
EXPECT_NE(content->setProcessName(content, &client->client, nullptr, 0), 0);
|
||||
|
||||
content->setAppSandbox(content, &client->client);
|
||||
int ret = content->setAppAccessToken(content, &client->client);
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_NE(content->coldStartApp(content, &client->client), 0);
|
||||
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Standard_002 end";
|
||||
}
|
||||
|
||||
/**
|
||||
* @tc.name: App_Spawn_Standard_003
|
||||
* @tc.desc: Verify set Arg if GetAppSpawnClient succeed.
|
||||
@ -421,6 +364,60 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_3, TestSize.Level0)
|
||||
APPSPAWN_LOGI("App_Spawn_Standard_003_3 en");
|
||||
}
|
||||
/**
|
||||
* @tc.name: App_Spawn_Standard_003_4
|
||||
* @tc.desc: Verify set Arg if GetAppSpawnClient succeed, with dataGroupList
|
||||
* @tc.type: FUNC
|
||||
* @tc.require:issueI7FUPV
|
||||
* @tc.author:
|
||||
*/
|
||||
HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003_4, TestSize.Level0)
|
||||
{
|
||||
APPSPAWN_LOGI("App_Spawn_Standard_003_4 start");
|
||||
AppSpawnClientExt client = {};
|
||||
char arg1[] = "/system/bin/appspawn";
|
||||
char arg2[] = "cold-start";
|
||||
char arg3[] = "1";
|
||||
char arg4[] = "1:1:1:1:1:1:1:1:1:2:1000:1000:ohos.samples:ohos.samples.ecg:"
|
||||
"default:671201800:system_core:default:0:671201800";
|
||||
char arg5[] = "0";
|
||||
char arg6[] = "0";
|
||||
char arg7[] = "0";
|
||||
char arg8[] = "0";
|
||||
{
|
||||
char arg9[] = "10";
|
||||
char arg10[] = "012345678";
|
||||
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10};
|
||||
int argc = sizeof(argv)/sizeof(argv[0]);
|
||||
EXPECT_EQ(0, GetAppSpawnClientFromArg(argc, argv, &client));
|
||||
FreeHspList(client.property.hspList);
|
||||
}
|
||||
{ // dataGroupList length is 0
|
||||
char arg9[] = "0";
|
||||
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, nullptr};
|
||||
int argc = sizeof(argv)/sizeof(argv[0]);
|
||||
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
|
||||
}
|
||||
{ // dataGroupList length is nullptr
|
||||
char arg10[] = "0123456789";
|
||||
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, nullptr, arg10};
|
||||
int argc = sizeof(argv)/sizeof(argv[0]);
|
||||
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
|
||||
}
|
||||
{ // dataGroupList length is non-zero, but argc is 7
|
||||
char arg9[] = "10";
|
||||
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9};
|
||||
int argc = sizeof(argv)/sizeof(argv[0]);
|
||||
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
|
||||
}
|
||||
{ // dataGroupList length is non-zero, but content is nullptr
|
||||
char arg9[] = "10";
|
||||
char* argv[] = {arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, nullptr};
|
||||
int argc = sizeof(argv)/sizeof(argv[0]);
|
||||
EXPECT_EQ(-1, GetAppSpawnClientFromArg(argc, argv, &client));
|
||||
}
|
||||
APPSPAWN_LOGI("App_Spawn_Standard_003_4 en");
|
||||
}
|
||||
/**
|
||||
* @tc.name: App_Spawn_Standard_004
|
||||
* @tc.desc: App cold start.
|
||||
* @tc.type: FUNC
|
||||
@ -505,6 +502,22 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_005, TestSize.Level0)
|
||||
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);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
clientExt->property.flags &= ~APP_NO_SANDBOX;
|
||||
// bundle name
|
||||
clientExt->property.hspList.data = strdup("{ \
|
||||
\"bundles\":[\"test.bundle1\", \"test.bundle2\"], \
|
||||
\"modules\":[\"module1\", \"module2\"], \
|
||||
\"versions\":[\"v10001\", \"v10002\"] \
|
||||
}");
|
||||
clientExt->property.hspList.totalLength = strlen(clientExt->property.hspList.data);
|
||||
ret = SetAppSandboxProperty((AppSpawnContent_*)content, &clientExt->client);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
free(content);
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Standard_005 end";
|
||||
}
|
||||
@ -560,6 +573,7 @@ static AppSpawnContentExt *TestClient(int flags,
|
||||
AppOperateType code, const std::string &processName, const std::string &serverName)
|
||||
{
|
||||
char buffer[64] = {0}; // 64 buffer size
|
||||
CheckAndCreateDir(SOCKET_DIR);
|
||||
AppSpawnContentExt *content =
|
||||
(AppSpawnContentExt *)AppSpawnCreateContent(serverName.c_str(), buffer, sizeof(buffer), 0);
|
||||
if (content == nullptr) {
|
||||
@ -649,7 +663,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_006_4, TestSize.Level0)
|
||||
{
|
||||
GTEST_LOG_(INFO) << "App_Spawn_Standard_006_4 start";
|
||||
SetHapDomainSetcontextResult(-1);
|
||||
SetParameter("const.appspawn.preload", "false");
|
||||
|
||||
AppSpawnContentExt *content = TestClient(APP_COLD_BOOT,
|
||||
DEFAULT, "com.ohos.medialibrary.medialibrarydata", "test006_2");
|
||||
ASSERT_TRUE(content != nullptr);
|
||||
|
@ -16,10 +16,12 @@
|
||||
#ifndef SANDBOX_UTILS_H
|
||||
#define SANDBOX_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/types.h>
|
||||
#include <vector>
|
||||
|
||||
#include "nlohmann/json.hpp"
|
||||
#include "client_socket.h"
|
||||
#include "appspawn_server.h"
|
||||
@ -33,13 +35,14 @@ public:
|
||||
static void StoreJsonConfig(nlohmann::json &appSandboxConfig);
|
||||
static std::vector<nlohmann::json> &GetJsonConfig();
|
||||
static int32_t SetAppSandboxProperty(AppSpawnClient *client);
|
||||
static int32_t SetAppSandboxPropertyNweb(AppSpawnClient *client);
|
||||
static uint32_t GetNamespaceFlagsFromConfig(const char *bundleName);
|
||||
static std::set<std::string> GetMountPermissionNames();
|
||||
|
||||
private:
|
||||
static int32_t DoAppSandboxMountOnce(const char *originPath, const char *destinationPath,
|
||||
const char *fsType, unsigned long mountFlags,
|
||||
const char *options);
|
||||
const char *options, mode_t mountSharedFlag = MS_SLAVE);
|
||||
static int32_t DoSandboxFileCommonBind(const ClientSocket::AppProperty *appProperty, nlohmann::json &wholeConfig);
|
||||
static int32_t DoSandboxFileCommonSymlink(const ClientSocket::AppProperty *appProperty,
|
||||
nlohmann::json &wholeConfig);
|
||||
@ -78,6 +81,8 @@ private:
|
||||
nlohmann::json &config);
|
||||
static int32_t SetRenderSandboxProperty(const ClientSocket::AppProperty *appProperty,
|
||||
std::string &sandboxPackagePath);
|
||||
static int32_t SetRenderSandboxPropertyNweb(const ClientSocket::AppProperty *appProperty,
|
||||
std::string &sandboxPackagePath);
|
||||
static int32_t SetOverlayAppSandboxProperty(const ClientSocket::AppProperty *appProperty,
|
||||
std::string &sandboxPackagePath);
|
||||
static int32_t DoSandboxFilePermissionBind(ClientSocket::AppProperty *appProperty,
|
||||
|
@ -104,17 +104,15 @@ namespace {
|
||||
const char *g_topSandBoxSwitchPrefix = "top-sandbox-switch";
|
||||
const char *g_targetName = "target-name";
|
||||
const char *g_flagePoint = "flags-point";
|
||||
const char *g_mountSharedFlag = "mount-shared-flag";
|
||||
const char *g_flags = "flags";
|
||||
const char *g_sandBoxNameSpace = "sandbox-namespace";
|
||||
const char *g_sandBoxCloneFlags = "clone-flags";
|
||||
const char* g_fileSeparator = "/";
|
||||
const char* g_overlayDecollator = "|";
|
||||
#ifndef NWEB_SPAWN
|
||||
const std::string g_sandBoxRootDir = "/mnt/sandbox/";
|
||||
#else
|
||||
const std::string g_ohosRender = "__internal__.com.ohos.render";
|
||||
const std::string g_sandBoxRootDir = "/mnt/sandbox/com.ohos.render/";
|
||||
#endif
|
||||
const std::string g_sandBoxRootDirNweb = "/mnt/sandbox/com.ohos.render/";
|
||||
}
|
||||
|
||||
nlohmann::json SandboxUtils::appNamespaceConfig_;
|
||||
@ -200,7 +198,7 @@ static void MakeDirRecursive(const std::string &path, mode_t mode)
|
||||
|
||||
int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char *destinationPath,
|
||||
const char *fsType, unsigned long mountFlags,
|
||||
const char *options)
|
||||
const char *options, mode_t mountSharedFlag)
|
||||
{
|
||||
// To make sure destinationPath exist
|
||||
MakeDirRecursive(destinationPath, FILE_MODE);
|
||||
@ -213,7 +211,7 @@ int32_t SandboxUtils::DoAppSandboxMountOnce(const char *originPath, const char *
|
||||
destinationPath);
|
||||
return ret;
|
||||
}
|
||||
ret = mount(NULL, destinationPath, NULL, MS_SLAVE, NULL);
|
||||
ret = mount(NULL, destinationPath, NULL, mountSharedFlag, NULL);
|
||||
APPSPAWN_CHECK(ret == 0, return ret,
|
||||
"errno is: %{public}d, private mount to %{public}s failed", errno, destinationPath);
|
||||
#endif
|
||||
@ -539,17 +537,16 @@ int SandboxUtils::DoAllMntPointsMount(const ClientSocket::AppProperty *appProper
|
||||
mntPoint[g_sandBoxPath].get<std::string>());
|
||||
unsigned long mountFlags = GetMountFlagsFromConfig(mntPoint[g_sandBoxFlags].get<std::vector<std::string>>());
|
||||
std::string fsType = (mntPoint.find(g_fsType) != mntPoint.end()) ? mntPoint[g_fsType].get<std::string>() : "";
|
||||
const char* fsTypePoint = fsType.empty() ? nullptr : fsType.c_str();
|
||||
mode_t mountSharedFlag = (mntPoint.find(g_mountSharedFlag) != mntPoint.end()) ? MS_SHARED : MS_SLAVE;
|
||||
|
||||
/* check and prepare /data/app/el2 base and database package path to avoid BMS failed to create this folder */
|
||||
CheckAndPrepareSrcPath(appProperty, srcPath);
|
||||
/* if app mount failed for special strategy, we need deal with common mount config */
|
||||
int ret = HandleSpecialAppMount(appProperty, srcPath, sandboxPath, fsType, mountFlags);
|
||||
if (ret < 0) {
|
||||
if (fsType.empty()) {
|
||||
ret = DoAppSandboxMountOnce(srcPath.c_str(), sandboxPath.c_str(), nullptr, mountFlags, nullptr);
|
||||
} else {
|
||||
ret = DoAppSandboxMountOnce(srcPath.c_str(), sandboxPath.c_str(), fsType.c_str(), mountFlags, nullptr);
|
||||
}
|
||||
ret = DoAppSandboxMountOnce(srcPath.c_str(), sandboxPath.c_str(), fsTypePoint,
|
||||
mountFlags, nullptr, mountSharedFlag);
|
||||
}
|
||||
if (ret) {
|
||||
std::string actionStatus = g_statusCheck;
|
||||
@ -804,7 +801,12 @@ int32_t SandboxUtils::SetPermissionAppSandboxProperty_(ClientSocket::AppProperty
|
||||
int32_t SandboxUtils::SetRenderSandboxProperty(const ClientSocket::AppProperty *appProperty,
|
||||
std::string &sandboxPackagePath)
|
||||
{
|
||||
#ifdef NWEB_SPAWN
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SandboxUtils::SetRenderSandboxPropertyNweb(const ClientSocket::AppProperty *appProperty,
|
||||
std::string &sandboxPackagePath)
|
||||
{
|
||||
for (auto config : SandboxUtils::GetJsonConfig()) {
|
||||
nlohmann::json privateAppConfig = config[g_privatePrefix][0];
|
||||
|
||||
@ -820,7 +822,6 @@ int32_t SandboxUtils::SetRenderSandboxProperty(const ClientSocket::AppProperty *
|
||||
appProperty->bundleName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -995,7 +996,6 @@ int32_t SandboxUtils::MountAllGroup(const ClientSocket::AppProperty *appProperty
|
||||
APPSPAWN_CHECK(dataGroupIds[i].is_string() && gids[i].is_string() && dirs[i].is_string(),
|
||||
return -1, "MountAllGroup: element type error");
|
||||
|
||||
std::string gid = gids[i];
|
||||
std::string libPhysicalPath = dirs[i];
|
||||
APPSPAWN_CHECK(!CheckPath(libPhysicalPath), return -1, "MountAllGroup: path error");
|
||||
|
||||
@ -1150,7 +1150,6 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawnClient *client)
|
||||
rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
|
||||
}
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
|
||||
#ifndef NWEB_SPAWN
|
||||
rc = SetCommonAppSandboxProperty(appProperty, sandboxPackagePath);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetCommonAppSandboxProperty failed, packagename is %{public}s",
|
||||
bundleName.c_str());
|
||||
@ -1162,15 +1161,69 @@ int32_t SandboxUtils::SetAppSandboxProperty(AppSpawnClient *client)
|
||||
rc = SetPermissionAppSandboxProperty(appProperty);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetPermissionAppSandboxProperty failed, packagename is %{public}s",
|
||||
bundleName.c_str());
|
||||
#else
|
||||
|
||||
rc = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetOverlayAppSandboxProperty failed, packagename is %s",
|
||||
bundleName.c_str());
|
||||
|
||||
#ifndef APPSPAWN_TEST
|
||||
rc = chdir(sandboxPackagePath.c_str());
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "chdir failed, packagename is %{public}s, path is %{public}s",
|
||||
bundleName.c_str(), sandboxPackagePath.c_str());
|
||||
|
||||
if (sandboxSharedStatus) {
|
||||
rc = chroot(sandboxPackagePath.c_str());
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "chroot failed, path is %{public}s errno is %{public}d",
|
||||
sandboxPackagePath.c_str(), errno);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str());
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "errno is %{public}d, pivot root failed, packagename is %{public}s",
|
||||
errno, bundleName.c_str());
|
||||
|
||||
rc = umount2(".", MNT_DETACH);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "MNT_DETACH failed, packagename is %{public}s", bundleName.c_str());
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SandboxUtils::SetAppSandboxPropertyNweb(AppSpawnClient *client)
|
||||
{
|
||||
APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client");
|
||||
AppSpawnClientExt *clientExt = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
ClientSocket::AppProperty *appProperty = &clientExt->property;
|
||||
if (CheckBundleName(appProperty->bundleName) != 0) {
|
||||
return -1;
|
||||
}
|
||||
std::string sandboxPackagePath = g_sandBoxRootDirNweb;
|
||||
const std::string bundleName = appProperty->bundleName;
|
||||
bool sandboxSharedStatus = GetSandboxPrivateSharedStatus(bundleName);
|
||||
sandboxPackagePath += bundleName;
|
||||
MakeDirRecursive(sandboxPackagePath.c_str(), FILE_MODE);
|
||||
int rc = 0;
|
||||
// when CLONE_NEWPID is enabled, CLONE_NEWNS must be enabled.
|
||||
if (!(client->cloneFlags & CLONE_NEWPID)) {
|
||||
// add pid to a new mnt namespace
|
||||
rc = unshare(CLONE_NEWNS);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "unshare failed, packagename is %{public}s", bundleName.c_str());
|
||||
}
|
||||
|
||||
// check app sandbox switch
|
||||
if ((CheckTotalSandboxSwitchStatus(appProperty) == false) ||
|
||||
(CheckAppSandboxSwitchStatus(appProperty) == false)) {
|
||||
rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath);
|
||||
} else if (!sandboxSharedStatus) {
|
||||
rc = DoSandboxRootFolderCreate(appProperty, sandboxPackagePath);
|
||||
}
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "DoSandboxRootFolderCreate failed, %{public}s", bundleName.c_str());
|
||||
// rendering process can be created by different apps,
|
||||
// and the bundle names of these apps are different,
|
||||
// so we can't use the method SetPrivateAppSandboxProperty
|
||||
// which mount dirs by using bundle name.
|
||||
rc = SetRenderSandboxProperty(appProperty, sandboxPackagePath);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetRenderSandboxProperty failed, packagename is %{public}s",
|
||||
rc = SetRenderSandboxPropertyNweb(appProperty, sandboxPackagePath);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetRenderSandboxPropertyNweb failed, packagename is %{public}s",
|
||||
sandboxPackagePath.c_str());
|
||||
#endif
|
||||
|
||||
rc = SetOverlayAppSandboxProperty(appProperty, sandboxPackagePath);
|
||||
APPSPAWN_CHECK(rc == 0, return rc, "SetOverlayAppSandboxProperty failed, packagename is %s",
|
||||
|
Loading…
Reference in New Issue
Block a user