nweb from appspawn

Signed-off-by: wangxutao <wangxutao5@huawei.com>
This commit is contained in:
wangxutao 2023-07-07 20:19:02 +08:00
parent 61d14e264d
commit f41592ccf9
17 changed files with 553 additions and 196 deletions

111
BUILD.gn
View File

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

View File

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

View File

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

View File

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

View File

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

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

View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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