mirror of
https://gitee.com/openharmony/startup_appspawn
synced 2024-11-23 07:00:17 +00:00
nweb from appspawn
Signed-off-by: wangxutao <wangxutao5@huawei.com>
This commit is contained in:
parent
61d14e264d
commit
f41592ccf9
111
BUILD.gn
111
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" ]
|
||||
}
|
||||
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",
|
||||
@ -117,14 +136,15 @@ ohos_static_library("appspawn_server") {
|
||||
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",
|
||||
]
|
||||
|
||||
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" ]
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,7 @@
|
||||
|
||||
#include <cerrno>
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
#include "selinux/selinux.h"
|
||||
#endif
|
||||
|
||||
#include "appspawn_service.h"
|
||||
#ifdef WITH_SELINUX
|
||||
@ -33,17 +31,29 @@
|
||||
const char* RENDERER_NAME = "renderer";
|
||||
#endif
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
#include "tokenid_kit.h"
|
||||
#include "access_token.h"
|
||||
|
||||
using namespace OHOS::Security::AccessToken;
|
||||
#endif
|
||||
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
#if NWEB_SPAWN
|
||||
uint64_t tokenId = appProperty->property.accessTokenIdEx;
|
||||
int32_t ret = SetSelfTokenID(tokenId);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::set access token id failed, ret = %{public}d", ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
APPSPAWN_LOGV("AppSpawnServer::set access token id = %{public}llu, ret = %{public}d %{public}d",
|
||||
static_cast<unsigned long long>(appProperty->property.accessTokenIdEx), ret, getuid());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetAppAccessTokenNweb(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
TokenIdKit tokenIdKit;
|
||||
uint64_t tokenId = tokenIdKit.GetRenderTokenID(appProperty->property.accessTokenIdEx);
|
||||
if (tokenId == static_cast<uint64_t>(INVALID_TOKENID)) {
|
||||
@ -51,9 +61,6 @@ int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
static_cast<unsigned long long>(tokenId));
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
uint64_t tokenId = appProperty->property.accessTokenIdEx;
|
||||
#endif
|
||||
int32_t ret = SetSelfTokenID(tokenId);
|
||||
if (ret != 0) {
|
||||
APPSPAWN_LOGE("AppSpawnServer::set access token id failed, ret = %{public}d", ret);
|
||||
@ -68,9 +75,6 @@ int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
void 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;
|
||||
@ -89,21 +93,37 @@ void SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
APPSPAWN_LOGV("AppSpawnServer::Success to hap domain set context, ret = %{public}d", ret);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetSelinuxConNweb(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SELINUX
|
||||
setcon("u:r:isolated_render:s0");
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetUidGidFilter(struct AppSpawnContent_ *content)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
#ifdef NWEB_SPAWN
|
||||
if (!SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME)) {
|
||||
APPSPAWN_LOGE("Failed to set APPSPAWN seccomp filter and exit");
|
||||
#ifndef APPSPAWN_TEST
|
||||
_exit(0x7f);
|
||||
#endif
|
||||
} else {
|
||||
APPSPAWN_LOGI("Success to set APPSPAWN seccomp filter");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetUidGidFilterNweb(struct AppSpawnContent_ *content)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
|
||||
APPSPAWN_LOGE("Failed to set no new privs");
|
||||
}
|
||||
|
||||
if (!SetSeccompPolicyWithName(INDIVIDUAL, NWEBSPAWN_NAME)) {
|
||||
#else
|
||||
if (!SetSeccompPolicyWithName(INDIVIDUAL, APPSPAWN_NAME)) {
|
||||
#endif
|
||||
APPSPAWN_LOGE("Failed to set APPSPAWN seccomp filter and exit");
|
||||
#ifndef APPSPAWN_TEST
|
||||
_exit(0x7f);
|
||||
@ -117,13 +137,25 @@ 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;
|
||||
if (!SetSeccompPolicyWithName(type, appName)) {
|
||||
APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit", appName);
|
||||
#ifndef APPSPAWN_TEST
|
||||
return -EINVAL;
|
||||
#endif
|
||||
} else {
|
||||
APPSPAWN_LOGI("Success to set %{public}s seccomp filter", appName);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SetSeccompFilterNweb(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifdef WITH_SECCOMP
|
||||
const char *appName = RENDERER_NAME;
|
||||
SeccompFilterType type = INDIVIDUAL;
|
||||
if (!SetSeccompPolicyWithName(type, appName)) {
|
||||
APPSPAWN_LOGE("Failed to set %{public}s seccomp filter and exit", appName);
|
||||
#ifndef APPSPAWN_TEST
|
||||
|
@ -25,13 +25,20 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int32_t SetAppSandboxPropertyNweb(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetAppAccessTokenNweb(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void SetSelinuxCon(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
void SetSelinuxConNweb(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);
|
||||
void SetUidGidFilterNweb(struct AppSpawnContent_ *content);
|
||||
int SetSeccompFilter(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
int SetSeccompFilterNweb(struct AppSpawnContent_ *content, AppSpawnClient *client);
|
||||
uint32_t GetAppNamespaceFlags(const char *bundleName);
|
||||
void HandleInternetPermission(const AppSpawnClient *client);
|
||||
|
||||
|
@ -120,17 +120,28 @@ void *LoadWithRelroFile(const std::string &lib, const std::string &nsName,
|
||||
}
|
||||
#endif
|
||||
|
||||
void LoadExtendLib(AppSpawnContent *content)
|
||||
void LoadExtendLibNweb(AppSpawnContent *content)
|
||||
{
|
||||
const std::string loadLibDir = GetNWebHapLibsPath();
|
||||
int repeat_count = 0;
|
||||
#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);
|
||||
while (handle == nullptr && repeat_count < 10) {
|
||||
sleep(1);
|
||||
handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
++repeat_count;
|
||||
}
|
||||
#else
|
||||
void *handle = LoadWithRelroFile("libweb_engine.so", "nweb_ns", loadLibDir);
|
||||
while (handle == nullptr && repeat_count < 10) {
|
||||
sleep(1);
|
||||
handle = LoadWithRelroFile("libweb_engine.so", "nweb_ns", loadLibDir);
|
||||
++repeat_count;
|
||||
}
|
||||
if (handle == nullptr) {
|
||||
APPSPAWN_LOGE("dlopen_ns_ext failed, fallback to dlopen_ns");
|
||||
handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
@ -139,18 +150,33 @@ void LoadExtendLib(AppSpawnContent *content)
|
||||
#else
|
||||
const std::string engineLibDir = loadLibDir + "/libweb_engine.so";
|
||||
void *handle = dlopen(engineLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
while (handle == nullptr && repeat_count < 10) {
|
||||
sleep(1);
|
||||
handle = dlopen(engineLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
++repeat_count;
|
||||
}
|
||||
#endif
|
||||
if (handle == nullptr) {
|
||||
APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, [%{public}s]", dlerror());
|
||||
} else {
|
||||
APPSPAWN_LOGI("Success to dlopen libweb_engine.so");
|
||||
}
|
||||
|
||||
repeat_count = 0;
|
||||
#ifdef __MUSL__
|
||||
g_nwebHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
while (g_nwebHandle == nullptr && repeat_count < 10) {
|
||||
sleep(1);
|
||||
handle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL);
|
||||
++repeat_count;
|
||||
}
|
||||
#else
|
||||
const std::string renderLibDir = loadLibDir + "/libnweb_render.so";
|
||||
g_nwebHandle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
while (g_nwebHandle == nullptr && repeat_count < 10) {
|
||||
sleep(1);
|
||||
handle = dlopen(renderLibDir.c_str(), RTLD_NOW | RTLD_GLOBAL);
|
||||
++repeat_count;
|
||||
}
|
||||
#endif
|
||||
if (g_nwebHandle == nullptr) {
|
||||
APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, [%{public}s]", dlerror());
|
||||
@ -159,7 +185,7 @@ void LoadExtendLib(AppSpawnContent *content)
|
||||
}
|
||||
}
|
||||
|
||||
void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client)
|
||||
void RunChildProcessorNweb(AppSpawnContent *content, AppSpawnClient *client)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
using FuncType = void (*)(const char *cmd);
|
||||
|
@ -92,6 +92,42 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SetAppSandboxPropertyNweb(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
APPSPAWN_CHECK(client != NULL, return -1, "Invalid nwebspwn client");
|
||||
AppSpawnClientExt *clientExt = reinterpret_cast<AppSpawnClientExt *>(client);
|
||||
// no sandbox
|
||||
if (clientExt->property.flags & APP_NO_SANDBOX) {
|
||||
return 0;
|
||||
}
|
||||
// no news
|
||||
if ((client->cloneFlags & CLONE_NEWNS) != CLONE_NEWNS) {
|
||||
return 0;
|
||||
}
|
||||
int ret = SandboxUtils::SetAppSandboxPropertyNweb(client);
|
||||
// free HspList
|
||||
if (clientExt->property.hspList.data != nullptr) {
|
||||
free(clientExt->property.hspList.data);
|
||||
clientExt->property.hspList = {};
|
||||
}
|
||||
// free OverlayInfo
|
||||
if (clientExt->property.overlayInfo.data != nullptr) {
|
||||
free(clientExt->property.overlayInfo.data);
|
||||
clientExt->property.overlayInfo = {};
|
||||
}
|
||||
// free dataGroupInfoList
|
||||
if (clientExt->property.dataGroupInfoList.data != nullptr) {
|
||||
free(clientExt->property.dataGroupInfoList.data);
|
||||
clientExt->property.dataGroupInfoList = {};
|
||||
}
|
||||
// for module test do not create sandbox
|
||||
if (strncmp(clientExt->property.bundleName,
|
||||
MODULE_TEST_BUNDLE_NAME.c_str(), MODULE_TEST_BUNDLE_NAME.size()) == 0) {
|
||||
return 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t GetAppNamespaceFlags(const char *bundleName)
|
||||
{
|
||||
return SandboxUtils::GetNamespaceFlagsFromConfig(bundleName);
|
||||
|
52
adapter/nwebspawn_lancher.cpp
Normal file
52
adapter/nwebspawn_lancher.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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[2] = {};
|
||||
for (int j = 0; j < 2; ++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
|
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"
|
||||
}
|
||||
]
|
||||
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
@ -161,6 +161,47 @@ static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *cli
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int SetCapabilitiesNweb(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
// init cap
|
||||
struct __user_cap_header_struct cap_header;
|
||||
|
||||
bool isRet = memset_s(&cap_header, sizeof(cap_header), 0, sizeof(cap_header)) != EOK;
|
||||
APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap header");
|
||||
|
||||
cap_header.version = _LINUX_CAPABILITY_VERSION_3;
|
||||
cap_header.pid = 0;
|
||||
|
||||
struct __user_cap_data_struct cap_data[2];
|
||||
isRet = memset_s(&cap_data, sizeof(cap_data), 0, sizeof(cap_data)) != EOK;
|
||||
APPSPAWN_CHECK(!isRet, return -EINVAL, "Failed to memset cap data");
|
||||
|
||||
// init inheritable permitted effective zero
|
||||
#ifdef GRAPHIC_PERMISSION_CHECK
|
||||
const uint64_t inheriTable = 0;
|
||||
const uint64_t permitted = 0;
|
||||
const uint64_t effective = 0;
|
||||
#else
|
||||
const uint64_t inheriTable = 0x3fffffffff;
|
||||
const uint64_t permitted = 0x3fffffffff;
|
||||
const uint64_t effective = 0x3fffffffff;
|
||||
#endif
|
||||
|
||||
cap_data[0].inheritable = (__u32)(inheriTable);
|
||||
cap_data[1].inheritable = (__u32)(inheriTable >> BITLEN32);
|
||||
cap_data[0].permitted = (__u32)(permitted);
|
||||
cap_data[1].permitted = (__u32)(permitted >> BITLEN32);
|
||||
cap_data[0].effective = (__u32)(effective);
|
||||
cap_data[1].effective = (__u32)(effective >> BITLEN32);
|
||||
|
||||
// set capabilities
|
||||
isRet = capset(&cap_header, &cap_data[0]) == -1;
|
||||
APPSPAWN_CHECK(!isRet, return -errno, "capset failed: %{public}d", errno);
|
||||
SetSelinuxConNweb(content, client);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *client)
|
||||
{
|
||||
#ifndef APPSPAWN_TEST
|
||||
@ -669,17 +710,25 @@ 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->setUidGidFilter = SetUidGidFilter;
|
||||
if (strcmp(content->longProcName, NWEBSPAWN_SERVER_NAME) == 0) {
|
||||
content->setAppSandbox = SetAppSandboxPropertyNweb;
|
||||
content->setSeccompFilter = SetSeccompFilterNweb;
|
||||
content->setUidGidFilter = SetUidGidFilterNweb;
|
||||
content->setAppAccessToken = SetAppAccessTokenNweb;
|
||||
content->setCapabilities = SetCapabilitiesNweb;
|
||||
} else {
|
||||
content->setAppAccessToken = SetAppAccessToken;
|
||||
content->setAppSandbox = SetAppSandboxProperty;
|
||||
content->setSeccompFilter = SetSeccompFilter;
|
||||
content->setUidGidFilter = SetUidGidFilter;
|
||||
content->setCapabilities = SetCapabilities;
|
||||
}
|
||||
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)
|
||||
{
|
||||
const char *fileExtensionHapBundleName = "com.ohos.UserFile.ExternalFileManager";
|
||||
@ -459,7 +487,34 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef NWEB_SPAWN
|
||||
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);
|
||||
|
||||
// special handle bundle name medialibrary and scanner
|
||||
HandleSpecial(appProperty);
|
||||
if (g_appSpawnContent->timer != NULL) {
|
||||
LE_StopTimer(LE_GetDefaultLoop(), g_appSpawnContent->timer);
|
||||
g_appSpawnContent->timer = NULL;
|
||||
}
|
||||
appProperty->pid = 0;
|
||||
CheckColdAppEnabled(appProperty);
|
||||
int ret = HandleMessage(appProperty);
|
||||
if (ret != 0) {
|
||||
LE_CloseTask(LE_GetDefaultLoop(), taskHandle);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnReceiveRequestNweb(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");
|
||||
|
||||
if (!ReceiveRequestData(taskHandle, appProperty, buffer, buffLen)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get render process termination status, only nwebspawn need this logic.
|
||||
if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) {
|
||||
int ret = GetProcessTerminationStatus(&appProperty->client);
|
||||
@ -467,7 +522,6 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer,
|
||||
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);
|
||||
@ -529,6 +583,48 @@ APPSPAWN_STATIC TaskHandle AcceptClient(const LoopHandle loopHandle, const TaskH
|
||||
return stream;
|
||||
}
|
||||
|
||||
APPSPAWN_STATIC TaskHandle AcceptClientNweb(const LoopHandle loopHandle, const TaskHandle server, uint32_t flags)
|
||||
{
|
||||
static uint32_t clientId = 0;
|
||||
TaskHandle stream;
|
||||
LE_StreamInfo info = {};
|
||||
info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT;
|
||||
info.baseInfo.flags |= flags;
|
||||
info.baseInfo.close = OnClose;
|
||||
info.baseInfo.userDataSize = sizeof(AppSpawnClientExt);
|
||||
info.disConnectComplete = NULL;
|
||||
info.sendMessageComplete = SendMessageComplete;
|
||||
info.recvMessage = OnReceiveRequestNweb;
|
||||
|
||||
LE_STATUS ret = LE_AcceptStreamClient(loopHandle, server, &stream, &info);
|
||||
APPSPAWN_CHECK(ret == 0, return NULL, "Failed to alloc stream");
|
||||
AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(stream);
|
||||
APPSPAWN_CHECK(client != NULL, return NULL, "Failed to alloc stream");
|
||||
#ifndef APPSPAWN_CHECK_GID_UID
|
||||
struct ucred cred = {-1, -1, -1};
|
||||
socklen_t credSize = sizeof(struct ucred);
|
||||
if ((getsockopt(LE_GetSocketFd(stream), SOL_SOCKET, SO_PEERCRED, &cred, &credSize) < 0) ||
|
||||
(cred.uid != DecodeUid("foundation") && cred.uid != DecodeUid("root"))) {
|
||||
APPSPAWN_LOGE("Failed to check uid %{public}d", cred.uid);
|
||||
LE_CloseStreamTask(LE_GetDefaultLoop(), stream);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
client->stream = stream;
|
||||
client->client.id = ++clientId;
|
||||
client->client.flags = 0;
|
||||
client->property.hspList.totalLength = 0;
|
||||
client->property.hspList.savedLength = 0;
|
||||
client->property.hspList.data = NULL;
|
||||
client->property.overlayInfo.totalLength = 0;
|
||||
client->property.overlayInfo.data = NULL;
|
||||
client->property.dataGroupInfoList.totalLength = 0;
|
||||
client->property.dataGroupInfoList.data = NULL;
|
||||
APPSPAWN_LOGI("OnConnection client fd %{public}d Id %{public}d", LE_GetSocketFd(stream), client->client.id);
|
||||
return stream;
|
||||
}
|
||||
|
||||
static int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
|
||||
{
|
||||
APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server");
|
||||
@ -536,6 +632,13 @@ static int OnConnection(const LoopHandle loopHandle, const TaskHandle server)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OnConnectionNweb(const LoopHandle loopHandle, const TaskHandle server)
|
||||
{
|
||||
APPSPAWN_CHECK(server != NULL && loopHandle != NULL, return -1, "Error server");
|
||||
(void)AcceptClientNweb(loopHandle, server, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result)
|
||||
{
|
||||
AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client;
|
||||
@ -600,7 +703,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 (strcmp(content->longProcName, NWEBSPAWN_SERVER_NAME) == 0) {
|
||||
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);
|
||||
@ -650,7 +760,11 @@ static int CreateAppSpawnServer(AppSpawnContentExt *appSpawnContent, const char
|
||||
info.socketId = socketId;
|
||||
info.server = path;
|
||||
info.baseInfo.close = NULL;
|
||||
info.incommingConnect = OnConnection;
|
||||
if (strcmp(socketName, NWEBSPAWN_SOCKET_NAME) == 0) {
|
||||
info.incommingConnect = OnConnectionNweb;
|
||||
} else {
|
||||
info.incommingConnect = OnConnection;
|
||||
}
|
||||
|
||||
ret = LE_CreateStreamServer(LE_GetDefaultLoop(), &appSpawnContent->server, &info);
|
||||
APPSPAWN_CHECK(ret == 0, return -1, "Failed to create socket for %{public}s", path);
|
||||
@ -658,7 +772,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 (strcmp(socketName, NWEBSPAWN_SOCKET_NAME) == 0) {
|
||||
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",
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include "securec.h"
|
||||
#include "init_param.h"
|
||||
#include "syspara/parameter.h"
|
||||
|
||||
#include <policycoreutils.h>
|
||||
#include "nwebspawn_lancher.h"
|
||||
#define APPSPAWN_PRELOAD "libappspawn_helper.z.so"
|
||||
|
||||
static void CheckPreload(char *const argv[])
|
||||
@ -54,6 +55,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 +70,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",
|
||||
|
@ -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
|
||||
}
|
||||
@ -578,21 +577,8 @@ static AppSpawnContentExt *TestClient(int flags,
|
||||
task->incommingConnect(LE_GetDefaultLoop(), nullptr);
|
||||
int ret;
|
||||
content->content.initAppSpawn(&content->content);
|
||||
if (content->timer == nullptr) { // create timer for exit
|
||||
ret = LE_CreateTimer(LE_GetDefaultLoop(), &content->timer, ProcessTimer, nullptr);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = LE_StartTimer(LE_GetDefaultLoop(), content->timer, 500, 1); // 500 ms is timeout
|
||||
EXPECT_EQ(ret, 0);
|
||||
}
|
||||
ret = RunClient(content, flags, code, processName);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
if (content->timer == nullptr) { // create timer for exit
|
||||
ret = LE_CreateTimer(LE_GetDefaultLoop(), &content->timer, ProcessTimer, nullptr);
|
||||
EXPECT_EQ(ret, 0);
|
||||
ret = LE_StartTimer(LE_GetDefaultLoop(), content->timer, 500, 1); // 500 ms is timeout
|
||||
EXPECT_EQ(ret, 0);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ 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();
|
||||
|
||||
@ -78,6 +79,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,
|
||||
|
@ -109,12 +109,9 @@ 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_;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -1150,7 +1151,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 +1162,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