From f320707e25682efeb54c585a78b4dfd4b3e1613b Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 10:59:46 +0800 Subject: [PATCH 01/21] =?UTF-8?q?appspawn=20=E5=BD=92=E4=B8=80=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- BUILD.gn | 117 +- src/main.cpp => adapter/appspawn_ace.cpp | 40 +- .../appspawn_adapter.cpp | 97 +- .../appspawn_adapter.h | 29 +- adapter/appspawn_log.cpp | 83 ++ adapter/appspawn_nweb.cpp | 118 ++ adapter/appspawn_sandbox.cpp | 414 ++++++ appspawn.gni | 2 +- bundle.json | 1 - common/appspawn_server.c | 137 ++ common/appspawn_server.h | 116 ++ interfaces/innerkits/BUILD.gn | 6 +- .../innerkits/client}/appspawn_socket.cpp | 4 +- .../innerkits/client}/client_socket.cpp | 0 interfaces/innerkits/include/appspawn_msg.h | 80 ++ .../innerkits/include/appspawn_service.h | 33 +- interfaces/innerkits/include/client_socket.h | 39 +- lite/BUILD.gn | 83 ++ lite/appspawn_message.c | 204 +++ lite/appspawn_message.h | 57 + lite/appspawn_process.c | 193 +++ lite/appspawn_service.c | 206 +++ lite/bundle.json | 44 + lite/main.c | 85 ++ nwebspawn.cfg | 2 +- src/appspawn_msg_peer.cpp | 96 -- src/appspawn_server.cpp | 1186 ----------------- src/include/appspawn_msg_peer.h | 79 -- src/include/appspawn_server.h | 224 ---- src/include/server_socket.h | 132 -- src/socket/server_socket.cpp | 232 ---- standard/appspawn_process.c | 385 ++++++ standard/appspawn_service.c | 470 +++++++ standard/appspawn_service.h | 68 + standard/main.c | 52 + test/BUILD.gn | 8 +- test/mock/include/mock_server_socket.h | 180 --- test/mock/src/appspawn_msg_peer.cpp | 91 -- test/moduletest/BUILD.gn | 2 + test/moduletest/appspawn_module_test.cpp | 15 +- .../BUILD.gn | 43 +- .../app_spawn_lite_test.cpp | 399 ++++++ .../app_spawn_msg_peer_test.cpp | 224 ---- test/unittest/app_spawn_server_test/BUILD.gn | 115 -- .../app_spawn_server_mock_test.cpp | 162 --- .../app_spawn_server_override_test.cpp | 219 --- test/unittest/app_spawn_socket_test/BUILD.gn | 3 +- .../BUILD.gn | 40 +- .../app_spawn_standard_test.cpp | 189 +++ test/unittest/client_socket_test/BUILD.gn | 4 +- .../server_socket_test/server_socket_test.cpp | 185 --- tools/appspawn_start_app.cpp | 75 -- 52 files changed, 3602 insertions(+), 3466 deletions(-) rename src/main.cpp => adapter/appspawn_ace.cpp (41%) rename test/mock/src/server_socket.cpp => adapter/appspawn_adapter.cpp (30%) rename test/mock/src/main_thread.cpp => adapter/appspawn_adapter.h (52%) create mode 100644 adapter/appspawn_log.cpp create mode 100644 adapter/appspawn_nweb.cpp create mode 100644 adapter/appspawn_sandbox.cpp create mode 100644 common/appspawn_server.c create mode 100644 common/appspawn_server.h rename {src/socket => interfaces/innerkits/client}/appspawn_socket.cpp (97%) rename {src/socket => interfaces/innerkits/client}/client_socket.cpp (100%) create mode 100644 interfaces/innerkits/include/appspawn_msg.h rename test/mock/include/main_thread.h => interfaces/innerkits/include/appspawn_service.h (56%) mode change 100755 => 100644 interfaces/innerkits/include/client_socket.h create mode 100644 lite/BUILD.gn create mode 100644 lite/appspawn_message.c create mode 100644 lite/appspawn_message.h create mode 100644 lite/appspawn_process.c create mode 100644 lite/appspawn_service.c create mode 100644 lite/bundle.json create mode 100644 lite/main.c delete mode 100644 src/appspawn_msg_peer.cpp delete mode 100755 src/appspawn_server.cpp delete mode 100644 src/include/appspawn_msg_peer.h delete mode 100644 src/include/appspawn_server.h delete mode 100644 src/include/server_socket.h delete mode 100644 src/socket/server_socket.cpp create mode 100644 standard/appspawn_process.c create mode 100644 standard/appspawn_service.c create mode 100644 standard/appspawn_service.h create mode 100644 standard/main.c delete mode 100644 test/mock/include/mock_server_socket.h delete mode 100644 test/mock/src/appspawn_msg_peer.cpp rename test/unittest/{app_spawn_msg_peer_test => app_spawn_lite_test}/BUILD.gn (44%) create mode 100644 test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp delete mode 100644 test/unittest/app_spawn_msg_peer_test/app_spawn_msg_peer_test.cpp delete mode 100644 test/unittest/app_spawn_server_test/BUILD.gn delete mode 100644 test/unittest/app_spawn_server_test/app_spawn_server_mock_test.cpp delete mode 100644 test/unittest/app_spawn_server_test/app_spawn_server_override_test.cpp rename test/unittest/{server_socket_test => app_spawn_standard_test}/BUILD.gn (47%) create mode 100644 test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp delete mode 100644 test/unittest/server_socket_test/server_socket_test.cpp delete mode 100644 tools/appspawn_start_app.cpp diff --git a/BUILD.gn b/BUILD.gn index f5e5c570..034efc34 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -17,20 +17,30 @@ import("//build/ohos.gni") config("appspawn_config") { visibility = [ ":*" ] include_dirs = [ - "src/include", + "common", + "standard", + "adapter", "interfaces/innerkits/include", "//utils/native/base/include", "${aafwk_path}/frameworks/kits/appkit/native/app/include", "${aafwk_path}/interfaces/innerkits/app_manager/include/appmgr", + "${appexecfwk_path}/interfaces/innerkits/libeventhandler/include", + "${appexecfwk_path}/common/log/include", + "${appexecfwk_path}/interfaces/innerkits/appexecfwk_core/include/bundlemgr", + "${appexecfwk_path}/interfaces/innerkits/appexecfwk_base/include", "${aafwk_path}/interfaces/innerkits/want/include/ohos/aafwk/content", "${aafwk_path}/interfaces/innerkits/want/include", "${aafwk_path}/interfaces/innerkits/ability_manager/include", "${aafwk_path}/interfaces/innerkits/base/include", "${aafwk_path}/frameworks/kits/ability/native/include", "${aafwk_path}/services/abilitymgr/include", + "//base/global/resmgr_standard/interfaces/innerkits/include", "//base/security/access_token/interfaces/innerkits/token_setproc/include", "//base/startup/init_lite/services/log", + "//base/startup/init_lite/services/include", + "//base/startup/init_lite/services/loopevent/include", "//base/startup/init_lite/interfaces/innerkits/include", + "//base/startup/init_lite/interfaces/innerkits/sandbox/include", "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", ] @@ -40,13 +50,22 @@ config("appspawn_config") { } ohos_executable("appspawn") { - sources = [ "${appspawn_path}/src/main.cpp" ] + sources = [ + "${appspawn_path}/adapter/appspawn_ace.cpp", + "${appspawn_path}/standard/main.c", + ] configs = [ ":appspawn_config" ] deps = [ "${appspawn_path}:appspawn_server", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", + "//foundation/aafwk/standard/frameworks/kits/appkit:appkit_native", + ] + external_deps = [ + "ability_base:want", + "ability_runtime:app_manager", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "utils_base:utils", ] - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] install_enable = true subsystem_name = "${subsystem_name}" @@ -55,29 +74,30 @@ ohos_executable("appspawn") { ohos_static_library("appspawn_server") { sources = [ - "${appspawn_path}/src/appspawn_msg_peer.cpp", - "${appspawn_path}/src/appspawn_server.cpp", - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/server_socket.cpp", + "${appspawn_path}/adapter/appspawn_adapter.cpp", + "${appspawn_path}/adapter/appspawn_log.cpp", + "${appspawn_path}/adapter/appspawn_sandbox.cpp", + "${appspawn_path}/common/appspawn_server.c", + "${appspawn_path}/standard/appspawn_process.c", + "${appspawn_path}/standard/appspawn_service.c", + ] + defines = [ + "GRAPHIC_PERMISSION_CHECK", + "INIT_AGENT", ] - defines = [ "INIT_AGENT" ] configs = [ ":appspawn_config" ] ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ] deps = [ - "${aafwk_path}/frameworks/kits/ability/native:abilitykit_native", - "${aafwk_path}/frameworks/kits/appkit:appkit_native", + "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", "//base/startup/init_lite/interfaces/innerkits:libbegetutil", - "//base/startup/init_lite/services/log:init_log", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox", + "//base/startup/init_lite/services/loopevent:loopevent", + "//base/startup/init_lite/services/utils:libinit_tools", "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", + "//third_party/libuv:uv_static", "//utils/native/base:utils", ] - external_deps = [ - "ability_base:want", - "hilog_native:libhilog", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - ] - + external_deps = [ "hiviewdfx_hilog_native:libhilog" ] if (build_selinux) { external_deps += [ "selinux:libhap_restorecon" ] } @@ -86,20 +106,6 @@ ohos_static_library("appspawn_server") { part_name = "${part_name}" } -ohos_executable("appspawntools") { - sources = [ "${appspawn_path}/tools/appspawn_start_app.cpp" ] - configs = [ ":appspawn_config" ] - deps = [ - "${appspawn_path}:appspawn_server", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", - ] - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - - install_enable = true - subsystem_name = "${subsystem_name}" - part_name = "${part_name}" -} - ohos_prebuilt_etc("appspawn.rc") { source = "appspawn.cfg" relative_install_dir = "init" @@ -109,52 +115,17 @@ ohos_prebuilt_etc("appspawn.rc") { ohos_executable("nwebspawn") { defines = [ "NWEB_SPAWN" ] - sources = [ "${appspawn_path}/src/main.cpp" ] - configs = [ ":appspawn_config" ] - deps = [ - "${appspawn_path}:nwebspawn_server", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", - ] - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] - - install_enable = true - subsystem_name = "${subsystem_name}" - part_name = "${part_name}" -} - -ohos_static_library("nwebspawn_server") { - defines = [ - "INIT_AGENT", - "NWEB_SPAWN", - ] sources = [ - "${appspawn_path}/src/appspawn_msg_peer.cpp", - "${appspawn_path}/src/appspawn_server.cpp", - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/server_socket.cpp", + "${appspawn_path}/adapter/appspawn_nweb.cpp", + "${appspawn_path}/standard/main.c", ] configs = [ ":appspawn_config" ] - ldflags = [ "-Wl,--dynamic-linker,/system/bin/linker64z" ] deps = [ - "${aafwk_path}/frameworks/kits/ability/native:abilitykit_native", - "${aafwk_path}/frameworks/kits/appkit:appkit_native", - "//base/startup/init_lite/interfaces/innerkits:libbegetutil", - "//base/startup/init_lite/interfaces/innerkits/socket:libsocket_static", - "//base/startup/init_lite/services/log:init_log", - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", - "//utils/native/base:utils", - ] - external_deps = [ - "ability_base:want", - "hilog_native:libhilog", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", + "${appspawn_path}:appspawn_server", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox", ] - if (build_selinux) { - external_deps += [ "selinux:libhap_restorecon" ] - } - + install_enable = true subsystem_name = "${subsystem_name}" part_name = "${part_name}" } diff --git a/src/main.cpp b/adapter/appspawn_ace.cpp similarity index 41% rename from src/main.cpp rename to adapter/appspawn_ace.cpp index ae9fc8d2..09b5c90c 100644 --- a/src/main.cpp +++ b/adapter/appspawn_ace.cpp @@ -13,26 +13,34 @@ * limitations under the License. */ -#include +#include "appspawn_adapter.h" -#include "appspawn_server.h" -#include "hilog/log.h" +#include "main_thread.h" -int main(int argc, char *const argv[]) +void LoadExtendLib(AppSpawnContent *content) { - if (argc > 0) { - // calculate child process long name size - uintptr_t start = reinterpret_cast(argv[0]); - uintptr_t end = reinterpret_cast(strchr(argv[argc - 1], 0)); - uintptr_t argvSize = end - start; - -#ifdef NWEB_SPAWN - OHOS::AppSpawn::AppSpawnServer appspawnServer("/dev/unix/socket/NWebSpawn"); +#ifdef __aarch64__ + const char *acelibdir("/system/lib64/libace.z.so"); #else - OHOS::AppSpawn::AppSpawnServer appspawnServer("AppSpawn"); + const char *acelibdir("/system/lib/libace.z.so"); +#endif + void *AceAbilityLib = NULL; + APPSPAWN_LOGI("MainThread::LoadAbilityLibrary. Start calling dlopen acelibdir."); +#ifndef APPSPAWN_TEST + AceAbilityLib = dlopen(acelibdir, RTLD_NOW | RTLD_GLOBAL); #endif - appspawnServer.ServerMain(argv[0], argvSize); + if (AceAbilityLib == NULL) { + APPSPAWN_LOGE("Fail to dlopen %s, [%s]", acelibdir, dlerror()); + } else { + APPSPAWN_LOGI("Success to dlopen %s", acelibdir); } - - return 0; + APPSPAWN_LOGI("MainThread::LoadAbilityLibrary. End calling dlopen."); } + +void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) +{ + APPSPAWN_LOGI("AppExecFwk::MainThread::Start"); +#ifndef APPSPAWN_TEST + OHOS::AppExecFwk::MainThread::Start(); +#endif +} \ No newline at end of file diff --git a/test/mock/src/server_socket.cpp b/adapter/appspawn_adapter.cpp similarity index 30% rename from test/mock/src/server_socket.cpp rename to adapter/appspawn_adapter.cpp index 48d4c106..74a6e0d6 100644 --- a/test/mock/src/server_socket.cpp +++ b/adapter/appspawn_adapter.cpp @@ -13,81 +13,30 @@ * limitations under the License. */ -#include "server_socket.h" +#include "appspawn_adapter.h" #include -#include -#include -#include "client_socket.h" -#include "hilog/log.h" -#include "securec.h" - -namespace OHOS { -namespace AppSpawn { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MockServerSocket"}; - -ServerSocket::ServerSocket(const std::string &server) : AppSpawnSocket(server) -{} - -ServerSocket::~ServerSocket() -{} - -int ServerSocket::VerifyConnection(int connectFd) -{ - HiLog::Info(LABEL, "VerifyConnection"); - return 0; -} - -void ServerSocket::CloseConnection(int connectFd) -{ - HiLog::Info(LABEL, "CloseConnection"); -} - -void ServerSocket::SaveConnection(int connectFd) -{ - HiLog::Info(LABEL, "CloseConnection"); -} - -void ServerSocket::CloseServer() -{ - HiLog::Info(LABEL, "CloseServer"); -} - -void ServerSocket::CloseServerMonitor() -{ - HiLog::Info(LABEL, "CloseServerMonitor"); -} - -int ServerSocket::BindSocket(int connectFd) -{ - HiLog::Info(LABEL, "BindSocket"); - return 0; -} - -int ServerSocket::RegisterServerSocket(int &connectFd) -{ - HiLog::Info(LABEL, "RegisterServerSocket connectFd"); - return 0; -} - -int ServerSocket::RegisterServerSocket() -{ - HiLog::Info(LABEL, "RegisterServerSocket"); - return 0; -} - -int ServerSocket::WaitForConnection(int connectFd) -{ - HiLog::Info(LABEL, "WaitForConnection connectFd"); - return 0; -} - -int ServerSocket::WaitForConnection() -{ - HiLog::Info(LABEL, "WaitForConnection"); - return 0; +#include "token_setproc.h" +#ifdef WITH_SELINUX +#include "hap_restorecon.h" +#endif + +void SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + int32_t ret = SetSelfTokenID(appProperty->property.accessTokenId); + APPSPAWN_LOGI("AppSpawnServer::set access token id = %d, ret = %d %d", + appProperty->property.accessTokenId, ret, getuid()); + +#ifdef WITH_SELINUX + HapContext hapContext; + ret = hapContext.HapDomainSetcontext(appProperty->property.apl, appProperty->property.processName); + if (ret != 0) { + APPSPAWN_LOGE("AppSpawnServer::Failed to hap domain set context, errno = %d %s", + errno, appProperty->property.apl); + } else { + APPSPAWN_LOGI("AppSpawnServer::Success to hap domain set context, ret = %d", ret); + } +#endif } -} // namespace AppSpawn -} // namespace OHOS diff --git a/test/mock/src/main_thread.cpp b/adapter/appspawn_adapter.h similarity index 52% rename from test/mock/src/main_thread.cpp rename to adapter/appspawn_adapter.h index e063c078..267c8e1c 100644 --- a/test/mock/src/main_thread.cpp +++ b/adapter/appspawn_adapter.h @@ -13,17 +13,24 @@ * limitations under the License. */ -#include "main_thread.h" -#include "hilog/log.h" +#ifndef APPSPAWN_ADPATER_CPP +#define APPSPAWN_ADPATER_CPP -namespace OHOS { -namespace AppExecFwk { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MockMainThread"}; +#include "appspawn_service.h" -void MainThread::Start() -{ - HiLog::Info(LABEL, "Start"); +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client); +void SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client); +void LoadExtendLib(AppSpawnContent *content); +void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); + +void RegisterAppSandbox(struct AppSpawnContent_ *content, AppSpawnClient *client); +#ifdef __cplusplus } -} // namespace AppExecFwk -} // namespace OHOS +#endif +#endif \ No newline at end of file diff --git a/adapter/appspawn_log.cpp b/adapter/appspawn_log.cpp new file mode 100644 index 00000000..8fcb72f6 --- /dev/null +++ b/adapter/appspawn_log.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_server.h" + +#include +#include +#include +#include +#include +#include + +#include "hilog/log.h" +#include "securec.h" + +static AppspawnLogLevel g_logLevel = AppspawnLogLevel::INFO; +static constexpr int MAX_LOG_SIZE = 1024; +static constexpr int BASE_YEAR = 1900; +static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0, APPSPAWN_LABEL}; + +void AppspawnLogPrint(AppspawnLogLevel logLevel, const char *file, int line, const char *fmt, ...) +{ + if (logLevel < g_logLevel) { + return; + } + + va_list list; + va_start(list, fmt); + char tmpFmt[MAX_LOG_SIZE]; + if (vsnprintf_s(tmpFmt, MAX_LOG_SIZE, MAX_LOG_SIZE - 1, fmt, list) == -1) { + va_end(list); + return; + } + va_end(list); + + switch (logLevel) { + case AppspawnLogLevel::DEBUG: + OHOS::HiviewDFX::HiLog::Debug(LABEL, "[%{public}s:%{public}d]%{public}s", file, line, tmpFmt); + break; + case AppspawnLogLevel::INFO: + OHOS::HiviewDFX::HiLog::Info(LABEL, "[%{public}s:%{public}d]%{public}s", file, line, tmpFmt); + break; + case AppspawnLogLevel::WARN: + OHOS::HiviewDFX::HiLog::Warn(LABEL, "[%{public}s:%{public}d]%{public}s", file, line, tmpFmt); + break; + case AppspawnLogLevel::ERROR: + OHOS::HiviewDFX::HiLog::Error(LABEL, "[%{public}s:%{public}d]%{public}s", file, line, tmpFmt); + break; + case AppspawnLogLevel::FATAL: + OHOS::HiviewDFX::HiLog::Fatal(LABEL, "[%{public}s:%{public}d]%{public}s", file, line, tmpFmt); + break; + default: + break; + } + + time_t second = time(0); + if (second <= 0) { + return; + } + struct tm *t = localtime(&second); + FILE *outfile = fopen("/data/init_agent/appspawn.log", "a+"); + if (t == nullptr || outfile == nullptr) { + return; + } + (void)fprintf(outfile, "[%d-%d-%d %d:%d:%d][pid=%d][%s:%d]%s \n", + (t->tm_year + BASE_YEAR), (t->tm_mon + 1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, + getpid(), file, line, tmpFmt); + (void)fflush(outfile); + (void)fclose(outfile); + return; +} diff --git a/adapter/appspawn_nweb.cpp b/adapter/appspawn_nweb.cpp new file mode 100644 index 00000000..3274c362 --- /dev/null +++ b/adapter/appspawn_nweb.cpp @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_adapter.h" + +#include +#include + +#ifdef NWEB_SPAWN +#define RENDER_PROCESS_MAX_NUM 16 +#define RENDER_PROCESS_ARRAY_IDLE 0 + +typedef struct { + int32_t pid; + int exitStatus; +} RenderProcessNode; + +static RenderProcessNode g_renderProcessArray[RENDER_PROCESS_MAX_NUM]; +#endif + +void *g_nwebHandle = nullptr; + +void LoadExtendLib(AppSpawnContent *content) +{ + const std::string LOAD_LIB_DIR = "/data/app/el1/bundle/public/com.ohos.nweb/libs/arm"; +#ifdef __MUSL__ + Dl_namespace dlns; + dlns_init(&dlns, "nweb_ns"); + dlns_create(&dlns, LOAD_LIB_DIR.c_str()); + void *handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL); +#else + const std::string ENGINE_LIB_DIR = LOAD_LIB_DIR + "/libweb_engine.so"; + void *handle = dlopen(ENGINE_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL); +#endif + if (handle == nullptr) { + APPSPAWN_LOGE("Fail to dlopen libweb_engine.so, [%s]", dlerror()); + } else { + APPSPAWN_LOGI("Success to dlopen libweb_engine.so"); + } +#ifdef __MUSL__ + g_nwebHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL); +#else + const std::string RENDER_LIB_DIR = LOAD_LIB_DIR + "/libnweb_render.so"; + g_nwebHandle = dlopen(RENDER_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL); +#endif + if (g_nwebHandle == nullptr) { + APPSPAWN_LOGE("Fail to dlopen libnweb_render.so, [%s]", dlerror()); + } else { + APPSPAWN_LOGI("Success to dlopen libnweb_render.so"); + } +} + +void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + using FuncType = void (*)(const char *cmd); + FuncType funcNWebRenderMain = reinterpret_cast(dlsym(g_nwebHandle, "NWebRenderMain")); + if (funcNWebRenderMain == nullptr) { + APPSPAWN_LOGI("webviewspawn dlsym ERROR=%s", dlerror()); + return; + } + funcNWebRenderMain(appProperty->property.renderCmd); +} + +static void DumpRenderProcessExitedArray() +{ + APPSPAWN_LOGI("dump render process exited array:"); + for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { + APPSPAWN_LOGI("[pid, exitedStatus] = [%d, %d]", + g_renderProcessArray[i].pid, g_renderProcessArray[i].exitStatus); + } +} + +void RecordRenderProcessExitedStatus(pid_t pid, int status) +{ + int i = 0; + for (; i < RENDER_PROCESS_MAX_NUM; i++) { + if (g_renderProcessArray[i].pid == RENDER_PROCESS_ARRAY_IDLE) { + g_renderProcessArray[i].exitStatus = status; + g_renderProcessArray[i].pid = pid; + break; + } + } + if (i == RENDER_PROCESS_MAX_NUM) { + APPSPAWN_LOGE("no empty space in render process exited array"); + DumpRenderProcessExitedArray(); + } +} + +int GetRenderProcessTerminationStatus(int32_t pid, int *status) +{ + if (status == nullptr) { + return -EINVAL; + } + + for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { + if (g_renderProcessArray[i].pid == pid) { + *status = g_renderProcessArray[i].exitStatus; + g_renderProcessArray[i].pid = RENDER_PROCESS_ARRAY_IDLE; + return 0; + } + } + APPSPAWN_LOGE("not find pid[%d] in render process exited arrary", pid); + DumpRenderProcessExitedArray(); + return -EINVAL; +} \ No newline at end of file diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp new file mode 100644 index 00000000..51dcee01 --- /dev/null +++ b/adapter/appspawn_sandbox.cpp @@ -0,0 +1,414 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_adapter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sandbox.h" +#include "sandbox_namespace.h" + +bool g_isPrivAppSandboxCreated = false; +bool g_isAppSandboxCreated = false; + +constexpr std::string_view APL_SYSTEM_CORE("system_core"); +constexpr std::string_view APL_SYSTEM_BASIC("system_basic"); +constexpr static int UID_BASE = 200000; +constexpr static mode_t FILE_MODE = 0711; +constexpr static mode_t NWEB_FILE_MODE = 0511; + +static void RegisterSandbox(AppSpawnContentExt *appSpawnContent, const char *sandbox) +{ + if (sandbox == nullptr) { + APPSPAWN_LOGE("AppSpawnServer::invalid parameters"); + return; + } + APPSPAWN_LOGE("RegisterSandbox %s", sandbox); + InitDefaultNamespace(); + if (!InitSandboxWithName(sandbox)) { + CloseDefaultNamespace(); + APPSPAWN_LOGE("AppSpawnServer::Failed to init sandbox with name %s", sandbox); + return; + } + + DumpSandboxByName(sandbox); + if (PrepareSandbox(sandbox) != 0) { + APPSPAWN_LOGE("AppSpawnServer::Failed to prepare sandbox %s", sandbox); + DestroySandbox(sandbox); + CloseDefaultNamespace(); + return; + } + if (EnterDefaultNamespace() < 0) { + APPSPAWN_LOGE("AppSpawnServer::Failed to set default namespace"); + DestroySandbox(sandbox); + CloseDefaultNamespace(); + return; + } + CloseDefaultNamespace(); + if (strcmp(sandbox, "app") == 0) { + appSpawnContent->flags |= FLAGS_SANDBOX_APP; + } else if (strcmp(sandbox, "priv-app") == 0) { + appSpawnContent->flags |= FLAGS_SANDBOX_PRIVATE; + } +} + +void RegisterAppSandbox(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content; + APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); + + if ((appSpawnContent->flags & FLAGS_SANDBOX_PRIVATE) != FLAGS_SANDBOX_PRIVATE) { + if (strcmp("system_basic", appProperty->property.apl) == 0) { + RegisterSandbox(appSpawnContent, "priv-app"); + } + } + if ((appSpawnContent->flags & FLAGS_SANDBOX_APP) != FLAGS_SANDBOX_APP) { + if (strcmp("normal", appProperty->property.apl) == 0) { + RegisterSandbox(appSpawnContent, "app"); + } + } +} + +static int32_t DoAppSandboxMountOnce(const std::string originPath, const std::string destinationPath) +{ + int rc = 0; + + rc = mount(originPath.c_str(), destinationPath.c_str(), NULL, MS_BIND | MS_REC, NULL); + if (rc) { + APPSPAWN_LOGE("bind mount %s to %s failed %d", originPath.c_str(), + destinationPath.c_str(), errno); + return rc; + } + + rc = mount(NULL, destinationPath.c_str(), NULL, MS_PRIVATE, NULL); + if (rc) { + APPSPAWN_LOGE("private mount to %s failed %d", destinationPath.c_str(), errno); + return rc; + } + + return 0; +} + +static int32_t DoAppSandboxMount(const AppParameter &appProperty, std::string rootPath) +{ + std::string currentUserId = std::to_string(appProperty.uid / UID_BASE); + std::string oriInstallPath = "/data/app/el1/bundle/public/"; + std::string oriel1DataPath = "/data/app/el1/" + currentUserId + "/base/"; + std::string oriel2DataPath = "/data/app/el2/" + currentUserId + "/base/"; + std::string oriDatabasePath = "/data/app/el2/" + currentUserId + "/database/"; + std::string destDatabasePath = rootPath + "/data/storage/el2/database"; + std::string destInstallPath = rootPath + "/data/storage/el1/bundle"; + std::string destel1DataPath = rootPath + "/data/storage/el1/base"; + std::string destel2DataPath = rootPath + "/data/storage/el2/base"; + + int rc = 0; + + std::string bundleName = appProperty.bundleName; + oriInstallPath += bundleName; + oriel1DataPath += bundleName; + oriel2DataPath += bundleName; + oriDatabasePath += bundleName; + + std::map mountMap; + mountMap[destDatabasePath] = oriDatabasePath; + mountMap[destInstallPath] = oriInstallPath; + mountMap[destel1DataPath] = oriel1DataPath; + mountMap[destel2DataPath] = oriel2DataPath; + + std::map::iterator iter; + for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) { + rc = DoAppSandboxMountOnce(iter->second.c_str(), iter->first.c_str()); + if (rc) { + return rc; + } + } + + // to create some useful dir when mount point created + std::vector mkdirInfo; + std::string dirPath; + mkdirInfo.push_back("/data/storage/el1/bundle/nweb"); + mkdirInfo.push_back("/data/storage/el1/bundle/ohos.global.systemres"); + + for (size_t i = 0; i < mkdirInfo.size(); i++) { + dirPath = rootPath + mkdirInfo[i]; + mkdir(dirPath.c_str(), FILE_MODE); + } + + return 0; +} + +static int32_t DoAppSandboxMountCustomized(const AppParameter &appProperty, const std::string &rootPath) +{ + std::string bundleName = appProperty.bundleName; + std::string currentUserId = std::to_string(appProperty.uid / UID_BASE); + std::string destInstallPath = rootPath + "/data/storage/el1/bundle"; + bool AuthFlag = false; + const std::vector AuthAppList = {"com.ohos.launcher", "com.ohos.permissionmanager"}; + if (std::find(AuthAppList.begin(), AuthAppList.end(), bundleName) != AuthAppList.end()) { + AuthFlag = true; + } + + if (strcmp(appProperty.apl, APL_SYSTEM_BASIC.data()) == 0 || + strcmp(appProperty.apl, APL_SYSTEM_CORE.data()) == 0 || AuthFlag) { + // account_0/applications/ dir can still access other packages' data now for compatibility purpose + std::string oriapplicationsPath = "/data/app/el1/bundle/public/"; + std::string destapplicationsPath = rootPath + "/data/accounts/account_0/applications/"; + DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destapplicationsPath.c_str()); + + // need permission check for system app here + std::string destbundlesPath = rootPath + "/data/bundles/"; + DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destbundlesPath.c_str()); + } + + std::string orimntHmdfsPath = "/mnt/hmdfs/"; + std::string destmntHmdfsPath = rootPath + orimntHmdfsPath; + DoAppSandboxMountOnce(orimntHmdfsPath.c_str(), destmntHmdfsPath.c_str()); + + // Add distributedfile module support, later reconstruct it + std::string oriDistributedPath = "/mnt/hmdfs/" + currentUserId + "/account/merge_view/data/" + bundleName; + std::string destDistributedPath = rootPath + "/data/storage/el2/distributedfiles"; + DoAppSandboxMountOnce(oriDistributedPath.c_str(), destDistributedPath.c_str()); + + std::string oriDistributedGroupPath = "/mnt/hmdfs/" + currentUserId + "/non_account/merge_view/data/" + bundleName; + std::string destDistributedGroupPath = rootPath + "/data/storage/el2/auth_groups"; + DoAppSandboxMountOnce(oriDistributedGroupPath.c_str(), destDistributedGroupPath.c_str()); + + // do nweb adaption + std::string orinwebPath = "/data/app/el1/bundle/public/com.ohos.nweb"; + std::string destnwebPath = destInstallPath + "/nweb"; + chmod(destnwebPath.c_str(), NWEB_FILE_MODE); + DoAppSandboxMountOnce(orinwebPath.c_str(), destnwebPath.c_str()); + + // do systemres adaption + std::string oriSysresPath = "/data/app/el1/bundle/public/ohos.global.systemres"; + std::string destSysresPath = destInstallPath + "/ohos.global.systemres"; + chmod(destSysresPath.c_str(), NWEB_FILE_MODE); + DoAppSandboxMountOnce(oriSysresPath.c_str(), destSysresPath.c_str()); + + if (bundleName.find("medialibrary") != std::string::npos) { + std::string oriMediaPath = "/storage/media/" + currentUserId; + std::string destMediaPath = rootPath + "/storage/media"; + DoAppSandboxMountOnce(oriMediaPath.c_str(), destMediaPath.c_str()); + } + + return 0; +} + +static void DoAppSandboxMkdir(const std::string &sandboxPackagePath, const AppParameter &appProperty) +{ + std::vector mkdirInfo; + std::string dirPath; + + mkdirInfo.push_back("/mnt/"); + mkdirInfo.push_back("/mnt/hmdfs/"); + mkdirInfo.push_back("/data/"); + mkdirInfo.push_back("/storage/"); + mkdirInfo.push_back("/storage/media"); + mkdirInfo.push_back("/data/storage"); + // to create /mnt/sandbox//data/storage/el1 related path, later should delete this code. + mkdirInfo.push_back("/data/storage/el1"); + mkdirInfo.push_back("/data/storage/el1/bundle"); + mkdirInfo.push_back("/data/storage/el1/base"); + mkdirInfo.push_back("/data/storage/el1/database"); + mkdirInfo.push_back("/data/storage/el2"); + mkdirInfo.push_back("/data/storage/el2/base"); + mkdirInfo.push_back("/data/storage/el2/database"); + mkdirInfo.push_back("/data/storage/el2/distributedfiles"); + mkdirInfo.push_back("/data/storage/el2/auth_groups"); + // create applications folder for compatibility purpose + mkdirInfo.push_back("/data/accounts"); + mkdirInfo.push_back("/data/accounts/account_0"); + mkdirInfo.push_back("/data/accounts/account_0/applications/"); + mkdirInfo.push_back("/data/bundles/"); + + for (size_t i = 0; i < mkdirInfo.size(); i++) { + dirPath = sandboxPackagePath + mkdirInfo[i]; + mkdir(dirPath.c_str(), FILE_MODE); + } +} + +static int32_t DoSandboxRootFolderCreateAdapt(const std::string &sandboxPackagePath) +{ + int rc = mount(nullptr, "/", nullptr, MS_REC | MS_SLAVE, nullptr); + if (rc) { + APPSPAWN_LOGE("set propagation slave failed"); + return rc; + } + + // bind mount "/" to /mnt/sandbox/ path + // rootfs: to do more resources bind mount here to get more strict resources constraints + rc = mount("/", sandboxPackagePath.c_str(), nullptr, MS_BIND | MS_REC, nullptr); + if (rc) { + APPSPAWN_LOGE("mount bind / failed"); + return rc; + } + + return 0; +} + +static int32_t DoSandboxRootFolderCreate(const std::string &sandboxPackagePath) +{ + int rc = mount(nullptr, "/", nullptr, MS_REC | MS_SLAVE, nullptr); + if (rc) { + return rc; + } + + // bind mount sandboxPackagePath to make it a mount point for pivot_root syscall + DoAppSandboxMountOnce(sandboxPackagePath.c_str(), sandboxPackagePath.c_str()); + + // do /mnt/sandbox/ path mkdir + std::map mountMap; + std::vector vecInfo; + std::string tmpDir = ""; + + vecInfo.push_back("/config"); + vecInfo.push_back("/dev"); + vecInfo.push_back("/proc"); + vecInfo.push_back("/sys"); + vecInfo.push_back("/sys_prod"); + vecInfo.push_back("/system"); + + for (size_t i = 0; i < vecInfo.size(); i++) { + tmpDir = sandboxPackagePath + vecInfo[i]; + mkdir(tmpDir.c_str(), FILE_MODE); + mountMap[vecInfo[i]] = tmpDir; + } + + // bind mount root folder to /mnt/sandbox/ path + std::map::iterator iter; + for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) { + rc = DoAppSandboxMountOnce(iter->first.c_str(), iter->second.c_str()); + if (rc) { + APPSPAWN_LOGE("move root folder failed, %s", sandboxPackagePath.c_str()); + } + } + + // to create symlink at /mnt/sandbox/ path + // bin -> /system/bin + // d -> /sys/kernel/debug + // etc -> /system/etc + // init -> /system/bin/init + // lib -> /system/lib + // sdcard -> /storage/self/primary + std::map symlinkMap; + symlinkMap["/system/bin"] = sandboxPackagePath + "/bin"; + symlinkMap["/sys/kernel/debug"] = sandboxPackagePath + "/d"; + symlinkMap["/system/etc"] = sandboxPackagePath + "/etc"; + symlinkMap["/system/bin/init"] = sandboxPackagePath + "/init"; +#ifdef __aarch64__ + symlinkMap["/system/lib64"] = sandboxPackagePath + "/lib64"; +#else + symlinkMap["/system/lib"] = sandboxPackagePath + "/lib"; +#endif + + for (iter = symlinkMap.begin(); iter != symlinkMap.end(); ++iter) { + symlink(iter->first.c_str(), iter->second.c_str()); + } + return 0; +} + +static void MatchSandbox(AppSpawnClientExt *appProperty) +{ + if (appProperty == nullptr) { + return; + } + if (strcmp("system_basic", appProperty->property.apl) == 0) { + EnterSandbox("priv-app"); + } else if (strcmp("normal", appProperty->property.apl) == 0) { + EnterSandbox("app"); + } else if (strcmp("system_core ", appProperty->property.apl) == 0) { + EnterSandbox("app"); + } else { + APPSPAWN_LOGE("AppSpawnServer::Failed to match appspawn sandbox %s", appProperty->property.apl); + EnterSandbox("app"); + } +} + +int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + int rc = 0; + APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + MatchSandbox(appProperty); + // create /mnt/sandbox/ path�?later put it to rootfs module + std::string sandboxPackagePath = "/"; + sandboxPackagePath += appProperty->property.bundleName; + mkdir(sandboxPackagePath.c_str(), FILE_MODE); + + // add pid to a new mnt namespace + rc = unshare(CLONE_NEWNS); + if (rc) { + APPSPAWN_LOGE("unshare failed, packagename is %s", appProperty->property.processName); + return rc; + } + + // to make wargnar work + if (access("/3rdmodem", F_OK) == 0) { + rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath); + } else { + rc = DoSandboxRootFolderCreate(sandboxPackagePath); + } + if (rc) { + APPSPAWN_LOGE("DoSandboxRootFolderCreate failed, %s", appProperty->property.processName); + return rc; + } + + // to create /mnt/sandbox//data/storage related path + DoAppSandboxMkdir(sandboxPackagePath, appProperty->property); + + rc = DoAppSandboxMount(appProperty->property, sandboxPackagePath); + if (rc) { + APPSPAWN_LOGE("DoAppSandboxMount failed, packagename is %s", appProperty->property.processName); + return rc; + } + + rc = DoAppSandboxMountCustomized(appProperty->property, sandboxPackagePath); + if (rc) { + APPSPAWN_LOGE("DoAppSandboxMountCustomized failed, packagename is %s", appProperty->property.processName); + return rc; + } + + rc = chdir(sandboxPackagePath.c_str()); + if (rc) { + APPSPAWN_LOGE("chdir failed, packagename is %s, path is %s", \ + appProperty->property.processName, sandboxPackagePath.c_str()); + return rc; + } + + rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str()); + if (rc) { + APPSPAWN_LOGE("pivot root failed, packagename is %s, errno is %d", \ + appProperty->property.processName, errno); + return rc; + } + + rc = umount2(".", MNT_DETACH); + if (rc) { + APPSPAWN_LOGE("MNT_DETACH failed, packagename is %s", appProperty->property.processName); + return rc; + } + return 0; +} diff --git a/appspawn.gni b/appspawn.gni index 50676bb5..4dc58471 100644 --- a/appspawn.gni +++ b/appspawn.gni @@ -12,8 +12,8 @@ # limitations under the License. appspawn_path = "//base/startup/appspawn_standard" +appexecfwk_path = "//foundation/appexecfwk/standard" aafwk_path = "//foundation/aafwk/standard" -communication_path = "//foundation/communication/ipc" subsystem_name = "startup" part_name = "appspawn" module_output_path = "${part_name}/appspawn_l2" diff --git a/bundle.json b/bundle.json index f7b6d593..18ac474a 100644 --- a/bundle.json +++ b/bundle.json @@ -37,7 +37,6 @@ "//base/startup/appspawn_standard:appspawn", "//base/startup/appspawn_standard:appspawn.rc", "//base/startup/appspawn_standard:appspawn_server", - "//base/startup/appspawn_standard:appspawntools", "//base/startup/appspawn_standard:nweb", "//base/startup/appspawn_standard/interfaces/innerkits:appspawn_socket_client" ], diff --git a/common/appspawn_server.c b/common/appspawn_server.c new file mode 100644 index 00000000..775da70c --- /dev/null +++ b/common/appspawn_server.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_server.h" + +#include +#include +#include +#ifdef OHOS_DEBUG +#include +#endif // OHOS_DEBUG + +static int NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result) +{ + if (content->notifyResToParent != NULL) { + content->notifyResToParent(content, client, result); + } + return 0; +} + +int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen) +{ + APPSPAWN_LOGI("DoStartApp id %d longProcNameLen %u", client->id, longProcNameLen); + int32_t ret = 0; + if (content->setAppSandbox) { + ret = content->setAppSandbox(content, client); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to set app sandbox"); + } + if (content->setKeepCapabilities) { + ret = content->setKeepCapabilities(content, client); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to set KeepCapabilities"); + } + if (content->setProcessName) { + ret = content->setProcessName(content, client, longProcName, longProcNameLen); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to set setProcessName"); + } + + if (content->setUidGid) { + ret = content->setUidGid(content, client); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to setUidGid"); + } + if (content->setFileDescriptors) { + ret = content->setFileDescriptors(content, client); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to setFileDescriptors"); + } + if (content->setCapabilities) { + ret = content->setCapabilities(content, client); + APPSPAWN_CHECK(ret == 0, NotifyResToParent(content, client, ret); + return ret, "Failed to setCapabilities"); + } + // notify success to father process and start app process + NotifyResToParent(content, client, 0); + return 0; +} + +int AppSpawnProcessMsg(struct AppSpawnContent_ *content, AppSpawnClient *client, pid_t *childPid) +{ + APPSPAWN_CHECK(content != NULL, return -1, "Invalid content for appspawn"); + APPSPAWN_CHECK(client != NULL && childPid != NULL, return -1, "Invalid client for appspawn"); + APPSPAWN_LOGI("AppSpawnProcessMsg id %d 0x%x", client->id, client->flags); + + if (content->registerAppSandbox != NULL) { + content->registerAppSandbox(content, client); + } + + pid_t pid = fork(); + if (pid < 0) { + return -errno; + } else if (pid == 0) { +#ifdef OHOS_DEBUG + struct timespec tmStart = {0}; + GetCurTime(&tmStart); +#endif // OHOS_DEBUG + + // close socket id and signal for child + if (content->clearEnvironment != NULL) { + content->clearEnvironment(content, client); + } + if (content->setAppAccessToken != NULL) { + content->setAppAccessToken(content, client); + } + int ret = -1; + if (client->flags & APP_COLD_START) { + if (content->coldStartApp != NULL && content->coldStartApp(content, client) == 0) { + _exit(0x7f); // 0x7f user exit + return -1; + } else { + ret = DoStartApp(content, client, content->longProcName, content->longProcNameLen); + } + } else { + ret = DoStartApp(content, client, content->longProcName, content->longProcNameLen); + } +#ifdef OHOS_DEBUG + struct timespec tmEnd = {0}; + GetCurTime(&tmEnd); + // 1s = 1000000000ns + long timeUsed = (tmEnd.tv_sec - tmStart.tv_sec) * 1000000000L + (tmEnd.tv_nsec - tmStart.tv_nsec); + APPSPAWN_LOGI("App timeused %d %ld ns.", getpid(), timeUsed); +#endif // OHOS_DEBUG + if (ret == 0 && content->runChildProcessor != NULL) { + content->runChildProcessor(content, client); + } + APPSPAWN_LOGI("App exit %d.", getpid()); + _exit(0x7f); // 0x7f user exit + } + *childPid = pid; + return 0; +} + +#ifdef OHOS_DEBUG +void GetCurTime(struct timespec *tmCur) +{ + if (tmCur == NULL) { + return; + } + if (clock_gettime(CLOCK_REALTIME, tmCur) != 0) { + APPSPAWN_LOGE("[appspawn] invoke, get time failed! err %d", errno); + } +} +#endif // OHOS_DEBUG diff --git a/common/appspawn_server.h b/common/appspawn_server.h new file mode 100644 index 00000000..b94c42bf --- /dev/null +++ b/common/appspawn_server.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APPSPAWN_SERVER_H +#define APPSPAWN_SERVER_H +#include "beget_ext.h" + +#include +#include +#include +#include +#ifdef OHOS_DEBUG +#include +#endif // OHOS_DEBUG + +#ifdef __cplusplus +extern "C" { +#endif + +#define UNUSED(x) (void)(x) +#define APP_COLD_START 0x01 +#define ERR_PIPE_FAIL (-100) +#define MAX_LEN_SHORT_NAME 16 +#define WAIT_DELAY_US (100 * 1000) // 100ms +#define GID_USER_DATA_RW 1008 + +typedef struct AppSpawnClient_ { + uint32_t id; + int32_t flags; +} AppSpawnClient; + +#define MAX_SOCKEYT_NAME_LEN 128 +typedef struct AppSpawnContent_ { + char *longProcName; + uint32_t longProcNameLen; + + // system + void (*loadExtendLib)(struct AppSpawnContent_ *content); + void (*initAppSpawn)(struct AppSpawnContent_ *content); + void (*runAppSpawn)(struct AppSpawnContent_ *content, int argc, char *const argv[]); + + // for child + void (*clearEnvironment)(struct AppSpawnContent_ *content, AppSpawnClient *client); + void (*setAppAccessToken)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setAppSandbox)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setKeepCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setFileDescriptors)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setProcessName)(struct AppSpawnContent_ *content, AppSpawnClient *client, + char *longProcName, uint32_t longProcNameLen); + int (*setUidGid)(struct AppSpawnContent_ *content, AppSpawnClient *client); + int (*setCapabilities)(struct AppSpawnContent_ *content, AppSpawnClient *client); + + int (*notifyResToParent)(struct AppSpawnContent_ *content, AppSpawnClient *client, int result); + void (*runChildProcessor)(struct AppSpawnContent_ *content, AppSpawnClient *client); + + // for cold start + int (*coldStartApp)(struct AppSpawnContent_ *content, AppSpawnClient *client); + void (*registerAppSandbox)(struct AppSpawnContent_ *content, AppSpawnClient *client); +} AppSpawnContent; + +AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int cold); +int AppSpawnProcessMsg(struct AppSpawnContent_ *content, AppSpawnClient *client, pid_t *childPid); +int DoStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client, char *longProcName, uint32_t longProcNameLen); + +#ifdef OHOS_DEBUG +void GetCurTime(struct timespec* tmCur); +#endif + +typedef enum { + DEBUG = 0, + INFO, + WARN, + ERROR, + FATAL, +} AppspawnLogLevel; + +void AppspawnLogPrint(AppspawnLogLevel logLevel, const char *file, int line, const char *fmt, ...); + +#ifndef FILE_NAME +#define FILE_NAME (strrchr((__FILE__), '/') ? strrchr((__FILE__), '/') + 1 : (__FILE__)) +#endif + +#define UNUSED(x) (void)(x) + +#ifndef APPSPAWN_LABEL +#define APPSPAWN_LABEL "APPSPAWN" +#endif +#define APPSPAWN_DOMAIN (BASE_DOMAIN + 0x11) + +#define APPSPAWN_LOGI(fmt, ...) STARTUP_LOGI(APPSPAWN_DOMAIN, APPSPAWN_LABEL, fmt, ##__VA_ARGS__) +#define APPSPAWN_LOGE(fmt, ...) STARTUP_LOGE(APPSPAWN_DOMAIN, APPSPAWN_LABEL, fmt, ##__VA_ARGS__) +#define APPSPAWN_LOGV(fmt, ...) STARTUP_LOGV(APPSPAWN_DOMAIN, APPSPAWN_LABEL, fmt, ##__VA_ARGS__) +#define APPSPAWN_LOGW(fmt, ...) STARTUP_LOGW(APPSPAWN_DOMAIN, APPSPAWN_LABEL, fmt, ##__VA_ARGS__) + +#define APPSPAWN_CHECK(retCode, exper, ...) \ + if (!(retCode)) { \ + APPSPAWN_LOGE(__VA_ARGS__); \ + exper; \ + } + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_SERVER_H diff --git a/interfaces/innerkits/BUILD.gn b/interfaces/innerkits/BUILD.gn index e710eb6d..8d6c1072 100644 --- a/interfaces/innerkits/BUILD.gn +++ b/interfaces/innerkits/BUILD.gn @@ -21,10 +21,10 @@ config("exported_header_files") { ohos_static_library("appspawn_socket_client") { sources = [ - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/client_socket.cpp", + "client/appspawn_socket.cpp", + "client/client_socket.cpp", ] - include_dirs = [ "${appspawn_path}/include" ] + include_dirs = [ "include" ] public_configs = [ ":exported_header_files" ] deps = [ "//utils/native/base:utils" ] external_deps = [ "hiviewdfx_hilog_native:libhilog" ] diff --git a/src/socket/appspawn_socket.cpp b/interfaces/innerkits/client/appspawn_socket.cpp similarity index 97% rename from src/socket/appspawn_socket.cpp rename to interfaces/innerkits/client/appspawn_socket.cpp index 1ba2f460..b1521f0b 100644 --- a/src/socket/appspawn_socket.cpp +++ b/interfaces/innerkits/client/appspawn_socket.cpp @@ -90,7 +90,7 @@ int AppSpawnSocket::PackSocketAddr() int AppSpawnSocket::CreateSocket() { - int socketFd = socket(AF_LOCAL, SOCK_SEQPACKET, 0); + int socketFd = socket(AF_UNIX, SOCK_STREAM, 0); // SOCK_SEQPACKET if (socketFd < 0) { HiLog::Error(LABEL, "Failed to create socket: %{public}d", errno); return (-errno); @@ -123,7 +123,7 @@ int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len) ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len)); if (rLen < 0) { - HiLog::Error(LABEL, "Read message from fd %{public}d error %zd: %{public}d", socketFd, rLen, errno); + HiLog::Error(LABEL, "Read message from fd %{public}d error %{public}zd: %{public}d", socketFd, rLen, errno); return -EFAULT; } diff --git a/src/socket/client_socket.cpp b/interfaces/innerkits/client/client_socket.cpp similarity index 100% rename from src/socket/client_socket.cpp rename to interfaces/innerkits/client/client_socket.cpp diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h new file mode 100644 index 00000000..4a325f65 --- /dev/null +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APPSPAWN_MSG_H +#define APPSPAWN_MSG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __MUSL__ +#define SOCKET_DIR "/dev/unix/socket/" +#else +#define SOCKET_DIR "/dev/socket/" +#endif + +#ifdef NWEB_SPAWN +#define APPSPAWN_SOCKET_NAME "NWebSpawn" +#else +#define APPSPAWN_SOCKET_NAME "AppSpawn" +#endif + +enum AppType { + APP_TYPE_DEFAULT = 0, // JavaScript app + APP_TYPE_NATIVE // Native C++ app +}; + +enum AppOperateCode { + DEFAULT = 0, + GET_RENDER_TERMINATION_STATUS, +}; + +#define APP_MSG_MAX_SIZE 4096 // appspawn message max size +#define APP_LEN_PROC_NAME 256 // process name length +#define APP_LEN_BUNDLE_NAME 256 // bundle name length +#define APP_LEN_SO_PATH 256 // load so lib +#define APP_MAX_GIDS 64 +#define APP_APL_MAX_LEN 32 +#define APP_RENDER_CMD_MAX_LEN 1024 +#define APP_COLD_BOOT 0x01 +#define BITLEN32 32 +#define FDLEN2 2 +#define FD_INIT_VALUE 0 + +typedef struct AppParameter_ { + uint32_t uid; // the UNIX uid that the child process setuid() to after fork() + uint32_t gid; // the UNIX gid that the child process setgid() to after fork() + uint32_t gidTable[APP_MAX_GIDS]; // a list of UNIX gids that the child process setgroups() to after fork() + uint32_t gidCount; // the size of gidTable + char processName[APP_LEN_PROC_NAME]; // process name + char bundleName[APP_LEN_BUNDLE_NAME]; // bundle name + char soPath[APP_LEN_SO_PATH]; // so lib path + uint32_t accessTokenId; + char apl[APP_APL_MAX_LEN]; + char renderCmd[APP_RENDER_CMD_MAX_LEN]; + uint32_t flags; + int32_t pid; // query render process exited status by render process pid + AppOperateCode code; +} AppParameter; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mock/include/main_thread.h b/interfaces/innerkits/include/appspawn_service.h similarity index 56% rename from test/mock/include/main_thread.h rename to interfaces/innerkits/include/appspawn_service.h index a0024c4d..16068f38 100644 --- a/test/mock/include/main_thread.h +++ b/interfaces/innerkits/include/appspawn_service.h @@ -4,7 +4,7 @@ * 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 + * 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, @@ -12,19 +12,26 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#ifndef BASE_STARTUP_APPSPAWN_SERVICE_H +#define BASE_STARTUP_APPSPAWN_SERVICE_H -#ifndef FOUNDATION_APPEXECFWK_MAIN_THREAD_H -#define FOUNDATION_APPEXECFWK_MAIN_THREAD_H +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ -namespace OHOS { -namespace AppExecFwk { -class MainThread { -public: - MainThread() = default; - virtual ~MainThread() = default; +#define APPSPAWN_SERVICE_NAME "appspawn" - static void Start(); +enum APPSPAWN_FUNCID { + ID_CALL_CREATE_SERVICE = 0, + ID_CALL_BUT }; -} // namespace AppExecFwk -} // namespace OHOS -#endif // MOCK_FOUNDATION_APPEXECFWK_MAIN_THREAD_H + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_APPSPAWN_SERVICE_H \ No newline at end of file diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h old mode 100755 new mode 100644 index 00f8b99d..0a839117 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -17,6 +17,7 @@ #define APPSPAWN_SOCKET_CLIENT_H #include "appspawn_socket.h" +#include "appspawn_msg.h" #include "nocopyable.h" namespace OHOS { @@ -83,36 +84,16 @@ public: APP_TYPE_NATIVE // Native C++ app }; - static constexpr int APPSPAWN_MSG_MAX_SIZE = 4096; // appspawn message max size - static constexpr int LEN_PROC_NAME = 256; // process name length - static constexpr int LEN_BUNDLE_NAME = 256; // bundle name length - static constexpr int LEN_SO_PATH = 256; // load so lib - static constexpr int MAX_GIDS = 64; - static constexpr int APL_MAX_LEN = 32; - static constexpr int RENDER_CMD_MAX_LEN = 1024; - static constexpr int APPSPAWN_COLD_BOOT = 0x01; - - enum AppOperateCode { - DEFAULT = 0, - GET_RENDER_TERMINATION_STATUS, - }; - - struct AppProperty { - uint32_t uid; // the UNIX uid that the child process setuid() to after fork() - uint32_t gid; // the UNIX gid that the child process setgid() to after fork() - uint32_t gidTable[MAX_GIDS]; // a list of UNIX gids that the child process setgroups() to after fork() - uint32_t gidCount; // the size of gidTable - char processName[LEN_PROC_NAME]; // process name - char bundleName[LEN_BUNDLE_NAME]; // bundle name - char soPath[LEN_SO_PATH]; // so lib path - uint32_t accessTokenId; - char apl[APL_MAX_LEN]; - char renderCmd[RENDER_CMD_MAX_LEN]; - uint32_t flags; - int32_t pid; // query render process exited status by render process pid - AppOperateCode code; - }; + static constexpr int APPSPAWN_MSG_MAX_SIZE = APP_MSG_MAX_SIZE; // appspawn message max size + static constexpr int LEN_PROC_NAME = APP_LEN_PROC_NAME; // process name length + static constexpr int LEN_BUNDLE_NAME = APP_LEN_BUNDLE_NAME; // bundle name length + static constexpr int LEN_SO_PATH = APP_LEN_SO_PATH; // load so lib + static constexpr int MAX_GIDS = APP_MAX_GIDS; + static constexpr int APL_MAX_LEN = APP_APL_MAX_LEN; + static constexpr int RENDER_CMD_MAX_LEN = APP_RENDER_CMD_MAX_LEN; + static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; + using AppProperty = AppParameter; private: /** * Connects a client socket. diff --git a/lite/BUILD.gn b/lite/BUILD.gn new file mode 100644 index 00000000..1fbe1d5c --- /dev/null +++ b/lite/BUILD.gn @@ -0,0 +1,83 @@ +# Copyright (c) 2021-2022 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import("//build/lite/config/component/lite_component.gni") +import("//build/lite/config/subsystem/aafwk/config.gni") + +lite_component("appspawn_lite") { + features = [ ":appspawn" ] +} + +# feature: appspawn +executable("appspawn") { + sources = [ + "../adapter/appspawn_log.cpp", + "../common/appspawn_server.c", + "appspawn_message.c", + "appspawn_process.c", + "appspawn_service.c", + "main.c", + ] + + ldflags = [ + "-lstdc++", + "-ldl", + ] + + cflags = [ + "-Wall", + "-Wno-format", + "-Wno-format-extra-args", + ] + + defines = [ "_GNU_SOURCE" ] + + include_dirs = [ + ".", + "../common", + "//base/startup/appspawn_standard/interfaces/innerkits/include", + "//base/startup/init_lite/interfaces/innerkits/include", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", + "${aafwk_lite_path}/interfaces/innerkits/abilitymgr_lite", + "//third_party/bounds_checking_function/include/", + "//third_party/cJSON", + "//utils/native/lite/include", + ] + + deps = [ + "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite", + "//base/startup/init_lite/interfaces/innerkits:libbegetutil", + "//build/lite/config/component/cJSON:cjson_shared", + "//foundation/communication/ipc_lite:liteipc_adapter", + "//foundation/distributedschedule/samgr_lite/samgr:samgr", + "//third_party/bounds_checking_function:libsec_shared", + "//utils/native/lite/kv_store:kv_store", + ] + + if (enable_ohos_appexecfwk_feature_ability == true) { + deps += [ + "//foundation/ace/ace_engine_lite/frameworks:ace_lite", + "//foundation/graphic/surface:lite_surface", + "//foundation/graphic/ui:lite_ui", + "//foundation/graphic/utils:lite_graphic_utils", + ] + } + + if (ohos_kernel_type == "liteos_a") { + deps += [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared" ] + } + + if (ohos_kernel_type == "linux") { + include_dirs += [] + } +} diff --git a/lite/appspawn_message.c b/lite/appspawn_message.c new file mode 100644 index 00000000..cad751cb --- /dev/null +++ b/lite/appspawn_message.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "appspawn_message.h" +#include +#include +#include +#include + +#ifdef __LINUX__ +#include +#else +#include +#endif + +#include "appspawn_server.h" +#include "cJSON.h" +#include "ohos_errno.h" +#include "securec.h" + +static const size_t MAX_BUNDLE_NAME_LEN = 127; +static const size_t MIN_BUNDLE_NAME_LEN = 7; +static const size_t MAX_IDENTITY_ID_LEN = 24; +static const size_t MIN_IDENTITY_ID_LEN = 1; +static const size_t MAX_CAPABILITY_COUNT = 10; + +void FreeMessageSt(MessageSt *targetSt) +{ + if (targetSt != NULL) { + if (targetSt->bundleName != NULL) { + free(targetSt->bundleName); + targetSt->bundleName = NULL; + } + + if (targetSt->identityID != NULL) { + free(targetSt->identityID); + targetSt->identityID = NULL; + } + + if (targetSt->caps != NULL) { + free(targetSt->caps); + targetSt->caps = NULL; + } + + targetSt->uID = -1; + targetSt->gID = -1; + targetSt->capsCnt = 0; + } +} + +static enum OHOSLiteErrorCode ReadStringItem(cJSON *strItem, char **buf, size_t maxLen, size_t minLen) +{ + if (strItem == NULL || !cJSON_IsString(strItem)) { + return EC_INVALID; + } + + char *strPtr = cJSON_GetStringValue(strItem); + if (strPtr == NULL) { + return EC_PROTOCOL; + } + + size_t strLength = strlen(strPtr); + if (strLength > maxLen || strLength < minLen) { + return EC_PROTOCOL; + } + + char *bufTmp = (char *)malloc(strLength + 1); + if (bufTmp == NULL) { + return EC_NOMEMORY; + } + + if (strLength > 0 && memcpy_s(bufTmp, strLength, strPtr, strLength) != EOK) { + free(bufTmp); + bufTmp = NULL; + return EC_FAILURE; + } + + bufTmp[strLength] = '\0'; + *buf = bufTmp; + return EC_SUCCESS; +} + +static double ReadNumberItem(cJSON *strItem) +{ + if (strItem == NULL || !cJSON_IsNumber(strItem)) { + return -1; + } + + return cJSON_GetNumberValue(strItem); +} + +static int GetCaps(const cJSON *curItem, MessageSt *msgSt) +{ + msgSt->capsCnt = 0; + msgSt->caps = NULL; + cJSON *capItem = cJSON_GetObjectItem(curItem, "capability"); + if (!cJSON_IsArray(capItem)) { + APPSPAWN_LOGE("[appspawn] GetCaps failed, no caps array found."); + return EC_INVALID; + } + + // caps array empty, means do not need any capability + int capsCnt = cJSON_GetArraySize(capItem); + if (capsCnt <= 0) { + return EC_SUCCESS; + } + + if (capsCnt > MAX_CAPABILITY_COUNT) { + APPSPAWN_LOGE("[appspawn] GetCaps, too many caps[cnt %d], max %d", + capsCnt, MAX_CAPABILITY_COUNT); + return EC_INVALID; + } + + msgSt->caps = (unsigned int *)malloc(sizeof(unsigned int) * capsCnt); + if (msgSt->caps == NULL) { + APPSPAWN_LOGE("[appspawn] GetCaps, malloc failed! capsCnt[cnt %d].", capsCnt); + return EC_NOMEMORY; + } + + for (int i = 0; i < capsCnt; ++i) { + cJSON *capJ = cJSON_GetArrayItem(capItem, i); + if (!cJSON_IsNumber(capJ) || cJSON_GetNumberValue(capJ) < 0) { + APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value detected!"); + free(msgSt->caps); + msgSt->caps = NULL; + return EC_INVALID; + } + msgSt->caps[i] = (unsigned int)cJSON_GetNumberValue(capJ); + if (msgSt->caps[i] > CAP_LAST_CAP) { + APPSPAWN_LOGE("[appspawn] GetCaps, invalid cap value %u detected!", \ + msgSt->caps[i]); + free(msgSt->caps); + msgSt->caps = NULL; + return EC_INVALID; + } + } + msgSt->capsCnt = capsCnt; + return EC_SUCCESS; +} + +int SplitMessage(const char *msg, unsigned int msgLen, MessageSt *msgSt) +{ + if (msgSt == NULL) { + return EC_INVALID; + } + + if (msg == NULL || msgLen == 0) { + FreeMessageSt(msgSt); + return EC_INVALID; + } + + cJSON *rootJ = cJSON_ParseWithLength(msg, msgLen); + if (rootJ == NULL) { + FreeMessageSt(msgSt); + return EC_PROTOCOL; + } + + cJSON *bundleNameItem = cJSON_GetObjectItem(rootJ, "bundleName"); + int ret = (int)ReadStringItem(bundleNameItem, &(msgSt->bundleName), MAX_BUNDLE_NAME_LEN, MIN_BUNDLE_NAME_LEN); + if (ret != EC_SUCCESS) { + FreeMessageSt(msgSt); + cJSON_Delete(rootJ); + return ret; + } + + cJSON *identityIDItem = cJSON_GetObjectItem(rootJ, "identityID"); + ret = (int)ReadStringItem(identityIDItem, &(msgSt->identityID), MAX_IDENTITY_ID_LEN, MIN_IDENTITY_ID_LEN); + if (ret != EC_SUCCESS) { + FreeMessageSt(msgSt); + cJSON_Delete(rootJ); + return ret; + } + + cJSON *uIDItem = cJSON_GetObjectItem(rootJ, "uID"); + cJSON *gIDItem = cJSON_GetObjectItem(rootJ, "gID"); + msgSt->uID = (int)ReadNumberItem(uIDItem); + msgSt->gID = (int)ReadNumberItem(gIDItem); + + ret = GetCaps(rootJ, msgSt); + if (ret != EC_SUCCESS) { + FreeMessageSt(msgSt); + cJSON_Delete(rootJ); + return ret; + } + + cJSON_Delete(rootJ); + + if (msgSt->uID <= 0 || msgSt->gID <= 0 || msgSt->uID == INT_MAX || msgSt->gID == INT_MAX) { + FreeMessageSt(msgSt); + return EC_PROTOCOL; + } + return EC_SUCCESS; +} diff --git a/lite/appspawn_message.h b/lite/appspawn_message.h new file mode 100644 index 00000000..e7a1ab2e --- /dev/null +++ b/lite/appspawn_message.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021-2022 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 BASE_STARTUP_APPSPAWN_MESSAGE_H +#define BASE_STARTUP_APPSPAWN_MESSAGE_H +#include +#include + +#include "appspawn_server.h" +#include "appspawn_service.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +typedef struct { + char *bundleName; + char *identityID; + int uID; + int gID; + unsigned int *caps; + unsigned int capsCnt; +} MessageSt; + +typedef struct { + AppSpawnClient client; + MessageSt message; +} AppSpawnClientLite; + +typedef struct { + AppSpawnContent content; +} AppSpawnContentLite; + +void SetContentFunction(AppSpawnContent *content); +int SplitMessage(const char *msg, unsigned int msgLen, MessageSt *msgSt); +void FreeMessageSt(MessageSt *targetSt); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif + +#endif // BASE_STARTUP_APPSPAWN_SERVICE_H diff --git a/lite/appspawn_process.c b/lite/appspawn_process.c new file mode 100644 index 00000000..46802eaf --- /dev/null +++ b/lite/appspawn_process.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#ifdef __LINUX__ +#include +#include +#include +#include +#else +#include +#endif // __LINUX__ + +#include "ability_main.h" +#include "appspawn_message.h" +#include "appspawn_server.h" +#include "appspawn_service.h" +#include "securec.h" + +#define DEFAULT_UMASK 022 +#define CAP_NUM 2 +#define ENV_TITLE "LD_LIBRARY_PATH=" +#define UPPER_BOUND_GID 999 +#define LOWER_BOUND_GID 100 +#define GRP_NUM 2 +#define DEVMGR_GRP 99 + +static int SetAmbientCapability(int cap) +{ +#ifdef __LINUX__ + if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, cap, 0, 0)) { + printf("[Init] prctl PR_CAP_AMBIENT failed\n"); + return -1; + } +#endif + return 0; +} + +static int SetCapability(unsigned int capsCnt, const unsigned int *caps) +{ + struct __user_cap_header_struct capHeader; + capHeader.version = _LINUX_CAPABILITY_VERSION_3; + capHeader.pid = 0; + + // common user, clear all caps + struct __user_cap_data_struct capData[CAP_NUM] = {0}; + for (unsigned int i = 0; i < capsCnt; ++i) { + capData[CAP_TO_INDEX(caps[i])].effective |= CAP_TO_MASK(caps[i]); + capData[CAP_TO_INDEX(caps[i])].permitted |= CAP_TO_MASK(caps[i]); + capData[CAP_TO_INDEX(caps[i])].inheritable |= CAP_TO_MASK(caps[i]); + } + + if (capset(&capHeader, capData) != 0) { + APPSPAWN_LOGE("[appspawn] capset failed, err: %d.", errno); + return -1; + } + for (unsigned int i = 0; i < capsCnt; ++i) { + if (SetAmbientCapability(caps[i]) != 0) { + APPSPAWN_LOGE("[appspawn] SetAmbientCapability failed, err: %d.", errno); + return -1; + } + } + return 0; +} + +static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client, + char *longProcName, uint32_t longProcNameLen) +{ + AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; + return prctl(PR_SET_NAME, appProperty->message.bundleName); +} + +static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + APPSPAWN_LOGE("SetKeepCapabilities"); +#ifdef __LINUX__ + if (prctl(PR_SET_SECUREBITS, SECBIT_NO_SETUID_FIXUP | SECBIT_NO_SETUID_FIXUP_LOCKED)) { + printf("prctl failed\n"); + return -1; + } +#endif + return 0; +} + +static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; + APPSPAWN_LOGE("SetUidGid %d %d", appProperty->message.uID, appProperty->message.gID); + if (setgid(appProperty->message.gID) != 0) { + APPSPAWN_LOGE("[appspawn] setgid failed, gID %u, err: %d.", appProperty->message.gID, errno); + return -1; + } + + if (setuid(appProperty->message.uID) != 0) { + APPSPAWN_LOGE("[appspawn] setuid failed, uID %u, err: %d.", appProperty->message.uID, errno); + return -1; + } + gid_t groups[GRP_NUM]; + // add device groups for system app + if (appProperty->message.gID >= LOWER_BOUND_GID && appProperty->message.gID <= UPPER_BOUND_GID) { + groups[0] = appProperty->message.gID; + groups[1] = DEVMGR_GRP; + if (setgroups(GRP_NUM, groups)) { + APPSPAWN_LOGE("[appspawn] setgroups failed, uID %u, err: %d.", appProperty->message.uID, errno); + return -1; + } + } + + // umask call always succeeds and return the previous mask value which is not needed here + (void)umask(DEFAULT_UMASK); + return 0; +} + +static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; + APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt); + // set rlimit +#ifdef __LINUX__ + static const rlim_t DEFAULT_RLIMIT = 40; + struct rlimit rlim = {0}; + rlim.rlim_cur = DEFAULT_RLIMIT; + rlim.rlim_max = DEFAULT_RLIMIT; + if (setrlimit(RLIMIT_NICE, &rlim) != 0) { + APPSPAWN_LOGE("[appspawn] setrlimit failed, err: %d.", errno); + return -1; + } + + unsigned int tmpCaps[] = {17}; // 17 means CAP_SYS_RAWIO + unsigned int tmpsCapCnt = sizeof(tmpCaps) / sizeof(tmpCaps[0]); + if (SetCapability(tmpsCapCnt, tmpCaps) != 0) { + APPSPAWN_LOGE("[appspawn] setrlimit failed, err: %d.", errno); + return -1; + } +#else + if (SetCapability(appProperty->message.capsCnt, appProperty->message.caps) != 0) { + APPSPAWN_LOGE("[appspawn] SetCapability failed, err: %d.", errno); + return -1; + } +#endif // __LINUX__ + APPSPAWN_LOGE("SetCapabilities appProperty->message.capsCnt %d", appProperty->message.capsCnt); + return 0; +} + +static void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) +{ + APPSPAWN_LOGI("AbilityMain"); + AppSpawnClientLite *appProperty = (AppSpawnClientLite *)client; + APPSPAWN_LOGI("[appspawn] invoke, msg<%s,%s,%d,%d>", + appProperty->message.bundleName, appProperty->message.identityID, appProperty->message.uID, + appProperty->message.gID); + + if (AbilityMain(appProperty->message.identityID) != 0) { + APPSPAWN_LOGE("[appspawn] AbilityMain execute failed, pid %d.", getpid()); + exit(0x7f); // 0x7f: user specified + } +} + +void SetContentFunction(AppSpawnContent *content) +{ + APPSPAWN_LOGI("SetContentFunction"); + content->setProcessName = SetProcessName; + content->setKeepCapabilities = SetKeepCapabilities; + content->setUidGid = SetUidGid; + content->setCapabilities = SetCapabilities; + content->runChildProcessor = RunChildProcessor; + + content->setFileDescriptors = NULL; + content->setAppSandbox = NULL; + content->setAppAccessToken = NULL; + content->notifyResToParent = NULL; + content->loadExtendLib = NULL; + content->initAppSpawn = NULL; + content->runAppSpawn = NULL; + content->clearEnvironment = NULL; +} diff --git a/lite/appspawn_service.c b/lite/appspawn_service.c new file mode 100644 index 00000000..4fa6ec3f --- /dev/null +++ b/lite/appspawn_service.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2021-2022 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. + */ + +#ifdef OHOS_DEBUG +#include +#include +#endif // OHOS_DEBUG + +#include "appspawn_message.h" +#include "appspawn_server.h" +#include "iproxy_server.h" +#include "iunknown.h" +#include "liteipc_adapter.h" +#include "message.h" +#include "ohos_errno.h" +#include "ohos_init.h" +#include "samgr_lite.h" +#include "service.h" + +static const int INVALID_PID = -1; +static const int CLIENT_ID = 100; + +typedef struct AppSpawnFeatureApi { + INHERIT_SERVER_IPROXY; +} AppSpawnFeatureApi; + +typedef struct AppSpawnService { + INHERIT_SERVICE; + INHERIT_IUNKNOWNENTRY(AppSpawnFeatureApi); + Identity identity; +} AppSpawnService; + +static const char *GetName(Service *service) +{ + (void)service; + APPSPAWN_LOGI("[appspawn] get service name %s.", APPSPAWN_SERVICE_NAME); + return APPSPAWN_SERVICE_NAME; +} + +static BOOL Initialize(Service *service, Identity identity) +{ + if (service == NULL) { + APPSPAWN_LOGE("[appspawn] initialize, service NULL!"); + return FALSE; + } + + AppSpawnService *spawnService = (AppSpawnService *)service; + spawnService->identity = identity; + + APPSPAWN_LOGI("[appspawn] initialize, identity<%d, %d, %p>", \ + identity.serviceId, identity.featureId, identity.queueId); + return TRUE; +} + +static BOOL MessageHandle(Service *service, Request *msg) +{ + (void)service; + (void)msg; + APPSPAWN_LOGE("[appspawn] message handle not support yet!"); + return FALSE; +} + +static TaskConfig GetTaskConfig(Service *service) +{ + (void)service; + TaskConfig config = {LEVEL_HIGH, PRI_BELOW_NORMAL, 0x800, 20, SHARED_TASK}; + return config; +} + +static int GetMessageSt(MessageSt *msgSt, IpcIo *req) +{ + if (msgSt == NULL || req == NULL) { + return EC_FAILURE; + } +#ifdef __LINUX__ + size_t len = 0; + char *str = IpcIoPopString(req, &len); + if (str == NULL || len == 0) { + APPSPAWN_LOGE("[appspawn] invoke, get data failed."); + return EC_FAILURE; + } + + int ret = SplitMessage(str, len, msgSt); // after split message, str no need to free(linux version) +#else + BuffPtr *dataPtr = IpcIoPopDataBuff(req); + if (dataPtr == NULL) { + APPSPAWN_LOGE("[appspawn] invoke, get data failed."); + return EC_FAILURE; + } + + int ret = SplitMessage((char *)dataPtr->buff, dataPtr->buffSz, msgSt); + + // release buffer + if (FreeBuffer(NULL, dataPtr->buff) != LITEIPC_OK) { + APPSPAWN_LOGE("[appspawn] invoke, free buffer failed!"); + } +#endif + return ret; +} + +static AppSpawnContentLite *g_appSpawnContentLite = NULL; +AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int cold) +{ + UNUSED(longProcName); + UNUSED(longProcNameLen); + APPSPAWN_LOGI("AppSpawnCreateContent %s", socketName); + AppSpawnContentLite *appSpawnContent = (AppSpawnContentLite *)malloc(sizeof(AppSpawnContentLite)); + APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn"); + appSpawnContent->content.longProcName = NULL; + appSpawnContent->content.longProcNameLen = NULL; + g_appSpawnContentLite = appSpawnContent; + return appSpawnContent; +} + +static int Invoke(IServerProxy *iProxy, int funcId, void *origin, IpcIo *req, IpcIo *reply) +{ +#ifdef OHOS_DEBUG + struct timespec tmStart = {0}; + GetCurTime(&tmStart); +#endif // OHOS_DEBUG + + (void)iProxy; + (void)origin; + + if (reply == NULL || funcId != ID_CALL_CREATE_SERVICE || req == NULL) { + APPSPAWN_LOGE("[appspawn] invoke, funcId %d invalid, reply %d.", funcId, INVALID_PID); + IpcIoPushInt64(reply, INVALID_PID); + return EC_BADPTR; + } + + AppSpawnClientLite *client = (AppSpawnClientLite *)malloc(sizeof(AppSpawnClientLite)); + APPSPAWN_CHECK(client != NULL, return -1, "malloc AppSpawnClientLite Failed"); + client->client.id = CLIENT_ID; + client->client.flags = 0; + if (GetMessageSt(&client->message, req) != EC_SUCCESS) { + APPSPAWN_LOGE("[appspawn] invoke, parse failed! reply %d.", INVALID_PID); + IpcIoPushInt64(reply, INVALID_PID); + return EC_FAILURE; + } + + APPSPAWN_LOGI("[appspawn] invoke, msg<%s,%s,%d,%d %d>", client->message.bundleName, client->message.identityID, + client->message.uID, client->message.gID, client->message.capsCnt); + + pid_t newPid = 0; + int ret = AppSpawnProcessMsg(g_appSpawnContentLite, &client->client, &newPid); + if (ret != 0) { + newPid = -1; + } + FreeMessageSt(&client->message); + IpcIoPushInt64(reply, newPid); + +#ifdef OHOS_DEBUG + struct timespec tmEnd = {0}; + GetCurTime(&tmEnd); + // 1s = 1000000000ns + long timeUsed = (tmEnd.tv_sec - tmStart.tv_sec) * 1000000000L + (tmEnd.tv_nsec - tmStart.tv_nsec); + APPSPAWN_LOGI("[appspawn] invoke, reply pid %d, timeused %ld ns.", newPid, timeUsed); +#else + APPSPAWN_LOGI("[appspawn] invoke, reply pid %d.", newPid); +#endif // OHOS_DEBUG + + return ((newPid > 0) ? EC_SUCCESS : EC_FAILURE); +} + +static AppSpawnService g_appSpawnService = { + .GetName = GetName, + .Initialize = Initialize, + .MessageHandle = MessageHandle, + .GetTaskConfig = GetTaskConfig, + SERVER_IPROXY_IMPL_BEGIN, + .Invoke = Invoke, + IPROXY_END, +}; + +void AppSpawnInit(void) +{ + if (SAMGR_GetInstance()->RegisterService((Service *)&g_appSpawnService) != TRUE) { + APPSPAWN_LOGE("[appspawn] register service failed!"); + return; + } + + APPSPAWN_LOGI("[appspawn] register service succeed. %p.", &g_appSpawnService); + + if (SAMGR_GetInstance()->RegisterDefaultFeatureApi(APPSPAWN_SERVICE_NAME, \ + GET_IUNKNOWN(g_appSpawnService)) != TRUE) { + (void)SAMGR_GetInstance()->UnregisterService(APPSPAWN_SERVICE_NAME); + APPSPAWN_LOGE("[appspawn] register featureapi failed!"); + return; + } + + APPSPAWN_LOGI("[appspawn] register featureapi succeed."); +} + +SYSEX_SERVICE_INIT(AppSpawnInit); diff --git a/lite/bundle.json b/lite/bundle.json new file mode 100644 index 00000000..e183e850 --- /dev/null +++ b/lite/bundle.json @@ -0,0 +1,44 @@ +{ + "name": "@ohos/startup_appspawn_lite", + "description": "lite app start manager", + "homePage": "https://gitee.com/openharmony", + "version": "3.1", + "license": "Apache License 2.0", + "repository": "https://gitee.com/openharmony/appspawn_standard", + "publishAs": "code-segment", + "segment": { + "destPath": "base/startup/appspawn_standard/lite" + }, + "dirs": {}, + "scripts": {}, + "component": { + "name": "appspawn_lite", + "subsystem": "startup", + "adapted_system_type": [ + "small" + ], + "rom": "26KB", + "ram": "~1.8M", + "deps": { + "components": [ + "hilog_lite", + "samgr_lite", + "ipc_lite", + "kv_store", + "aafwk_lite", + "ace_engine_lite", + "surface", + "ui" + ], + "third_party": [ + "cJSON", + "bounds_checking_function" + ] + }, + "build": { + "sub_component": [ + "//base/startup/appspawn_standard/lite:appspawn_lite" + ] + } + } +} \ No newline at end of file diff --git a/lite/main.c b/lite/main.c new file mode 100644 index 00000000..569096e8 --- /dev/null +++ b/lite/main.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include + +#include "samgr_lite.h" +#include "appspawn_server.h" +#include "appspawn_service.h" + +void __attribute__((weak)) HOS_SystemInit(void) +{ + SAMGR_Bootstrap(); + APPSPAWN_LOGI("[appspawn] HOS_SystemInit is called!"); +} + +static void SignalHandler(int sig) +{ + switch (sig) { + case SIGCHLD: { + pid_t sigPID; + int procStat = 0; + while (1) { + sigPID = waitpid(-1, &procStat, WNOHANG); + if (sigPID <= 0) { + break; + } + APPSPAWN_LOGE("SignalHandler sigPID %d.", sigPID); + } + break; + } + default: + break; + } +} + +void SignalRegist(void) +{ + struct sigaction act; + act.sa_handler = SignalHandler; + act.sa_flags = SA_RESTART; + if (sigfillset(&act.sa_mask) != 0) { + APPSPAWN_LOGE("[appspawn] sigfillset failed! err %d.", errno); + } + + if (sigaction(SIGCHLD, &act, NULL) != 0) { + APPSPAWN_LOGE("[appspawn] sigaction failed! err %d.", errno); + } +} + +int main(int argc, char * const argv[]) +{ + sleep(1); + APPSPAWN_LOGI("[appspawn] main, enter."); + + AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", NULL, 0, 0); + SetContentFunction(content); + // 1. ipc module init + HOS_SystemInit(); + + // 2. register signal for SIGCHLD + SignalRegist(); + + // 3. keep process alive + APPSPAWN_LOGI("[appspawn] main, entering wait."); + while (1) { + // pause only returns when a signal was caught and the signal-catching function returned. + // pause only returns -1, no need to process the return value. + (void)pause(); + } +} diff --git a/nwebspawn.cfg b/nwebspawn.cfg index 7e5dbc73..7046d9b2 100644 --- a/nwebspawn.cfg +++ b/nwebspawn.cfg @@ -5,7 +5,7 @@ "socket" : [{ "name" : "NWebSpawn", "family" : "AF_LOCAL", - "type" : "SOCK_SEQPACKET", + "type" : "SOCK_STREAM", "protocol" : "default", "permissions" : "0666", "uid" : "root", diff --git a/src/appspawn_msg_peer.cpp b/src/appspawn_msg_peer.cpp deleted file mode 100644 index 96f2460e..00000000 --- a/src/appspawn_msg_peer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "appspawn_msg_peer.h" - -#include - -#include "hilog/log.h" -#include "securec.h" - -namespace OHOS { -namespace AppSpawn { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnMain"}; - -AppSpawnMsgPeer::AppSpawnMsgPeer(const std::shared_ptr &socket, int connectFd) - : connectFd_(connectFd), socket_(socket) -{} - -AppSpawnMsgPeer::~AppSpawnMsgPeer() -{ - if ((socket_ != nullptr) && (connectFd_ >= 0)) { - socket_->CloseConnection(connectFd_); - } -} - -ClientSocket::AppProperty *AppSpawnMsgPeer::GetMsg() const -{ - return reinterpret_cast(buf_.get()); -} - -int AppSpawnMsgPeer::GetConnectFd() const -{ - return connectFd_; -} - -int AppSpawnMsgPeer::Response(pid_t pid) -{ - if ((socket_ == nullptr) || (connectFd_ < 0)) { - HiLog::Error(LABEL, "Invalid socket params: connectFd %{public}d", connectFd_); - return -EINVAL; - } - - if (socket_->WriteSocketMessage(connectFd_, &pid, sizeof(pid)) != sizeof(pid)) { - HiLog::Error(LABEL, "Failed to write message: connectFd %{public}d", connectFd_); - return (-errno); - } - - return 0; -} - -int AppSpawnMsgPeer::MsgPeer() -{ - if ((socket_ == nullptr) || (connectFd_ < 0)) { - HiLog::Error(LABEL, "Failed to init socket: connectFd %{public}d", connectFd_); - return -EINVAL; - } - - int32_t msgLen = sizeof(ClientSocket::AppProperty); - buf_ = std::make_unique(msgLen); - if (buf_ == nullptr) { - HiLog::Error(LABEL, "buf_ is null pointer!"); - return -EINVAL; - } - - int32_t rLen = 0; - - for (int8_t *offset = buf_.get(); msgLen > 0; offset += rLen, msgLen -= rLen) { - rLen = socket_->ReadSocketMessage(connectFd_, offset, msgLen); - if (rLen == 0) { - HiLog::Info(LABEL, "AppSpawnMsgPeer::MsgPeer ReadSocketMessage function value is 0."); - break; - } - - if ((rLen < 0) || (rLen > msgLen)) { - HiLog::Error(LABEL, "AppSpawnMsgPeer::Failed to read msg from socket %{public}d", connectFd_); - return -EINVAL; - } - } - - return 0; -} -} // namespace AppSpawn -} // namespace OHOS diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp deleted file mode 100755 index b5985dc2..00000000 --- a/src/appspawn_server.cpp +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "appspawn_server.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "errors.h" -#include "hilog/log.h" -#include "main_thread.h" -#include "securec.h" -#include "token_setproc.h" -#include "parameter.h" -#include "parameters.h" -#include "beget_ext.h" -#ifdef WITH_SELINUX -#include "hap_restorecon.h" -#endif - -#include -#include -#include -#include -#include - -constexpr static mode_t FILE_MODE = 0711; -constexpr static mode_t NWEB_FILE_MODE = 0511; - -#define APPSPAWN_LOGI(fmt, ...) STARTUP_LOGI(0, "APPSPAWN", fmt, ##__VA_ARGS__) -#define APPSPAWN_LOGE(fmt, ...) STARTUP_LOGE(0, "APPSPAWN", fmt, ##__VA_ARGS__) -#define GRAPHIC_PERMISSION_CHECK - -#ifdef NWEB_SPAWN -#define RENDER_PROCESS_MAX_NUM 16 -#define RENDER_PROCESS_ARRAY_IDLE 0 - -typedef struct { - int32_t pid; - int exitStatus; -} RenderProcessNode; - -static RenderProcessNode g_renderProcessArray[RENDER_PROCESS_MAX_NUM]; -#endif - -namespace OHOS { -namespace AppSpawn { -namespace { -constexpr int32_t ERR_PIPE_FAIL = -100; -constexpr int32_t MAX_LEN_SHORT_NAME = 16; -constexpr int32_t WAIT_DELAY_US = 100 * 1000; // 100ms -constexpr int32_t GID_USER_DATA_RW = 1008; -constexpr int32_t MAX_GIDS = 64; -constexpr int32_t UID_BASE = 200000; -constexpr int32_t WAIT_PARAM_TIME = 5; - -constexpr std::string_view BUNDLE_NAME_MEDIA_LIBRARY("com.ohos.medialibrary.MediaLibraryDataA"); -constexpr std::string_view BUNDLE_NAME_SCANNER("com.ohos.medialibrary.MediaScannerAbilityA"); -constexpr std::string_view APL_SYSTEM_CORE("system_core"); -constexpr std::string_view APL_SYSTEM_BASIC("system_basic"); -} // namespace - -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnServer"}; - -#ifdef __cplusplus -extern "C" { -#endif - -static void SignalHandler([[maybe_unused]] int sig) -{ - pid_t pid; - int status; - - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { - APPSPAWN_LOGE("SignalHandler HandleSignal: %d, status: %d", pid, status); - } -} - -static void InstallSigHandler() -{ - struct sigaction sa = {}; - sa.sa_handler = SignalHandler; - int err = sigaction(SIGCHLD, &sa, nullptr); - if (err < 0) { - HiLog::Error(LABEL, "Error installing SIGCHLD handler: %{public}d", errno); - return; - } - - struct sigaction sah = {}; - sah.sa_handler = SIG_IGN; - err = sigaction(SIGHUP, &sah, nullptr); - if (err < 0) { - HiLog::Error(LABEL, "Error installing SIGHUP handler: %{public}d", errno); - } -} - -static void UninstallSigHandler() -{ - struct sigaction sa = {}; - sa.sa_handler = nullptr; - int err = sigaction(SIGCHLD, &sa, nullptr); - if (err < 0) { - HiLog::Error(LABEL, "Error uninstalling SIGCHLD handler: %{public}d", errno); - } - - struct sigaction sah = {}; - sah.sa_handler = nullptr; - err = sigaction(SIGHUP, &sah, nullptr); - if (err < 0) { - HiLog::Error(LABEL, "Error uninstalling SIGHUP handler: %{public}d", errno); - } -} -#ifdef __cplusplus -} -#endif - -AppSpawnServer::AppSpawnServer(const std::string &socketName) -{ - socketName_ = socketName; - socket_ = std::make_shared(socketName_); - isRunning_ = true; -} - -void AppSpawnServer::MsgPeer(int connectFd) -{ - std::unique_ptr msgPeer = std::make_unique(socket_, connectFd); - if (msgPeer == nullptr || msgPeer->MsgPeer() != 0) { - HiLog::Error(LABEL, "Failed to listen connection %{public}d, %{public}d", connectFd, errno); - return; - } - - std::lock_guard lock(mut_); - appQueue_.push(std::move(msgPeer)); - dataCond_.notify_one(); -} - -void AppSpawnServer::ConnectionPeer() -{ - int connectFd; - - /* AppSpawn keeps receiving msg from AppMgr and never exits */ - while (isRunning_) { - connectFd = socket_->WaitForConnection(); - if (connectFd < 0) { - usleep(WAIT_DELAY_US); - HiLog::Info(LABEL, "AppSpawnServer::ConnectionPeer connectFd is %{public}d", connectFd); - continue; - } - - mut_.lock(); // Ensure that mutex in SaveConnection is unlocked before being forked - socket_->SaveConnection(connectFd); - mut_.unlock(); - std::thread(&AppSpawnServer::MsgPeer, this, connectFd).detach(); - } -} - -void AppSpawnServer::WaitRebootEvent() -{ - APPSPAWN_LOGI("wait 'startup.device.ctl' event"); - while (isRunning_) { - int ret = WaitParameter("startup.device.ctl", "stop", WAIT_PARAM_TIME); - if (ret == 0) { - std::lock_guard lock(mut_); - isStop_ = true; - dataCond_.notify_one(); - break; - } else { - std::string value = OHOS::system::GetParameter("startup.device.ctl", ""); - if (value == "stop") { - std::lock_guard lock(mut_); - isStop_ = true; - dataCond_.notify_one(); - break; - } - } - } -} - -#ifdef NWEB_SPAWN -static void DumpRenderProcessExitedArray() -{ - APPSPAWN_LOGI("dump render process exited array:"); - for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { - APPSPAWN_LOGI("[pid, exitedStatus] = [%d, %d]", - g_renderProcessArray[i].pid, g_renderProcessArray[i].exitStatus); - } -} - -static void RecordRenderProcessExitedStatus(pid_t pid, int status) -{ - int i = 0; - for (; i < RENDER_PROCESS_MAX_NUM; i++) { - if (g_renderProcessArray[i].pid == RENDER_PROCESS_ARRAY_IDLE) { - g_renderProcessArray[i].exitStatus = status; - g_renderProcessArray[i].pid = pid; - break; - } - } - if (i == RENDER_PROCESS_MAX_NUM) { - APPSPAWN_LOGE("no empty space in render process exited array"); - DumpRenderProcessExitedArray(); - } -} - -static int GetRenderProcessTerminationStatus(int32_t pid, int *status) -{ - if (status == nullptr) { - return -EINVAL; - } - - for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { - if (g_renderProcessArray[i].pid == pid) { - *status = g_renderProcessArray[i].exitStatus; - g_renderProcessArray[i].pid = RENDER_PROCESS_ARRAY_IDLE; - return 0; - } - } - APPSPAWN_LOGE("not find pid[%d] in render process exited arrary", pid); - DumpRenderProcessExitedArray(); - - return -EINVAL; -} -#endif - -void AppSpawnServer::HandleSignal() -{ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - sigprocmask(SIG_BLOCK, &mask, nullptr); - int signalFd = signalfd(-1, &mask, SFD_CLOEXEC); - if (signalFd < 0) { - APPSPAWN_LOGE("Error installing SIGHUP handler: %d", errno); - } - while (isRunning_) { - struct signalfd_siginfo fdsi; - ssize_t ret = read(signalFd, &fdsi, sizeof(fdsi)); - if (ret != sizeof(fdsi) || fdsi.ssi_signo != SIGCHLD) { - continue; - } - pid_t pid; - int status; - while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { -#ifdef NWEB_SPAWN - std::lock_guard lock(mut_); // to protect thread sync when access render process exited map - RecordRenderProcessExitedStatus(pid, status); -#endif - APPSPAWN_LOGE("HandleSignal: %d, status: %d", pid, status); - } - - std::lock_guard lock(mut_); - isChildDie_ = true; - childPid_ = fdsi.ssi_pid; - APPSPAWN_LOGI("exit app pid = %d", childPid_); - dataCond_.notify_one(); - } - close(signalFd); - signalFd = -1; -} - -void AppSpawnServer::LoadAceLib() -{ -#ifdef NWEB_SPAWN - const std::string LOAD_LIB_DIR = "/data/app/el1/bundle/public/com.ohos.nweb/libs/arm"; -#ifdef __MUSL__ - Dl_namespace dlns; - dlns_init(&dlns, "nweb_ns"); - dlns_create(&dlns, LOAD_LIB_DIR.c_str()); - void *handle = dlopen_ns(&dlns, "libweb_engine.so", RTLD_NOW | RTLD_GLOBAL); -#else - const std::string ENGINE_LIB_DIR = LOAD_LIB_DIR + "/libweb_engine.so"; - void *handle = dlopen(ENGINE_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL); -#endif - if (handle == nullptr) { - HiLog::Error(LABEL, "Fail to dlopen libweb_engine.so, [%{public}s]", dlerror()); - } else { - HiLog::Info(LABEL, "Success to dlopen libweb_engine.so"); - } -#ifdef __MUSL__ - nwebHandle = dlopen_ns(&dlns, "libnweb_render.so", RTLD_NOW | RTLD_GLOBAL); -#else - const std::string RENDER_LIB_DIR = LOAD_LIB_DIR + "/libnweb_render.so"; - nwebHandle = dlopen(RENDER_LIB_DIR.c_str(), RTLD_NOW | RTLD_GLOBAL); -#endif - if (nwebHandle == nullptr) { - HiLog::Error(LABEL, "Fail to dlopen libnweb_render.so, [%{public}s]", dlerror()); - } else { - HiLog::Info(LABEL, "Success to dlopen libnweb_render.so"); - } - -#else -#ifdef __aarch64__ - std::string acelibdir("/system/lib64/libace.z.so"); -#else - std::string acelibdir("/system/lib/libace.z.so"); -#endif - void *AceAbilityLib = nullptr; - HiLog::Info(LABEL, "MainThread::LoadAbilityLibrary. Start calling dlopen acelibdir."); - AceAbilityLib = dlopen(acelibdir.c_str(), RTLD_NOW | RTLD_GLOBAL); - if (AceAbilityLib == nullptr) { - HiLog::Error(LABEL, "Fail to dlopen %{public}s, [%{public}s]", acelibdir.c_str(), dlerror()); - } else { - HiLog::Info(LABEL, "Success to dlopen %{public}s", acelibdir.c_str()); - } - HiLog::Info(LABEL, "MainThread::LoadAbilityLibrary. End calling dlopen."); -#endif -} - -static void InitDebugParams(const ClientSocket::AppProperty *appProperty) -{ -#ifdef __aarch64__ - const char *debugSoPath = "/system/lib64/libhidebug.so"; -#else - const char *debugSoPath = "/system/lib/libhidebug.so"; -#endif - if (access(debugSoPath, F_OK) != 0) { - HiLog::Error(LABEL, "access failed, errno = %{public}d", errno); - return; - } - void* handle = dlopen(debugSoPath, RTLD_LAZY); - if (handle == nullptr) { - HiLog::Error(LABEL, "Failed to dlopen libhidebug.so, %{public}s", dlerror()); - return; - } - bool (* initParam)(const char *name); - initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam"); - if (initParam == nullptr) { - HiLog::Error(LABEL, "Failed to dlsym InitEnvironmentParam, %{public}s", dlerror()); - dlclose(handle); - return; - } - bool ret = (*initParam)(appProperty->processName); - if (!ret) { - HiLog::Error(LABEL, "init parameters failed."); - } - dlclose(handle); -} - -static void ClearEnvironment(void) -{ - sigset_t mask; - sigemptyset(&mask); - sigaddset(&mask, SIGCHLD); - sigprocmask(SIG_UNBLOCK, &mask, nullptr); - return; -} - -int AppSpawnServer::DoColdStartApp(ClientSocket::AppProperty *appProperty, int fd) -{ - APPSPAWN_LOGI("DoColdStartApp::appName %s", appProperty->processName); - std::vector extractedCmds; - extractedCmds.push_back(const_cast("/system/bin/appspawntools")); - std::string tmp = std::to_string(fd); - APPSPAWN_LOGI("DoColdStartApp::fd %d %s", fd, tmp.c_str()); - extractedCmds.push_back(const_cast(tmp.c_str())); - std::string uid = std::to_string(appProperty->uid); - APPSPAWN_LOGI("DoColdStartApp::uid %d gid %d %s", appProperty->uid, appProperty->gid, uid.c_str()); - extractedCmds.push_back(const_cast(uid.c_str())); - std::string gid = std::to_string(appProperty->gid); - extractedCmds.push_back(const_cast(gid.c_str())); - extractedCmds.push_back(const_cast(appProperty->processName)); - extractedCmds.push_back(const_cast(appProperty->bundleName)); - extractedCmds.push_back(const_cast(appProperty->soPath)); - std::string accessTokenId = std::to_string(appProperty->accessTokenId); - APPSPAWN_LOGI("DoColdStartApp::accessTokenId %d %s", appProperty->accessTokenId, accessTokenId.c_str()); - extractedCmds.push_back(const_cast(accessTokenId.c_str())); - extractedCmds.push_back(const_cast(appProperty->apl)); - APPSPAWN_LOGI("DoColdStartApp renderCmd %s", appProperty->renderCmd); - extractedCmds.push_back(const_cast(appProperty->renderCmd)); - std::string flags = std::to_string(appProperty->flags); - extractedCmds.push_back(const_cast(flags.c_str())); - std::string gidCount = std::to_string(appProperty->gidCount); - APPSPAWN_LOGI("DoColdStartApp gidCount %d %s", appProperty->gidCount, gidCount.c_str()); - extractedCmds.push_back(const_cast(gidCount.c_str())); - for (uint32_t i = 0; i < appProperty->gidCount; i++) { - extractedCmds.push_back(const_cast(std::string(std::to_string(appProperty->gidTable[i])).c_str())); - } - extractedCmds.push_back(nullptr); - APPSPAWN_LOGI("DoColdStartApp extractedCmds %d", extractedCmds.size()); - int ret = execv(extractedCmds[0], extractedCmds.data()); - if (ret) { - HiLog::Error(LABEL, "Failed to execv, errno = %{public}d", errno); - NotifyResToParentProc(fd, -1); - } - return 0; -} - -static int WaitChild(int fd, int pid, ClientSocket::AppProperty *appProperty) -{ - int result = ERR_OK; - fd_set rd; - struct timeval tv; - FD_ZERO(&rd); - FD_SET(fd, &rd); - tv.tv_sec = 1; - tv.tv_usec = 0; - int ret = select(fd + 1, &rd, nullptr, nullptr, &tv); - if (ret == 0) { // timeout - APPSPAWN_LOGI("Time out for child %s %d", appProperty->processName, pid); - result = ERR_OK; - } else if (ret == -1) { - APPSPAWN_LOGI("Error for child %s %d", appProperty->processName, pid); - result = ERR_OK; - } else { - ret = read(fd, &result, sizeof(result)); - } - APPSPAWN_LOGI("child process %s %s pid %d", - appProperty->processName, (result == ERR_OK) ? "success" : "fail", pid); - return (result == ERR_OK) ? 0 : result; -} - -int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, - ClientSocket::AppProperty *appProperty, int connectFd, pid_t &pid) -{ - if (!CheckAppProperty(appProperty)) { - return -EINVAL; - } - int32_t fd[FDLEN2] = {FD_INIT_VALUE, FD_INIT_VALUE}; - if (pipe(fd) == -1) { - HiLog::Error(LABEL, "create pipe fail, errno = %{public}d", errno); - return ERR_PIPE_FAIL; - } - fcntl(fd[0], F_SETFL, O_NDELAY); - - InstallSigHandler(); - pid = fork(); - if (pid < 0) { - HiLog::Error(LABEL, "AppSpawnServer::Failed to fork new process, errno = %{public}d", errno); - close(fd[0]); - close(fd[1]); - return -errno; - } else if (pid == 0) { - InitDebugParams(appProperty); - SpecialHandle(appProperty); - // close socket connection and peer socket in child process - if (socket_ != NULL) { - socket_->CloseConnection(connectFd); - socket_->CloseServerMonitor(); - } - close(fd[0]); // close read fd - ClearEnvironment(); - UninstallSigHandler(); - SetAppAccessToken(appProperty); - if ((appProperty->flags == ClientSocket::APPSPAWN_COLD_BOOT) && - OHOS::system::GetBoolParameter("appspawn.cold.boot", false)) { - DoColdStartApp(appProperty, fd[1]); - } else { - SetAppProcProperty(appProperty, longProcName, longProcNameLen, fd[1]); - } - _exit(0); - } - int ret = WaitChild(fd[0], pid, appProperty); - close(fd[0]); - close(fd[1]); - return ret; -} - -void AppSpawnServer::QuickExitMain() -{ -#ifndef TEST_EXIT - quick_exit(0); -#endif - return; -} - -void AppSpawnServer::ProcessAppSpawnMsg(char *longProcName, int64_t longProcNameLen, - const std::unique_ptr &msg) -{ - int connectFd = msg->GetConnectFd(); - ClientSocket::AppProperty *appProperty = msg->GetMsg(); -#ifdef NWEB_SPAWN - if (appProperty->code == ClientSocket::GET_RENDER_TERMINATION_STATUS) { - int exitStatus = 0; - int ret = GetRenderProcessTerminationStatus(appProperty->pid, &exitStatus); - if (ret) { - msg->Response(ret); - } else { - msg->Response(exitStatus); - } - APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s", - exitStatus, appProperty->pid, appProperty->uid, appProperty->processName, appProperty->bundleName); - return; - } -#endif - pid_t pid = 0; - int ret = StartApp(longProcName, longProcNameLen, appProperty, connectFd, pid); - if (ret) { - msg->Response(ret); - } else { - msg->Response(pid); - appMap_[pid] = appProperty->processName; - } - APPSPAWN_LOGI("AppSpawnServer::parent process create app finish, pid = %d uid %d %s %s", - pid, appProperty->uid, appProperty->processName, appProperty->bundleName); -} - -bool AppSpawnServer::ServerMain(char *longProcName, int64_t longProcNameLen) -{ - if (socket_->RegisterServerSocket() != 0) { - HiLog::Error(LABEL, "AppSpawnServer::Failed to register server socket"); - return false; - } - std::thread(&AppSpawnServer::ConnectionPeer, this).detach(); - LoadAceLib(); - - std::thread(&AppSpawnServer::WaitRebootEvent, this).detach(); - std::thread(&AppSpawnServer::HandleSignal, this).detach(); - while (isRunning_) { - std::unique_lock lock(mut_); - dataCond_.wait(lock, [this] { return !this->appQueue_.empty() || isStop_ || isChildDie_;}); - if (isStop_) { // finish - break; - } - if (isChildDie_) { // process child die - isChildDie_ = false; - auto iter = appMap_.find(childPid_); - if (iter != appMap_.end()) { - APPSPAWN_LOGI("delete pid=%d in appMap", iter->first); - appMap_.erase(iter); - } - } - if (this->appQueue_.empty()) { - continue; - } - std::unique_ptr msg = std::move(appQueue_.front()); - appQueue_.pop(); - int connectFd = msg->GetConnectFd(); - ProcessAppSpawnMsg(longProcName, longProcNameLen, msg); - socket_->CloseConnection(connectFd); // close socket connection - } - - while (appMap_.size() > 0) { - auto iter = appMap_.begin(); - APPSPAWN_LOGI("kill app, pid = %d, processName = %s", iter->first, iter->second.c_str()); - kill(iter->first, SIGKILL); - appMap_.erase(iter); - } - QuickExitMain(); - return false; -} - -int32_t AppSpawnServer::SetProcessName( - char *longProcName, int64_t longProcNameLen, const char *processName, int32_t len) -{ - if (longProcName == nullptr || processName == nullptr || len <= 0) { - HiLog::Error(LABEL, "process name is nullptr or length error"); - return -EINVAL; - } - - char shortName[MAX_LEN_SHORT_NAME]; - if (memset_s(shortName, sizeof(shortName), 0, sizeof(shortName)) != EOK) { - HiLog::Error(LABEL, "Failed to memset short name"); - return -EINVAL; - } - - // process short name max length 16 bytes. - if (len >= MAX_LEN_SHORT_NAME) { - if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, processName, MAX_LEN_SHORT_NAME - 1) != EOK) { - HiLog::Error(LABEL, "strncpy_s short name error: %{public}d", errno); - return -EINVAL; - } - } else { - if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, processName, len) != EOK) { - HiLog::Error(LABEL, "strncpy_s short name error: %{public}d", errno); - return -EINVAL; - } - } - - // set short name - if (prctl(PR_SET_NAME, shortName) == -1) { - HiLog::Error(LABEL, "prctl(PR_SET_NAME) error: %{public}d", errno); - return (-errno); - } - - // reset longProcName - if (memset_s(longProcName, static_cast(longProcNameLen), 0, static_cast(longProcNameLen)) != EOK) { - HiLog::Error(LABEL, "Failed to memset long process name"); - return -EINVAL; - } - - // set long process name - if (strncpy_s(longProcName, len, processName, len) != EOK) { - HiLog::Error(LABEL, "strncpy_s long name error: %{public}d", errno); - return -EINVAL; - } - - return ERR_OK; -} - -int32_t AppSpawnServer::SetUidGid( - const uint32_t uid, const uint32_t gid, const uint32_t *gitTable, const uint32_t gidCount) -{ - if (gitTable == nullptr) { - HiLog::Error(LABEL, "gitTable is nullptr"); - return (-errno); - } - - // set gids - if (setgroups(gidCount, reinterpret_cast(&gitTable[0])) == -1) { - HiLog::Error(LABEL, "setgroups failed: %{public}d, gids.size=%{public}u", errno, gidCount); - return (-errno); - } - - // set gid - if (setresgid(gid, gid, gid) == -1) { - HiLog::Error(LABEL, "setgid(%{public}u) failed: %{public}d", gid, errno); - return (-errno); - } - - // If the effective user ID is changed from 0 to nonzero, then all capabilities are cleared from the effective set - if (setresuid(uid, uid, uid) == -1) { - HiLog::Error(LABEL, "setuid(%{public}u) failed: %{public}d", uid, errno); - return (-errno); - } - - return ERR_OK; -} - -int32_t AppSpawnServer::SetFileDescriptors() -{ - // close stdin stdout stderr - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); - - // redirect to /dev/null - int dev_null_fd = open(deviceNull_.c_str(), O_RDWR); - if (dev_null_fd == -1) { - HiLog::Error(LABEL, "open dev_null error: %{public}d", errno); - return (-errno); - } - - // stdin - if (dup2(dev_null_fd, STDIN_FILENO) == -1) { - HiLog::Error(LABEL, "dup2 STDIN error: %{public}d", errno); - return (-errno); - }; - - // stdout - if (dup2(dev_null_fd, STDOUT_FILENO) == -1) { - HiLog::Error(LABEL, "dup2 STDOUT error: %{public}d", errno); - return (-errno); - }; - - // stderr - if (dup2(dev_null_fd, STDERR_FILENO) == -1) { - HiLog::Error(LABEL, "dup2 STDERR error: %{public}d", errno); - return (-errno); - }; - - return ERR_OK; -} - -int32_t AppSpawnServer::SetCapabilities() -{ - // init cap - __user_cap_header_struct cap_header; - - if (memset_s(&cap_header, sizeof(cap_header), 0, sizeof(cap_header)) != EOK) { - HiLog::Error(LABEL, "Failed to memset cap header"); - return -EINVAL; - } - cap_header.version = _LINUX_CAPABILITY_VERSION_3; - cap_header.pid = 0; - - __user_cap_data_struct cap_data[2]; - if (memset_s(&cap_data, sizeof(cap_data), 0, sizeof(cap_data)) != EOK) { - HiLog::Error(LABEL, "Failed to memset cap data"); - return -EINVAL; - } - - // 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 = static_cast<__u32>(inheriTable); - cap_data[1].inheritable = static_cast<__u32>(inheriTable >> BITLEN32); - cap_data[0].permitted = static_cast<__u32>(permitted); - cap_data[1].permitted = static_cast<__u32>(permitted >> BITLEN32); - cap_data[0].effective = static_cast<__u32>(effective); - cap_data[1].effective = static_cast<__u32>(effective >> BITLEN32); - - // set capabilities - if (capset(&cap_header, &cap_data[0]) == -1) { - HiLog::Error(LABEL, "capset failed: %{public}d", errno); - return (-errno); - } - - return ERR_OK; -} - -void AppSpawnServer::SetRunning(bool isRunning) -{ - isRunning_ = isRunning; -} - -void AppSpawnServer::SetServerSocket(const std::shared_ptr &serverSocket) -{ - socket_ = serverSocket; -} - -int32_t AppSpawnServer::DoAppSandboxMountOnce(const std::string originPath, const std::string destinationPath) -{ - int rc = 0; - - rc = mount(originPath.c_str(), destinationPath.c_str(), NULL, MS_BIND | MS_REC, NULL); - if (rc) { - HiLog::Error(LABEL, "bind mount %{public}s to %{public}s failed %{public}d", originPath.c_str(), - destinationPath.c_str(), errno); - return rc; - } - - rc = mount(NULL, destinationPath.c_str(), NULL, MS_PRIVATE, NULL); - if (rc) { - HiLog::Error(LABEL, "private mount to %{public}s failed %{public}d", destinationPath.c_str(), errno); - return rc; - } - - return 0; -} - -int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appProperty, - std::string rootPath) -{ - std::string currentUserId = std::to_string(appProperty->uid / UID_BASE); - std::string oriInstallPath = "/data/app/el1/bundle/public/"; - std::string oriel1DataPath = "/data/app/el1/" + currentUserId + "/base/"; - std::string oriel2DataPath = "/data/app/el2/" + currentUserId + "/base/"; - std::string oriDatabasePath = "/data/app/el2/" + currentUserId + "/database/"; - std::string destDatabasePath = rootPath + "/data/storage/el2/database"; - std::string destInstallPath = rootPath + "/data/storage/el1/bundle"; - std::string destel1DataPath = rootPath + "/data/storage/el1/base"; - std::string destel2DataPath = rootPath + "/data/storage/el2/base"; - - int rc = 0; - - std::string bundleName = appProperty->bundleName; - oriInstallPath += bundleName; - oriel1DataPath += bundleName; - oriel2DataPath += bundleName; - oriDatabasePath += bundleName; - - std::map mountMap; - mountMap[destDatabasePath] = oriDatabasePath; - mountMap[destInstallPath] = oriInstallPath; - mountMap[destel1DataPath] = oriel1DataPath; - mountMap[destel2DataPath] = oriel2DataPath; - - std::map::iterator iter; - for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) { - rc = DoAppSandboxMountOnce(iter->second.c_str(), iter->first.c_str()); - if (rc) { - return rc; - } - } - - // to create some useful dir when mount point created - std::vector mkdirInfo; - std::string dirPath; - mkdirInfo.push_back("/data/storage/el1/bundle/nweb"); - mkdirInfo.push_back("/data/storage/el1/bundle/ohos.global.systemres"); - - for (int i = 0; i < mkdirInfo.size(); i++) { - dirPath = rootPath + mkdirInfo[i]; - mkdir(dirPath.c_str(), FILE_MODE); - } - - return 0; -} - -int32_t AppSpawnServer::DoAppSandboxMountCustomized(const ClientSocket::AppProperty *appProperty, std::string rootPath) -{ - std::string bundleName = appProperty->bundleName; - std::string currentUserId = std::to_string(appProperty->uid / UID_BASE); - std::string destInstallPath = rootPath + "/data/storage/el1/bundle"; - bool AuthFlag = false; - const std::vector AuthAppList = {"com.ohos.launcher", "com.ohos.permissionmanager"}; - if (std::find(AuthAppList.begin(), AuthAppList.end(), bundleName) != AuthAppList.end()) { - AuthFlag = true; - } - - if (strcmp(appProperty->apl, APL_SYSTEM_BASIC.data()) == 0 || - strcmp(appProperty->apl, APL_SYSTEM_CORE.data()) == 0 || AuthFlag) { - // account_0/applications/ dir can still access other packages' data now for compatibility purpose - std::string oriapplicationsPath = "/data/app/el1/bundle/public/"; - std::string destapplicationsPath = rootPath + "/data/accounts/account_0/applications/"; - DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destapplicationsPath.c_str()); - - // need permission check for system app here - std::string destbundlesPath = rootPath + "/data/bundles/"; - DoAppSandboxMountOnce(oriapplicationsPath.c_str(), destbundlesPath.c_str()); - } - - std::string orimntHmdfsPath = "/mnt/hmdfs/"; - std::string destmntHmdfsPath = rootPath + orimntHmdfsPath; - DoAppSandboxMountOnce(orimntHmdfsPath.c_str(), destmntHmdfsPath.c_str()); - - // Add distributedfile module support, later reconstruct it - std::string oriDistributedPath = "/mnt/hmdfs/" + currentUserId + "/account/merge_view/data/" + bundleName; - std::string destDistributedPath = rootPath + "/data/storage/el2/distributedfiles"; - DoAppSandboxMountOnce(oriDistributedPath.c_str(), destDistributedPath.c_str()); - - std::string oriDistributedGroupPath = "/mnt/hmdfs/" + currentUserId + "/non_account/merge_view/data/" + bundleName; - std::string destDistributedGroupPath = rootPath + "/data/storage/el2/auth_groups"; - DoAppSandboxMountOnce(oriDistributedGroupPath.c_str(), destDistributedGroupPath.c_str()); - - // do nweb adaption - std::string orinwebPath = "/data/app/el1/bundle/public/com.ohos.nweb"; - std::string destnwebPath = destInstallPath + "/nweb"; - chmod(destnwebPath.c_str(), NWEB_FILE_MODE); - DoAppSandboxMountOnce(orinwebPath.c_str(), destnwebPath.c_str()); - - // do systemres adaption - std::string oriSysresPath = "/data/app/el1/bundle/public/ohos.global.systemres"; - std::string destSysresPath = destInstallPath + "/ohos.global.systemres"; - chmod(destSysresPath.c_str(), NWEB_FILE_MODE); - DoAppSandboxMountOnce(oriSysresPath.c_str(), destSysresPath.c_str()); - - if (bundleName.find("medialibrary") != std::string::npos) { - std::string oriMediaPath = "/storage/media/" + currentUserId; - std::string destMediaPath = rootPath + "/storage/media"; - DoAppSandboxMountOnce(oriMediaPath.c_str(), destMediaPath.c_str()); - } - - return 0; -} - -void AppSpawnServer::DoAppSandboxMkdir(std::string sandboxPackagePath, const ClientSocket::AppProperty *appProperty) -{ - std::vector mkdirInfo; - std::string dirPath; - - mkdirInfo.push_back("/mnt/"); - mkdirInfo.push_back("/mnt/hmdfs/"); - mkdirInfo.push_back("/data/"); - mkdirInfo.push_back("/storage/"); - mkdirInfo.push_back("/storage/media"); - mkdirInfo.push_back("/data/storage"); - // to create /mnt/sandbox//data/storage/el1 related path, later should delete this code. - mkdirInfo.push_back("/data/storage/el1"); - mkdirInfo.push_back("/data/storage/el1/bundle"); - mkdirInfo.push_back("/data/storage/el1/base"); - mkdirInfo.push_back("/data/storage/el1/database"); - mkdirInfo.push_back("/data/storage/el2"); - mkdirInfo.push_back("/data/storage/el2/base"); - mkdirInfo.push_back("/data/storage/el2/database"); - mkdirInfo.push_back("/data/storage/el2/distributedfiles"); - mkdirInfo.push_back("/data/storage/el2/auth_groups"); - // create applications folder for compatibility purpose - mkdirInfo.push_back("/data/accounts"); - mkdirInfo.push_back("/data/accounts/account_0"); - mkdirInfo.push_back("/data/accounts/account_0/applications/"); - mkdirInfo.push_back("/data/bundles/"); - - for (int i = 0; i < mkdirInfo.size(); i++) { - dirPath = sandboxPackagePath + mkdirInfo[i]; - mkdir(dirPath.c_str(), FILE_MODE); - } -} - -int32_t AppSpawnServer::DoSandboxRootFolderCreateAdapt(std::string sandboxPackagePath) -{ - int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); - if (rc) { - HiLog::Error(LABEL, "set propagation slave failed"); - return rc; - } - - // bind mount "/" to /mnt/sandbox/ path - // rootfs: to do more resources bind mount here to get more strict resources constraints - rc = mount("/", sandboxPackagePath.c_str(), NULL, MS_BIND | MS_REC, NULL); - if (rc) { - HiLog::Error(LABEL, "mount bind / failed"); - return rc; - } - - return 0; -} - -int32_t AppSpawnServer::DoSandboxRootFolderCreate(std::string sandboxPackagePath) -{ - int rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); - if (rc) { - return rc; - } - - // bind mount sandboxPackagePath to make it a mount point for pivot_root syscall - DoAppSandboxMountOnce(sandboxPackagePath.c_str(), sandboxPackagePath.c_str()); - - // do /mnt/sandbox/ path mkdir - std::map mountMap; - std::vector vecInfo; - std::string tmpDir = ""; - - vecInfo.push_back("/config"); - vecInfo.push_back("/dev"); - vecInfo.push_back("/proc"); - vecInfo.push_back("/sys"); - vecInfo.push_back("/sys_prod"); - vecInfo.push_back("/system"); - - for (int i = 0; i < vecInfo.size(); i++) { - tmpDir = sandboxPackagePath + vecInfo[i]; - mkdir(tmpDir.c_str(), FILE_MODE); - mountMap[vecInfo[i]] = tmpDir; - } - - // bind mount root folder to /mnt/sandbox/ path - std::map::iterator iter; - for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) { - rc = DoAppSandboxMountOnce(iter->first.c_str(), iter->second.c_str()); - if (rc) { - HiLog::Error(LABEL, "move root folder failed, %{public}s", sandboxPackagePath.c_str()); - } - } - - // to create symlink at /mnt/sandbox/ path - // bin -> /system/bin - // d -> /sys/kernel/debug - // etc -> /system/etc - // init -> /system/bin/init - // lib -> /system/lib - // sdcard -> /storage/self/primary - std::map symlinkMap; - symlinkMap["/system/bin"] = sandboxPackagePath + "/bin"; - symlinkMap["/sys/kernel/debug"] = sandboxPackagePath + "/d"; - symlinkMap["/system/etc"] = sandboxPackagePath + "/etc"; - symlinkMap["/system/bin/init"] = sandboxPackagePath + "/init"; -#ifdef __aarch64__ - symlinkMap["/system/lib64"] = sandboxPackagePath + "/lib64"; -#else - symlinkMap["/system/lib"] = sandboxPackagePath + "/lib"; -#endif - - for (iter = symlinkMap.begin(); iter != symlinkMap.end(); ++iter) { - symlink(iter->first.c_str(), iter->second.c_str()); - } - - return 0; -} - -int32_t AppSpawnServer::SetAppSandboxProperty(const ClientSocket::AppProperty *appProperty) -{ - int rc = 0; - - // create /mnt/sandbox/ path, later put it to rootfs module - std::string sandboxPackagePath = "/mnt/sandbox/"; - mkdir(sandboxPackagePath.c_str(), FILE_MODE); - sandboxPackagePath += appProperty->bundleName; - mkdir(sandboxPackagePath.c_str(), FILE_MODE); - - // add pid to a new mnt namespace - rc = unshare(CLONE_NEWNS); - if (rc) { - HiLog::Error(LABEL, "unshare failed, packagename is %{public}s", appProperty->processName); - return rc; - } - - // to make wargnar work - if (access("/3rdmodem", F_OK) == 0) { - rc = DoSandboxRootFolderCreateAdapt(sandboxPackagePath); - } else { - rc = DoSandboxRootFolderCreate(sandboxPackagePath); - } - if (rc) { - HiLog::Error(LABEL, "DoSandboxRootFolderCreate failed, %{public}s", appProperty->processName); - return rc; - } - - // to create /mnt/sandbox//data/storage related path - DoAppSandboxMkdir(sandboxPackagePath, appProperty); - - rc = DoAppSandboxMount(appProperty, sandboxPackagePath); - if (rc) { - HiLog::Error(LABEL, "DoAppSandboxMount failed, packagename is %{public}s", appProperty->processName); - return rc; - } - - rc = DoAppSandboxMountCustomized(appProperty, sandboxPackagePath); - if (rc) { - HiLog::Error(LABEL, "DoAppSandboxMountCustomized failed, packagename is %{public}s", appProperty->processName); - return rc; - } - - rc = chdir(sandboxPackagePath.c_str()); - if (rc) { - HiLog::Error(LABEL, "chdir failed, packagename is %{public}s, path is %{public}s", \ - appProperty->processName, sandboxPackagePath.c_str()); - return rc; - } - - rc = syscall(SYS_pivot_root, sandboxPackagePath.c_str(), sandboxPackagePath.c_str()); - if (rc) { - HiLog::Error(LABEL, "pivot root failed, packagename is %{public}s, errno is %{public}d", \ - appProperty->processName, errno); - return rc; - } - - rc = umount2(".", MNT_DETACH); - if (rc) { - HiLog::Error(LABEL, "MNT_DETACH failed, packagename is %{public}s", appProperty->processName); - return rc; - } - - return ERR_OK; -} - -void AppSpawnServer::SetAppAccessToken(const ClientSocket::AppProperty *appProperty) -{ - int32_t ret = SetSelfTokenID(appProperty->accessTokenId); - HiLog::Info(LABEL, "AppSpawnServer::set access token id = %{public}d, ret = %{public}d %{public}d", - appProperty->accessTokenId, ret, getuid()); - -#ifdef WITH_SELINUX - HapContext hapContext; - ret = hapContext.HapDomainSetcontext(appProperty->apl, appProperty->processName); - if (ret) { - HiLog::Error(LABEL, "AppSpawnServer::Failed to hap domain set context, errno = %{public}d %{public}s", - errno, appProperty->apl); - } else { - HiLog::Info(LABEL, "AppSpawnServer::Success to hap domain set context, ret = %{public}d", ret); - } -#endif -} - -bool AppSpawnServer::SetAppProcProperty(const ClientSocket::AppProperty *appProperty, char *longProcName, - int64_t longProcNameLen, const int32_t fd) -{ - HiLog::Debug(LABEL, "AppSpawnServer::Success to fork new process, pid = %{public}d", getpid()); - int32_t ret = SetAppSandboxProperty(appProperty); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } - - ret = SetKeepCapabilities(appProperty->uid); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } - - ret = SetProcessName(longProcName, longProcNameLen, appProperty->processName, strlen(appProperty->processName) + 1); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } - -#ifdef GRAPHIC_PERMISSION_CHECK - ret = SetUidGid(appProperty->uid, appProperty->gid, appProperty->gidTable, appProperty->gidCount); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } -#endif - - ret = SetFileDescriptors(); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } - - ret = SetCapabilities(); - if (FAILED(ret)) { - NotifyResToParentProc(fd, ret); - return false; - } - // notify success to father process and start app process - NotifyResToParentProc(fd, ret); - -#ifdef NWEB_SPAWN - using FuncType = void (*)(const char *cmd); - FuncType funcNWebRenderMain = reinterpret_cast(dlsym(nwebHandle, "NWebRenderMain")); - if (funcNWebRenderMain == nullptr) { - HiLog::Error(LABEL, "nwebspawn dlsym ERROR=%{public}s", dlerror()); - return false; - } - funcNWebRenderMain(appProperty->renderCmd); -#else - AppExecFwk::MainThread::Start(); -#endif - return true; -} - -void AppSpawnServer::NotifyResToParentProc(const int32_t fd, const int32_t value) -{ - write(fd, &value, sizeof(value)); - close(fd); -} - -void AppSpawnServer::SpecialHandle(ClientSocket::AppProperty *appProperty) -{ - if (appProperty == nullptr) { - HiLog::Error(LABEL, "appProperty is nullptr"); - return; - } - // special handle bundle name medialibrary and scanner - if ((strcmp(appProperty->processName, BUNDLE_NAME_MEDIA_LIBRARY.data()) == 0) || - (strcmp(appProperty->processName, BUNDLE_NAME_SCANNER.data()) == 0)) { - if (appProperty->gidCount < MAX_GIDS) { - appProperty->gidTable[appProperty->gidCount] = GID_USER_DATA_RW; - appProperty->gidCount++; - } else { - HiLog::Info(LABEL, "gidCount out of bounds !"); - } - } -} - -int32_t AppSpawnServer::SetKeepCapabilities(uint32_t uid) -{ - // set keep capabilities when user not root. - if (uid != 0) { - if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { - HiLog::Error(LABEL, "set keepcaps failed: %{public}d", errno); - return (-errno); - } - } - - return ERR_OK; -} - -bool AppSpawnServer::CheckAppProperty(const ClientSocket::AppProperty *appProperty) -{ - if (appProperty == nullptr) { - HiLog::Error(LABEL, "appProperty is nullptr"); - return false; - } - - if (appProperty->gidCount > ClientSocket::MAX_GIDS) { - HiLog::Error(LABEL, "gidCount error: %{public}u", appProperty->gidCount); - return false; - } - - if (strlen(appProperty->processName) == 0) { - HiLog::Error(LABEL, "process name length is 0"); - return false; - } - - return true; -} - -int AppSpawnServer::AppColdStart(char *longProcName, - int64_t longProcNameLen, const ClientSocket::AppProperty *appProperty, int fd) -{ - APPSPAWN_LOGI("AppColdStart appName %s", appProperty->bundleName); - LoadAceLib(); - if (!SetAppProcProperty(appProperty, longProcName, longProcNameLen, fd)) { - return -1; - } - APPSPAWN_LOGI("AppColdStart appName %s success", appProperty->bundleName); - return 0; -} -} // namespace AppSpawn -} // namespace OHOS diff --git a/src/include/appspawn_msg_peer.h b/src/include/appspawn_msg_peer.h deleted file mode 100644 index 473a00de..00000000 --- a/src/include/appspawn_msg_peer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef APPSPAWN_MSG_PEER_H -#define APPSPAWN_MSG_PEER_H - -#include - -#include "client_socket.h" -#include "server_socket.h" -#include "nocopyable.h" - -namespace OHOS { -namespace AppSpawn { -class AppSpawnMsgPeer { -public: - /** - * Constructor used to delete the default constructor. - */ - AppSpawnMsgPeer() = delete; - - /** - * Constructor used to create a AppSpawnMsgPeer. - */ - AppSpawnMsgPeer(const std::shared_ptr &socket, int connectFd); - - /** - * Destructor used to destroy a AppSpawnMsgPeer - */ - ~AppSpawnMsgPeer(); - - /** - * Disables copy and moving of AppSpawnMsgPeer. - */ - DISALLOW_COPY_AND_MOVE(AppSpawnMsgPeer); - - /** - * Gets the message about the app property. - */ - ClientSocket::AppProperty *GetMsg() const; - - /** - * Returns the PID of the application process in the response sent to the ability manager service - * after AppSpawn forks the application process. - * - * @param pid Indicates the PID of the application process. - */ - int Response(pid_t pid); - - /** - * Reads the message from MsgPeer over the socket. - */ - int MsgPeer(); - - /** - * Gets the connection file description used by the ability manager service to connect to AppSpawn. - */ - int GetConnectFd() const; - -private: - int connectFd_ = -1; - std::shared_ptr socket_ = nullptr; - std::unique_ptr buf_ = nullptr; -}; -} // namespace AppSpawn -} // namespace OHOS -#endif diff --git a/src/include/appspawn_server.h b/src/include/appspawn_server.h deleted file mode 100644 index 987057f5..00000000 --- a/src/include/appspawn_server.h +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef APPSPAWN_SERVER_H -#define APPSPAWN_SERVER_H - -#include -#include -#include - -#include "appspawn_msg_peer.h" -#include "server_socket.h" -#include "nocopyable.h" - -namespace OHOS { -namespace AppSpawn { -class AppSpawnServer { -public: - /** - * Constructor used to delete the default constructor. - */ - AppSpawnServer() = delete; - - /** - * Constructor used to create a AppSpawnServer. - */ - explicit AppSpawnServer(const std::string &socketName); - - /** - * Destructor used to destroy a AppSpawnServer - */ - ~AppSpawnServer() = default; - - /** - * Disables copying and moving for the AppSpawnServer. - */ - DISALLOW_COPY_AND_MOVE(AppSpawnServer); - - /** - * Provides the AppSpawn core function for the server to receive messages from ability manager service. - * - * @param longProcName Indicates the long process name. - * @param longProcNameLen Indicates the length of long process name. - */ - bool ServerMain(char *longProcName, int64_t longProcNameLen); - - /** - * Controls the server listening socket. - * - * @param isRunning Indicates whether the server is running. Value false means to stop the server and exit. - */ - void SetRunning(bool isRunning); - - /** - * Set its value to the member variable socket_. - * - * @param serverSocket Indicates the server socket. - */ - void SetServerSocket(const std::shared_ptr &serverSocket); - - int AppColdStart(char *longProcName, - int64_t longProcNameLen, const ClientSocket::AppProperty *appProperty, int fd); - -private: - int DoColdStartApp(ClientSocket::AppProperty *appProperty, int fd); - - static constexpr uint8_t BITLEN32 = 32; - static constexpr uint8_t FDLEN2 = 2; - static constexpr uint8_t FD_INIT_VALUE = 0; - - /** - * Use the MsgPeer method in the AppSpawnMsgPeer class to read message from socket, and notify the ServerMain to - * unlock. - * - * @param connectFd Indicates the connect FDs. - */ - void MsgPeer(int connectFd); - - /** - * Gets the connect fd and creates a thread to receive messages. - */ - void ConnectionPeer(); - - /** - * Sets a name for an application process. - * - * @param longProcName Indicates the length of long process name. - * @param longProcNameLen Indicates the long process name. - * @param processName Indicates the process name from the ability manager service. - * @param len Indicates the size of processName. - */ - int32_t SetProcessName(char *longProcName, int64_t longProcNameLen, const char *processName, int32_t len); - - /** - * Sets keep capabilities. - */ - int32_t SetKeepCapabilities(uint32_t uid); - - /** - * Sets the uid and gid of an application process. - * - * @param uid Indicates the uid of the application process. - * @param gid Indicates the gid of the application process. - * @param gidTable Indicates an array of application processes. - * @param gidCount Indicates the number of GIDs. - */ - int32_t SetUidGid(const uint32_t uid, const uint32_t gid, const uint32_t *gidTable, const uint32_t gidCount); - - /** - * Sets FDs in an application process. - */ - int32_t SetFileDescriptors(); - - /** - * Sets capabilities of an application process. - */ - int32_t SetCapabilities(); - - /** - * Create sandbox root folder file - */ - int32_t DoSandboxRootFolderCreate(std::string sandboxPackagePath); - - /** - * Create sandbox root folder file with wargnar device - */ - int32_t DoSandboxRootFolderCreateAdapt(std::string sandboxPackagePath); - - /** - * Do app sandbox original path mount common - */ - int32_t DoAppSandboxMountOnce(const std::string originPath, const std::string destinationPath); - - /** - * Do app sandbox original path mount - */ - int32_t DoAppSandboxMount(const ClientSocket::AppProperty *appProperty, std::string rootPath); - - /** - * Do app sandbox original path mount for some customized packages - */ - int32_t DoAppSandboxMountCustomized(const ClientSocket::AppProperty *appProperty, std::string rootPath); - - /** - * Do app sandbox mkdir /mnt/sandbox// - */ - void DoAppSandboxMkdir(std::string rootPath, const ClientSocket::AppProperty *appProperty); - - /** - * Sets app sandbox property. - */ - int32_t SetAppSandboxProperty(const ClientSocket::AppProperty *appProperty); - - /** - * Sets app process property. - */ - bool SetAppProcProperty(const ClientSocket::AppProperty *appProperty, char *longProcName, - int64_t longProcNameLen, const int32_t fd); - - /** - * Notify - */ - void NotifyResToParentProc(const int32_t fd, const int32_t value); - - /** - * Special app process property. - */ - void SpecialHandle(ClientSocket::AppProperty *appProperty); - - /** - * Check app process property. - */ - bool CheckAppProperty(const ClientSocket::AppProperty *appProperty); - - void LoadAceLib(); - - void SetAppAccessToken(const ClientSocket::AppProperty *appProperty); - - int StartApp(char *longProcName, int64_t longProcNameLen, - ClientSocket::AppProperty *appProperty, int connectFd, pid_t &pid); - - void WaitRebootEvent(); - - void HandleSignal(); - - void QuickExitMain(); - - void ProcessAppSpawnMsg(char *longProcName, int64_t longProcNameLen, - const std::unique_ptr &msg); - -private: - const std::string deviceNull_ = "/dev/null"; - std::string socketName_ {}; - std::shared_ptr socket_ = nullptr; - std::mutex mut_ {}; - mutable std::condition_variable dataCond_ {}; - std::queue> appQueue_ {}; - std::function propertyHandler_ = nullptr; - std::function errHandlerHook_ = nullptr; - bool isRunning_ {}; - bool isStop_ { false }; - bool isChildDie_ { false }; - pid_t childPid_ {}; - std::map appMap_; -#ifdef NWEB_SPAWN - void *nwebHandle = nullptr; -#endif -}; -} // namespace AppSpawn -} // namespace OHOS - -#endif diff --git a/src/include/server_socket.h b/src/include/server_socket.h deleted file mode 100644 index eae78cba..00000000 --- a/src/include/server_socket.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef APPSPAWN_SOCKET_SERVER_H -#define APPSPAWN_SOCKET_SERVER_H - -#include -#include -#include -#include - -#include "appspawn_socket.h" -#include "nocopyable.h" - -namespace OHOS { -namespace AppSpawn { -class ServerSocket : public AppSpawnSocket { -public: - /** - * Constructor used to create a ServerSocket - */ - explicit ServerSocket(const std::string &server); - - /** - * Destructor used to destroy a ServerSocket - */ - virtual ~ServerSocket(); - - /** - * Disables copying and moving for ServerSocket. - */ - DISALLOW_COPY_AND_MOVE(ServerSocket); - - /** - * Closes a socket connection. - * - * @param connectFd Indicates the connection's file descriptor (FD). - */ - virtual void CloseConnection(int connectFd); - - /** - * Saves the connection's FD. - * - * @param connectFd Indicates the connection's file descriptor (FD). - */ - virtual void SaveConnection(int connectFd); - - /** - * Closes a server socket. - */ - virtual void CloseServer(); - - /** - * Closes the server monitor. - */ - virtual void CloseServerMonitor(); - - /** - * Creates server socket, binds socket and listens it. - * - * @return -1:failed; 0:success - */ - virtual int RegisterServerSocket(); - - /** - * Sets socket option and waits for connection. - * - * @return -1:failed;other means connection FD. - */ - virtual int WaitForConnection(); - - /** - * Verifies the connection's FD. - * - * @return -1:failed; 0:success - */ - virtual int VerifyConnection(int connectFd); - - /** - * Uses functions of the parent class. - */ - using AppSpawnSocket::CloseSocket; - using AppSpawnSocket::CreateSocket; - using AppSpawnSocket::GetSocketFd; - using AppSpawnSocket::ReadSocketMessage; - using AppSpawnSocket::WriteSocketMessage; - - static constexpr uid_t APPSPAWN_ID_ROOT = 0; // chown owner - static constexpr gid_t APPSPAWN_ID_SYSTEM = 1000; // chown group - static constexpr mode_t SOCKET_PERM = 0660; // root system can read and write appspawn socket - -private: - /** - * Binds a socket and sets socket attributes. - * - * @param connectFd Indicates the connection's FD. - */ - int BindSocket(int connectFd); - - /** - * Creates a socket and binds it. - * - * @param connectFd Indicates the connection's FD. - */ - int RegisterServerSocket(int &connectFd); - - /** - * Accepts a socket. - * - * @param connectFd Indicates the connection's FD. - */ - int WaitForConnection(int connectFd); - -private: - std::vector connectFds_ = {}; - std::mutex mutexConnect_; -}; -} // namespace AppSpawn -} // namespace OHOS -#endif diff --git a/src/socket/server_socket.cpp b/src/socket/server_socket.cpp deleted file mode 100644 index fd035d13..00000000 --- a/src/socket/server_socket.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (c) 2021-2022 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 "server_socket.h" - -#include -#include -#include - -#include "hilog/log.h" -#include "init_socket.h" -#include "securec.h" - -namespace OHOS { -namespace AppSpawn { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "ServerSocket"}; - -ServerSocket::ServerSocket(const std::string &server) : AppSpawnSocket(server) -{} - -ServerSocket::~ServerSocket() -{ - CloseServer(); -} - -int ServerSocket::VerifyConnection(int connectFd) -{ - std::lock_guard lock(mutexConnect_); - - std::vector::iterator it = find(connectFds_.begin(), connectFds_.end(), connectFd); - if (it == connectFds_.end()) { - return -1; - } - - return 0; -} - -void ServerSocket::CloseConnection(int connectFd) -{ - if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid connectFd %{public}d", connectFd); - return; - } - - std::lock_guard lock(mutexConnect_); - - std::vector::iterator it = find(connectFds_.begin(), connectFds_.end(), connectFd); - if (it == connectFds_.end()) { - close(connectFd); - return; - } - - close(connectFd); - connectFds_.erase(it); - HiLog::Debug(LABEL, "Server: Erase connect fd %{public}d from list", connectFd); -} - -void ServerSocket::SaveConnection(int connectFd) -{ - if (connectFd >= 0) { - std::lock_guard lock(mutexConnect_); - connectFds_.push_back(connectFd); - } -} - -void ServerSocket::CloseServer() -{ - std::lock_guard lock(mutexConnect_); - - for (const int &fd : connectFds_) { - HiLog::Debug(LABEL, "Server: Closed connection fd %{public}d", fd); - close(fd); - } - - if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) { - HiLog::Error(LABEL, "Server: Failed to unlink, err %{public}d", errno); - } - - connectFds_.clear(); - if (socketFd_ >= 0) { - CloseSocket(socketFd_); - socketFd_ = -1; - } -} - -void ServerSocket::CloseServerMonitor() -{ - if (socketFd_ >= 0) { - CloseSocket(socketFd_); - socketFd_ = -1; - } -} - -int ServerSocket::BindSocket(int connectFd) -{ - if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid socket fd: %{public}d", connectFd); - return -EINVAL; - } - - if (PackSocketAddr() != 0) { - return -1; - } - - if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) { - HiLog::Error(LABEL, "Server: Failed to unlink, err %{public}d", errno); - return (-errno); - } - - int reuseAddr = 0; - if ((setsockopt(connectFd, SOL_SOCKET, SO_REUSEADDR, &reuseAddr, sizeof(reuseAddr)) != 0) || - (setsockopt(connectFd, SOL_SOCKET, SO_RCVTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) != 0) || - (setsockopt(connectFd, SOL_SOCKET, SO_SNDTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) != 0)) { - HiLog::Warn(LABEL, "Server: Failed to set opt of socket %{public}d, err %{public}d", connectFd, errno); - return (-errno); - } - - if (bind(connectFd, reinterpret_cast(&socketAddr_), socketAddrLen_) < 0) { - HiLog::Error(LABEL, "Server: Bind socket fd %{public}d, failed: %{public}d", connectFd, errno); - return (-errno); - } - - if (chown(socketAddr_.sun_path, APPSPAWN_ID_ROOT, APPSPAWN_ID_SYSTEM)) { - HiLog::Error(LABEL, "Server: failed to chown socket fd %{public}d, failed: %{public}d", connectFd, errno); - return (-errno); - } - if (chmod(socketAddr_.sun_path, SOCKET_PERM)) { - HiLog::Error(LABEL, "Server: failed to chmod socket fd %{public}d, failed: %{public}d", connectFd, errno); - return (-errno); - } - - HiLog::Debug(LABEL, "Server: Bind socket fd %{public}d success", connectFd); - return 0; -} - -int ServerSocket::RegisterServerSocket(int &connectFd) -{ - if (socketName_.empty()) { - HiLog::Error(LABEL, "Server: Invalid socket name: empty"); - return -EINVAL; - } - -#ifdef NWEB_SPAWN - connectFd = GetControlSocket("NWebSpawn"); -#else - connectFd = CreateSocket(); -#endif - if (connectFd < 0) { - return connectFd; - } - -#ifndef NWEB_SPAWN - if ((BindSocket(connectFd) != 0) || (listen(connectFd, listenBacklog_) < 0)) { - HiLog::Error(LABEL, - "Server: Register socket fd %{public}d with backlog %{public}d error: %{public}d", - connectFd, - listenBacklog_, - errno); - if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) { - HiLog::Error(LABEL, "Server: Failed to unlink, err %{public}d", errno); - } - close(connectFd); - connectFd = -1; - return (-errno); - } -#endif - HiLog::Debug(LABEL, "Server: Suc to register server socket fd %{public}d", connectFd); - return 0; -} - -int ServerSocket::RegisterServerSocket() -{ - if (socketFd_ >= 0) { - HiLog::Info(LABEL, "Server: Already register server socket %{public}d", socketFd_); - return 0; - } - - return RegisterServerSocket(socketFd_); -} - -int ServerSocket::WaitForConnection(int connectFd) -{ - if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid args: connectFd %{public}d", connectFd); - return -EINVAL; - } - - struct sockaddr_un clientAddr; - socklen_t clientLen = sizeof(clientAddr); - if (memset_s(&clientAddr, clientLen, 0, clientLen) != EOK) { - HiLog::Warn(LABEL, "Server: Failed to memset client addr"); - return -EINVAL; - } - - int connFd = accept(connectFd, reinterpret_cast(&clientAddr), &clientLen); - if (connFd < 0) { - return (-errno); - } - - if ((setsockopt(connFd, SOL_SOCKET, SO_RCVTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) < 0) || - (setsockopt(connFd, SOL_SOCKET, SO_SNDTIMEO, &SOCKET_TIMEOUT, sizeof(SOCKET_TIMEOUT)) < 0)) { - HiLog::Warn(LABEL, "Server: Failed to set opt of Connection %{public}d, err %{public}d", connFd, errno); - close(connFd); - return (-errno); - } - - HiLog::Debug(LABEL, "Server: Connection accepted, connect fd %{public}d", connFd); - return connFd; -} - -int ServerSocket::WaitForConnection() -{ - int connectFd = WaitForConnection(socketFd_); - SaveConnection(connectFd); - - return connectFd; -} -} // namespace AppSpawn -} // namespace OHOS diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c new file mode 100644 index 00000000..2f2d8789 --- /dev/null +++ b/standard/appspawn_process.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_service.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sandbox.h" +#include "appspawn_adapter.h" +#include "securec.h" + +#define DEVICE_NULL_STR "/dev/null" + +static int SetProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client, + char *longProcName, uint32_t longProcNameLen) +{ + AppSpawnClientExt *appPropertyExt = (AppSpawnClientExt *)client; + AppParameter *appProperty = &appPropertyExt->property; + int len = strlen(appProperty->processName); + if (longProcName == NULL || len <= 0) { + APPSPAWN_LOGE("process name is nullptr or length error"); + return -EINVAL; + } + + char shortName[MAX_LEN_SHORT_NAME] = {0}; + // process short name max length 16 bytes. + if (len >= MAX_LEN_SHORT_NAME) { + if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, appProperty->processName, MAX_LEN_SHORT_NAME - 1) != EOK) { + APPSPAWN_LOGE("strncpy_s short name error: %d", errno); + return -EINVAL; + } + } else { + if (strncpy_s(shortName, MAX_LEN_SHORT_NAME, appProperty->processName, len) != EOK) { + APPSPAWN_LOGE("strncpy_s short name error: %d", errno); + return -EINVAL; + } + } + + // set short name + if (prctl(PR_SET_NAME, shortName) == -1) { + APPSPAWN_LOGE("prctl(PR_SET_NAME) error: %d", errno); + return (-errno); + } + + // reset longProcName + if (memset_s(longProcName, (size_t)longProcNameLen, 0, (size_t)longProcNameLen) != EOK) { + APPSPAWN_LOGE("Failed to memset long process name"); + return -EINVAL; + } + + // set long process name + if (strncpy_s(longProcName, sizeof(appProperty->processName) - 1, appProperty->processName, len) != EOK) { + APPSPAWN_LOGE("strncpy_s long name error: %d longProcNameLen %u", errno, longProcNameLen); + return -EINVAL; + } + return 0; +} + +static int SetKeepCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + // set keep capabilities when user not root. + if (appProperty->property.uid != 0) { + if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { + APPSPAWN_LOGE("set keepcaps failed: %d", errno); + return (-errno); + } + } + return 0; +} + +static int SetCapabilities(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + // init cap + struct __user_cap_header_struct cap_header; + + if (memset_s(&cap_header, sizeof(cap_header), 0, sizeof(cap_header)) != EOK) { + APPSPAWN_LOGE("Failed to memset cap header"); + return -EINVAL; + } + cap_header.version = _LINUX_CAPABILITY_VERSION_3; + cap_header.pid = 0; + + struct __user_cap_data_struct cap_data[2]; + if (memset_s(&cap_data, sizeof(cap_data), 0, sizeof(cap_data)) != EOK) { + APPSPAWN_LOGE("Failed to memset cap data"); + return -EINVAL; + } + + // 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 + if (capset(&cap_header, &cap_data[0]) == -1) { + APPSPAWN_LOGE("capset failed: %d", errno); + return (-errno); + } + return 0; +} + +static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; +#ifdef __aarch64__ + const char *debugSoPath = "/system/lib64/libhidebug.so"; +#else + const char *debugSoPath = "/system/lib/libhidebug.so"; +#endif + if (access(debugSoPath, F_OK) != 0) { + APPSPAWN_LOGE("access failed, errno = %d", errno); + return; + } + void *handle = dlopen(debugSoPath, RTLD_LAZY); + if (handle == NULL) { + APPSPAWN_LOGE("Failed to dlopen libhidebug.so, %s", dlerror()); + return; + } + bool (*initParam)(const char *name); + initParam = (bool (*)(const char *name))dlsym(handle, "InitEnvironmentParam"); + if (initParam == NULL) { + APPSPAWN_LOGE("Failed to dlsym InitEnvironmentParam, %s", dlerror()); + dlclose(handle); + return; + } + bool ret = (*initParam)(appProperty->property.processName); + if (!ret) { + APPSPAWN_LOGV("init parameters failed."); + } + dlclose(handle); +} + +static void ClearEnvironment(AppSpawnContent *content, AppSpawnClient *client) +{ + APPSPAWN_LOGI("ClearEnvironment id %d", client->id); + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGTERM); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + // close child fd + close(appProperty->fd[0]); + InitDebugParams(content, client); + return; +} + +static int SetUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ +#ifdef GRAPHIC_PERMISSION_CHECK + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + // set gids + if (setgroups(appProperty->property.gidCount, (const gid_t *)(&appProperty->property.gidTable[0])) == -1) { + APPSPAWN_LOGE("setgroups failed: %d, gids.size=%u", errno, appProperty->property.gidCount); + return (-errno); + } + + // set gid + if (setresgid(appProperty->property.gid, appProperty->property.gid, appProperty->property.gid) == -1) { + APPSPAWN_LOGE("setgid(%u) failed: %d", appProperty->property.gid, errno); + return (-errno); + } + + // If the effective user ID is changed from 0 to nonzero, then all capabilities are cleared from the effective set + if (setresuid(appProperty->property.uid, appProperty->property.uid, appProperty->property.uid) == -1) { + APPSPAWN_LOGE("setuid(%u) failed: %d", appProperty->property.uid, errno); + return (-errno); + } +#endif + return 0; +} + +static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + // close stdin stdout stderr + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + // redirect to /dev/null + int dev_null_fd = open(DEVICE_NULL_STR, O_RDWR); + if (dev_null_fd == -1) { + APPSPAWN_LOGE("open dev_null error: %d", errno); + return (-errno); + } + + // stdin + if (dup2(dev_null_fd, STDIN_FILENO) == -1) { + APPSPAWN_LOGE("dup2 STDIN error: %d", errno); + return (-errno); + }; + + // stdout + if (dup2(dev_null_fd, STDOUT_FILENO) == -1) { + APPSPAWN_LOGE("dup2 STDOUT error: %d", errno); + return (-errno); + }; + + // stderr + if (dup2(dev_null_fd, STDERR_FILENO) == -1) { + APPSPAWN_LOGE("dup2 STDERR error: %d", errno); + return (-errno); + }; + + return 0; +} + +static void Free(char **argv) +{ + argv[0] = NULL; + for (int i = 0; i < NULL_INDEX; i++) { + if (argv[i] != NULL) { + free(argv[i]); + argv[i] = NULL; + } + } + free(argv); +} + +static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; + APPSPAWN_LOGI("ColdStartApp::appName %s", appProperty->processName); + char buffer[32] = {0}; // 32 buffer for fd + int len = sprintf_s(buffer, sizeof(buffer), "%d", ((AppSpawnClientExt *)client)->fd[1]); + APPSPAWN_CHECK(len > 0, return -1, "Invalid to format fd"); + char **argv = calloc(1, (NULL_INDEX + 1) * sizeof(char *)); + APPSPAWN_CHECK(argv != NULL, return -1, "Failed to get argv"); + + int32_t startLen = 0; + const int32_t originLen = sizeof(AppParameter) + PARAM_BUFFER_LEN; + // param + char *param = malloc(originLen + APP_LEN_PROC_NAME); + APPSPAWN_CHECK(param != NULL, free(argv); + return -1, "Failed to malloc for param"); + + int ret = -1; + do { + argv[PARAM_INDEX] = param; + argv[0] = param + originLen; + ret = strcpy_s(argv[0], APP_LEN_PROC_NAME, "/system/bin/appspawn"); + APPSPAWN_CHECK(ret >= 0, break, "Invalid strdup"); + argv[START_INDEX] = strdup("cold-start"); + APPSPAWN_CHECK(argv[START_INDEX] != NULL, break, "Invalid strdup"); + argv[FD_INDEX] = strdup(buffer); + APPSPAWN_CHECK(argv[FD_INDEX] != NULL, break, "Invalid strdup"); + + len = sprintf_s(param + startLen, originLen - startLen, "%u:%u:%u:%d", + ((AppSpawnClientExt *)client)->client.id, + appProperty->uid, appProperty->gid, appProperty->gidCount); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format"); + startLen += len; + for (uint32_t i = 0; i < appProperty->gidCount; i++) { + len = sprintf_s(param + startLen, originLen - startLen, ":%u", appProperty->gidTable[i]); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format gid"); + startLen += len; + } + // processName + len = sprintf_s(param + startLen, originLen - startLen, ":%s:%s:%s:%u:%s:%s", + appProperty->processName, appProperty->bundleName, appProperty->soPath, + appProperty->accessTokenId, appProperty->apl, appProperty->renderCmd); + APPSPAWN_CHECK(len > 0 && (len < (originLen - startLen)), break, "Invalid to format processName"); + startLen += len; + ret = 0; + } while (0); + + if (ret == 0) { + argv[NULL_INDEX] = NULL; +#ifndef APPSPAWN_TEST + ret = execv(argv[0], argv); +#endif + if (ret) { + APPSPAWN_LOGE("Failed to execv, errno = %d", errno); + } + } + + return ret; +} + +int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client) +{ + APPSPAWN_CHECK(argv != NULL, return -1, "Invalid arg"); + APPSPAWN_CHECK(argc > PARAM_INDEX, return -1, "Invalid argc %d", argc); + + client->fd[1] = atoi(argv[FD_INDEX]); + APPSPAWN_LOGV("GetAppSpawnClientFromArg %s ", argv[PARAM_INDEX]); + char *end = NULL; + char *start = strtok_r(argv[PARAM_INDEX], ":", &end); + // clientid + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get client id"); + client->client.id = atoi(start); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get uid"); + client->property.uid = atoi(start); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gid"); + client->property.gid = atoi(start); + // gidCount + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gidCount"); + client->property.gidCount = atoi(start); + for (uint32_t i = 0; i < client->property.gidCount; i++) { + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get gidTable"); + client->property.gidTable[i] = atoi(start); + } + // processname + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get processName"); + int ret = strcpy_s(client->property.processName, sizeof(client->property.processName), start); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy processName"); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get bundleName"); + ret = strcpy_s(client->property.bundleName, sizeof(client->property.bundleName), start); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy bundleName"); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get soPath"); + ret = strcpy_s(client->property.soPath, sizeof(client->property.soPath), start); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy soPath"); + // accesstoken + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get accessTokenId"); + client->property.accessTokenId = atoi(start); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get apl"); + ret = strcpy_s(client->property.apl, sizeof(client->property.apl), start); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy apl"); + start = strtok_r(NULL, ":", &end); + APPSPAWN_CHECK(start != NULL, return -1, "Failed to get renderCmd"); + ret = strcpy_s(client->property.renderCmd, sizeof(client->property.renderCmd), start); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to strcpy renderCmd"); + return 0; +} + +void SetContentFunction(AppSpawnContent *content) +{ + APPSPAWN_LOGI("SetContentFunction"); + content->clearEnvironment = ClearEnvironment; + content->setProcessName = SetProcessName; + content->setKeepCapabilities = SetKeepCapabilities; + content->setUidGid = SetUidGid; + content->setCapabilities = SetCapabilities; + content->setFileDescriptors = SetFileDescriptors; + content->setAppSandbox = SetAppSandboxProperty; + content->setAppAccessToken = SetAppAccessToken; + content->coldStartApp = ColdStartApp; + content->registerAppSandbox = RegisterAppSandbox; +} diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c new file mode 100644 index 00000000..511a5bf1 --- /dev/null +++ b/standard/appspawn_service.c @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_service.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "appspawn_server.h" +#include "init_hashmap.h" +#include "init_socket.h" +#include "parameter.h" +#include "securec.h" + +static AppSpawnContentExt *g_appSpawnContent = NULL; + +static const int TV_SEC = 60; + +static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2) +{ + AppInfo *testNode1 = HASHMAP_ENTRY(node1, AppInfo, node); + AppInfo *testNode2 = HASHMAP_ENTRY(node2, AppInfo, node); + return testNode1->pid - testNode2->pid; +} + +static int TestHashKeyCompare(const HashNode *node1, const void *key) +{ + AppInfo *testNode1 = HASHMAP_ENTRY(node1, AppInfo, node); + return testNode1->pid - *(pid_t *)key; +} + +static int AppInfoHashNodeFunction(const HashNode *node) +{ + AppInfo *testNode = HASHMAP_ENTRY(node, AppInfo, node); + if (testNode == NULL) { + return -1; + } + return testNode->pid % APP_HASH_BUTT; +} + +static int AppInfoHashKeyFunction(const void *key) +{ + pid_t code = *(pid_t *)key; + return code % APP_HASH_BUTT; +} + +static void AppInfoHashNodeFree(const HashNode *node) +{ + AppInfo *testNode = HASHMAP_ENTRY(node, AppInfo, node); + APPSPAWN_LOGI("AppInfoHashNodeFree %s\n", testNode->name); + free(testNode); +} + +static void AddAppInfo(pid_t pid, const char *processName) +{ + size_t len = strlen(processName) + 1; + AppInfo *node = (AppInfo *)malloc(sizeof(AppInfo) + len + 1); + APPSPAWN_CHECK(node != NULL, return, "Failed to malloc for appinfo"); + + node->pid = pid; + int ret = strcpy_s(node->name, len, processName); + APPSPAWN_CHECK(ret == 0, free(node); + return, "Failed to strcpy process name"); + HASHMAPInitNode(&node->node); + ret = HashMapAdd(g_appSpawnContent->appMap, &node->node); + APPSPAWN_CHECK(ret == 0, free(node); + return, "Failed to add appinfo to hash"); + APPSPAWN_LOGI("Add %s, pid=%d success", processName, pid); +} + +static void RemoveAppInfo(pid_t pid) +{ + HashNode *node = HashMapGet(g_appSpawnContent->appMap, (const void *)&pid); + APPSPAWN_CHECK(node != NULL, return, "Invalid node %d", pid); + AppInfo *appInfo = HASHMAP_ENTRY(node, AppInfo, node); + APPSPAWN_CHECK(appInfo != NULL, return, "Invalid node %d", pid); + HashMapRemove(g_appSpawnContent->appMap, (const void *)&pid); + free(appInfo); +} + +static void KillProcess(const HashNode *node, const void *context) +{ + AppInfo *hashNode = (AppInfo *)node; + kill(hashNode->pid, SIGKILL); + APPSPAWN_LOGI("kill app, pid = %d, processName = %s", hashNode->pid, hashNode->name); +} + +static void OnClose(const TaskHandle taskHandle) +{ + AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(taskHandle); + APPSPAWN_CHECK(client != NULL, return, "Failed to get client"); + APPSPAWN_LOGI("OnClose client.id %d ", client->client.id); +} + +static void SendMessageComplete(const TaskHandle taskHandle, BufferHandle handle) +{ + AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(taskHandle); + APPSPAWN_CHECK(client != NULL, return, "Failed to get client"); + APPSPAWN_LOGI("SendMessageComplete client.id %d ", client->client.id); +} + +static int SendResponse(AppSpawnClientExt *client, const char *buff, size_t buffSize) +{ + APPSPAWN_CHECK(buffSize >= 0 && buff != 0, return -1, "Invalid content buffSize %d", buffSize); + uint32_t bufferSize = buffSize; + BufferHandle handle = LE_CreateBuffer(LE_GetDefaultLoop(), bufferSize); + char *buffer = (char *)LE_GetBufferInfo(handle, NULL, &bufferSize); + int ret = memcpy_s(buffer, bufferSize, buff, buffSize); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to memcpy_s bufferSize"); + return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize); +} + +static void SignalHandler(const struct signalfd_siginfo *siginfo) +{ + APPSPAWN_LOGI("SignalHandler signum %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) { + APPSPAWN_LOGI("SignalHandler pid %d status %d", pid, status); + RemoveAppInfo(pid); +#ifdef NWEB_SPAWN + RecordRenderProcessExitedStatus(pid, status); +#endif + } + break; + } + case SIGTERM: { // appswapn killed, use kill without parameter + HashMapTraverse(g_appSpawnContent->appMap, KillProcess, NULL); + LE_StopLoop(LE_GetDefaultLoop()); + break; + } + default: + APPSPAWN_LOGI("SigHandler, unsupported signal %d.", siginfo->ssi_signo); + break; + } +} + +static void ProcessTimer(const TimerHandle taskHandle, void *context) +{ + APPSPAWN_LOGI("timeout stop appspawn"); + LE_StopLoop(LE_GetDefaultLoop()); +} + +static void HandleSpecial(AppSpawnClientExt *appProperty) +{ + // special handle bundle name medialibrary and scanner + const char *specialBundleNames[] = { + "com.ohos.medialibrary.MediaLibraryDataA", + "com.ohos.medialibrary.MediaScannerAbilityA" + }; + for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) { + if (strcmp(appProperty->property.processName, specialBundleNames[i]) == 0) { + if (appProperty->property.gidCount < APP_MAX_GIDS) { + appProperty->property.gidTable[appProperty->property.gidCount] = GID_USER_DATA_RW; + appProperty->property.gidCount++; + } else { + APPSPAWN_LOGE("gidCount out of bounds !"); + } + break; + } + } +} + +static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty) +{ + int result = 0; + fd_set rd; + struct timeval tv; + FD_ZERO(&rd); + FD_SET(fd, &rd); + tv.tv_sec = TV_SEC; + tv.tv_usec = 0; + int ret = select(fd + 1, &rd, NULL, NULL, &tv); + if (ret == 0) { // timeout + APPSPAWN_LOGI("Time out for child %s %d fd %d", appProperty->property.processName, pid, fd); + result = 0; + } else if (ret == -1) { + APPSPAWN_LOGI("Error for child %s %d", appProperty->property.processName, pid); + result = 0; + } else { + (void)read(fd, &result, sizeof(result)); + } + return result; +} + +static void StartColdApp(const AppSpawnClientExt *appProperty) +{ + if (appProperty == NULL) { + return; + } + if (appProperty->property.flags & 0x01) { + char cold[10] = {0}; // 10 cold + ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); + APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); + if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { + appProperty->client.flags |= APP_COLD_START; + } + } +} + +static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) +{ +#ifdef NWEB_SPAWN + if (appProperty == NULL) { + return -1; + } + if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) { + int exitStatus = 0; + int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); + if (ret) { + SendResponse(appProperty, (char *)&ret, sizeof(ret)); + } else { + SendResponse(appProperty, (char *)&exitStatus, sizeof(exitStatus)); + } + APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s", + exitStatus, appProperty->property.pid, appProperty->property.uid, appProperty->property.processName, appProperty->property.bundleName); + return 0; + } +#endif + return -1; +} + +static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) +{ + APPSPAWN_CHECK(buffer != NULL && buffLen >= sizeof(AppParameter), LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Invalid buffer buffLen %u", buffLen); + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)LE_GetUserData(taskHandle); + APPSPAWN_CHECK(appProperty != NULL, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "alloc client Failed"); + int ret = memcpy_s(&appProperty->property, sizeof(appProperty->property), buffer, buffLen); + APPSPAWN_CHECK(ret == 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Invalid buffer buffLen %u", buffLen); + APPSPAWN_CHECK(appProperty->property.gidCount <= APP_MAX_GIDS && strlen(appProperty->property.processName) > 0, + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Invalid property %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; + } + + // cold start app + StartColdApp(appProperty); + + // create pipe for commication from child + if (pipe(appProperty->fd) == -1) { + APPSPAWN_LOGE("create pipe fail, errno = %d", errno); + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return; + } + APPSPAWN_LOGI("OnReceiveRequest client.id %d appProperty %d processname %s buffLen %d flags 0x%x", + appProperty->client.id, appProperty->property.uid, appProperty->property.processName, + buffLen, appProperty->property.flags); + + fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); + + // get render process termination status + APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); + + pid_t pid = 0; + int result = AppSpawnProcessMsg(&g_appSpawnContent->content, &appProperty->client, &pid); + if (result == 0) { // wait child process resutl + result = WaitChild(appProperty->fd[0], pid, appProperty); + } + close(appProperty->fd[0]); + close(appProperty->fd[1]); + APPSPAWN_LOGI("child process %s %s pid %d", + appProperty->property.processName, (result == 0) ? "success" : "fail", pid); + // send response + if (result == 0) { + AddAppInfo(pid, appProperty->property.processName); + SendResponse(appProperty, (char *)&pid, sizeof(pid)); + } else { + SendResponse(appProperty, (char *)&result, sizeof(result)); + } + if (g_appSpawnContent->timer == NULL && ((g_appSpawnContent->flags & FLAGS_ON_DEMAND) == FLAGS_ON_DEMAND)) { + 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, 30000, 1); // 30000 30s + } +} + +static int OnConnection(const LoopHandle loopHandle, const TaskHandle server) +{ + static uint32_t clientId = 0; + APPSPAWN_LOGI("OnConnection "); + APPSPAWN_CHECK(server != NULL, return -1, "Error server"); + + TaskHandle stream; + LE_StreamInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_CONNECT; + info.baseInfo.close = OnClose; + info.baseInfo.userDataSize = sizeof(AppSpawnClientExt); + info.disConntectComplete = NULL; + info.sendMessageComplete = SendMessageComplete; + info.recvMessage = OnReceiveRequest; + LE_STATUS ret = LE_AcceptStreamClient(LE_GetDefaultLoop(), server, &stream, &info); + APPSPAWN_CHECK(ret == 0, return -1, "Failed to alloc stream"); + AppSpawnClientExt *client = (AppSpawnClientExt *)LE_GetUserData(stream); + APPSPAWN_CHECK(client != NULL, return -1, "Failed to alloc stream"); + client->stream = stream; + client->client.id = ++clientId; + client->client.flags = 0; + APPSPAWN_LOGI("OnConnection client fd %d Id %d", LE_GetSocketFd(stream), client->client.id); + return 0; +} + +static int NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + int fd = appProperty->fd[1]; + APPSPAWN_LOGI("NotifyResToParent %s fd %d result %d", appProperty->property.processName, fd, result); + write(appProperty->fd[1], &result, sizeof(result)); + // close write + close(fd); + return 0; +} + +static void AppSpawnInit(AppSpawnContent *content) +{ + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content; + APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); + + APPSPAWN_LOGI("AppSpawnInit"); + if (content->loadExtendLib) { + content->loadExtendLib(content); + } + content->notifyResToParent = NotifyResToParent; + // set private function + SetContentFunction(content); +} + +void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]) +{ + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content; + APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); + + AppSpawnClientExt *client = (AppSpawnClientExt *)malloc(sizeof(AppSpawnClientExt)); + APPSPAWN_CHECK(client != NULL, return, "Failed to alloc memory for client"); + int ret = GetAppSpawnClientFromArg(argc, argv, client); + APPSPAWN_CHECK(ret == 0, free(client); + return, "Failed to get client from arg"); + APPSPAWN_LOGI("Cold running %d processName %s %u ", getpid(), client->property.processName, + content->longProcNameLen); + + ret = DoStartApp(content, &client->client, content->longProcName, content->longProcNameLen); + if (ret == 0 && content->runChildProcessor != NULL) { + content->runChildProcessor(content, &client->client); + } + APPSPAWN_LOGI("App exit %d.", getpid()); + free(client); + free(appSpawnContent); + g_appSpawnContent = NULL; +} + +static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) +{ + APPSPAWN_LOGI("AppSpawnRun"); + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content; + APPSPAWN_CHECK(appSpawnContent != NULL, return, "Invalid appspawn content"); + LE_STATUS status = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandler); + if (status == 0) { + status = LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD); + status = LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM); + } + if (status != 0) { + APPSPAWN_LOGE("Failed to add signal %d", status); + } + + LE_RunLoop(LE_GetDefaultLoop()); + APPSPAWN_LOGI("AppSpawnRun exit "); + LE_CloseSignalTask(LE_GetDefaultLoop(), appSpawnContent->sigHandler); + // release resource + HashMapDestory(appSpawnContent->appMap); + free(content); + g_appSpawnContent = NULL; +} + +static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) +{ + HashInfo hashInfo = { + AppInfoHashNodeCompare, + TestHashKeyCompare, + AppInfoHashNodeFunction, + AppInfoHashKeyFunction, + AppInfoHashNodeFree, + APP_HASH_BUTT + }; + int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to create hash for app"); + +} + +AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode) +{ + APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop"); + APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name"); + APPSPAWN_LOGI("AppSpawnCreateContent %s %u mode %d", socketName, longProcNameLen, mode); + + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)malloc(sizeof(AppSpawnContentExt)); + APPSPAWN_CHECK(appSpawnContent != NULL, return NULL, "Failed to alloc memory for appspawn"); + (void)memset_s(&appSpawnContent->content, sizeof(appSpawnContent->content), 0, sizeof(appSpawnContent->content)); + appSpawnContent->content.longProcName = longProcName; + appSpawnContent->content.longProcNameLen = longProcNameLen; + appSpawnContent->timer = NULL; + appSpawnContent->flags = 0; + appSpawnContent->server = NULL; + appSpawnContent->sigHandler = NULL; + appSpawnContent->content.initAppSpawn = AppSpawnInit; + + if (mode) { + appSpawnContent->flags |= FLAGS_MODE_COLD; + appSpawnContent->content.runAppSpawn = AppSpawnColdRun; + } else { + appSpawnContent->content.runAppSpawn = AppSpawnRun; + + // create hash for app + CreateHashForApp(appSpawnContent); + + char path[128] = {0}; // 128 max path + int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); + APPSPAWN_CHECK(ret >= 0, free(appSpawnContent); + return NULL, "Failed to snprintf_s %d", ret); + int socketId = GetControlSocket(socketName); + APPSPAWN_LOGI("get socket form env %s socketId %d", socketName, socketId); + if (socketId > 0) { + appSpawnContent->flags |= FLAGS_ON_DEMAND; + } + + LE_StreamServerInfo info = {}; + info.baseInfo.flags = TASK_STREAM | TASK_PIPE | TASK_SERVER; + info.socketId = socketId; + info.server = path; + info.baseInfo.close = NULL; + info.incommingConntect = OnConnection; + ret = LE_CreateStreamServer(LE_GetDefaultLoop(), &appSpawnContent->server, &info); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to create socket for %s", path); + // create socket + ret = chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to chmod %s, err %d. ", path, errno); + APPSPAWN_LOGI("AppSpawnCreateContent path %s fd %d", path, LE_GetSocketFd(appSpawnContent->server)); + } + g_appSpawnContent = appSpawnContent; + return &g_appSpawnContent->content; +} diff --git a/standard/appspawn_service.h b/standard/appspawn_service.h new file mode 100644 index 00000000..3ef432fd --- /dev/null +++ b/standard/appspawn_service.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APPSPAWN_SERVICE_H +#define APPSPAWN_SERVICE_H + +#include "appspawn_msg.h" +#include "appspawn_server.h" +#include "init_hashmap.h" +#include "loop_event.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define APP_HASH_BUTT 32 +#define FLAGS_ON_DEMAND 0x1 +#define FLAGS_MODE_COLD 0x2 +#define FLAGS_SANDBOX_PRIVATE 0x10 +#define FLAGS_SANDBOX_APP 0x20 + +#define START_INDEX 1 +#define FD_INDEX 2 +#define PARAM_INDEX 3 +#define NULL_INDEX 4 +#define PARAM_BUFFER_LEN 128 +typedef struct { + AppSpawnClient client; + TaskHandle stream; + int32_t fd[2]; // 2 fd count + AppParameter property; +} AppSpawnClientExt; + +typedef struct { + HashNode node; + pid_t pid; + char name[0]; +} AppInfo; + +typedef struct { + AppSpawnContent content; + uint32_t flags; + TaskHandle server; + SignalHandle sigHandler; + TimerHandle timer; + HashMapHandle appMap; // save app pid and name +} AppSpawnContentExt; + +void SetContentFunction(AppSpawnContent *content); +void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]); +int GetAppSpawnClientFromArg(int argc, char *const argv[], AppSpawnClientExt *client); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_SERVICE_H diff --git a/standard/main.c b/standard/main.c new file mode 100644 index 00000000..6d40789b --- /dev/null +++ b/standard/main.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "appspawn_adapter.h" +#include "appspawn_msg.h" +#include "appspawn_server.h" + +int main(int argc, char *const argv[]) +{ + if (argc <= 0) { + return 0; + } + uint32_t argvSize = 0; + char *buffer = (char *)argv[0]; + int mode = 0; + if ((argc > PARAM_INDEX) && (strcmp(argv[START_INDEX], "cold-start") == 0)) { + buffer = argv[0]; + argvSize = APP_LEN_PROC_NAME; + mode = 1; + } else { + // calculate child process long name size + uintptr_t start = (uintptr_t)argv[0]; + uintptr_t end = (uintptr_t)strchr(argv[argc - 1], 0); + if (end <= 0) { + return -1; + } + argvSize = end - start; + } + APPSPAWN_LOGI("AppSpawnCreateContent argc %d mode %d %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); + content->runAppSpawn(content, argc, argv); + return 0; +} diff --git a/test/BUILD.gn b/test/BUILD.gn index 85ce8df3..30ab969b 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -18,11 +18,9 @@ group("unittest") { testonly = true deps = [ - "unittest/app_spawn_msg_peer_test:unittest", - "unittest/app_spawn_server_test:unittest", "unittest/app_spawn_socket_test:unittest", + "unittest/app_spawn_standard_test:unittest", "unittest/client_socket_test:unittest", - "unittest/server_socket_test:unittest", ] } @@ -39,7 +37,7 @@ config("appspawn_test_config") { include_dirs = [ "${appspawn_path}/test/mock/include", - "${appspawn_path}/src/include", + "${appspawn_path}/common", "${appspawn_path}/interfaces/innerkits/include", ] } @@ -66,6 +64,8 @@ ohos_source_set("appspawn_test_source") { external_deps = [ "ability_base:want", + "bundle_framework:appexecfwk_base", + "bundle_framework:appexecfwk_core", "hiviewdfx_hilog_native:libhilog", ] } diff --git a/test/mock/include/mock_server_socket.h b/test/mock/include/mock_server_socket.h deleted file mode 100644 index 0c3c2ff3..00000000 --- a/test/mock/include/mock_server_socket.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2021-2022 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 "server_socket.h" -#include "client_socket.h" - -#include "gmock/gmock.h" -#include "securec.h" -#include "hilog/log.h" - -namespace OHOS { -namespace AppSpawn { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MockServerSocket"}; - -class MockServerSocket : public ServerSocket { -public: - MockServerSocket() = delete; - virtual ~MockServerSocket() = default; - MockServerSocket(const std::string &server) : ServerSocket(server){}; - - MOCK_METHOD1(SaveConnection, void(int32_t connectFd)); - MOCK_METHOD1(CloseConnection, void(int32_t connectFd)); - MOCK_METHOD0(CloseServer, void()); - MOCK_METHOD0(CloseServerMonitor, void()); - MOCK_METHOD0(RegisterServerSocket, int32_t()); - MOCK_METHOD0(WaitForConnection, int32_t()); - MOCK_METHOD1(VerifyConnection, int32_t(int32_t connectFd)); - MOCK_METHOD3(ReadSocketMessage, int32_t(int32_t socketFd, void *buf, int32_t len)); - MOCK_METHOD3(WriteSocketMessage, int32_t(int32_t socketFd, const void *buf, int32_t len)); - - int32_t ReadImplGidCountMax([[maybe_unused]] int32_t socketFd, void *buf, [[maybe_unused]] int32_t len) - { - std::lock_guard lock(mutex_); - - // assign AppProperty - ClientSocket::AppProperty *params = static_cast(buf); - if (params == nullptr) { - return 0; - } - params->uid = 0; - params->gid = 0; - auto ret = memset_s(params->gidTable, sizeof(params->gidTable), 0, sizeof(params->gidTable)); - if (ret != EOK) { - HiLog::Info(LABEL, "memset_s failed"); - return 0; - } - params->gidCount = ClientSocket::MAX_GIDS + 1; - std::string processName = "processName"; - ret = memcpy_s(params->processName, sizeof(params->processName), processName.c_str(), processName.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - std::string soPath = "soPath"; - ret = memcpy_s(params->soPath, sizeof(params->soPath), soPath.c_str(), soPath.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - - return sizeof(ClientSocket::AppProperty); - } - - int32_t ReadImplProcessName([[maybe_unused]] int32_t socketFd, void *buf, [[maybe_unused]] int32_t len) - { - std::lock_guard lock(mutex_); - - // assign AppProperty - ClientSocket::AppProperty *params = static_cast(buf); - if (params == nullptr) { - return 0; - } - params->uid = 0; - params->gid = 0; - auto ret = memset_s(params->gidTable, sizeof(params->gidTable), 0, sizeof(params->gidTable)); - if (ret != EOK) { - HiLog::Info(LABEL, "memset_s failed"); - return 0; - } - params->gidCount = ClientSocket::MAX_GIDS; - std::string processName = ""; - ret = memcpy_s(params->processName, sizeof(params->processName), processName.c_str(), processName.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - std::string soPath = "soPath"; - ret = memcpy_s(params->soPath, sizeof(params->soPath), soPath.c_str(), soPath.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - - return sizeof(ClientSocket::AppProperty); - } - - int32_t ReadImplValid([[maybe_unused]] int32_t socketFd, void *buf, [[maybe_unused]] int32_t len) - { - std::lock_guard lock(mutex_); - - // assign AppProperty - ClientSocket::AppProperty *params = static_cast(buf); - if (params == nullptr) { - return 0; - } - params->uid = 0; - params->gid = 0; - auto ret = memset_s(params->gidTable, sizeof(params->gidTable), 0, sizeof(params->gidTable)); - if (ret != EOK) { - HiLog::Info(LABEL, "memset_s failed"); - return 0; - } - params->gidCount = ClientSocket::MAX_GIDS; - std::string processName = "processName"; - ret = memcpy_s(params->processName, sizeof(params->processName), processName.c_str(), processName.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - std::string soPath = "soPath"; - ret = memcpy_s(params->soPath, sizeof(params->soPath), soPath.c_str(), soPath.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - - return sizeof(ClientSocket::AppProperty); - } - - int32_t ReadImplValidLongProcessName([[maybe_unused]] int32_t socketFd, void *buf, [[maybe_unused]] int32_t len) - { - std::lock_guard lock(mutex_); - - // assign AppProperty - ClientSocket::AppProperty *params = static_cast(buf); - if (params == nullptr) { - return 0; - } - params->uid = 0; - params->gid = 0; - auto ret = memset_s(params->gidTable, sizeof(params->gidTable), 0, sizeof(params->gidTable)); - if (ret != EOK) { - HiLog::Info(LABEL, "memset_s failed"); - return 0; - } - params->gidCount = ClientSocket::MAX_GIDS; - std::string processName = "ProcessName1234567890"; - ret = memcpy_s(params->processName, sizeof(params->processName), processName.c_str(), processName.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - std::string soPath = "soPath"; - ret = memcpy_s(params->soPath, sizeof(params->soPath), soPath.c_str(), soPath.length()); - if (ret != EOK) { - HiLog::Info(LABEL, "memcpy_s failed"); - return 0; - } - - return sizeof(ClientSocket::AppProperty); - } - -private: - std::mutex mutex_; -}; -} // namespace AppSpawn -} // namespace OHOS diff --git a/test/mock/src/appspawn_msg_peer.cpp b/test/mock/src/appspawn_msg_peer.cpp deleted file mode 100644 index a488e181..00000000 --- a/test/mock/src/appspawn_msg_peer.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "appspawn_msg_peer.h" - -#include - -#include "hilog/log.h" -#include "securec.h" - -namespace OHOS { -namespace AppSpawn { -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "MockAppSpawnMsgPeer"}; - -AppSpawnMsgPeer::AppSpawnMsgPeer(const std::shared_ptr &socket, int connectFd) - : connectFd_(connectFd), socket_(socket) -{ - buf_ = std::make_unique(sizeof(ClientSocket::AppProperty)); - if (buf_ == nullptr) { - HiLog::Error(LABEL, "buf_ is null pointer!"); - } -} - -AppSpawnMsgPeer::~AppSpawnMsgPeer() -{ - connectFd_ = -1; -} - -ClientSocket::AppProperty *AppSpawnMsgPeer::GetMsg() const -{ - HiLog::Info(LABEL, "GetMsg"); - if (buf_ != nullptr) { - ClientSocket::AppProperty *appProperty = reinterpret_cast(buf_.get()); - appProperty->uid = 0; - appProperty->gid = 0; - auto ret = memset_s(appProperty->gidTable, sizeof(appProperty->gidTable), 0, sizeof(appProperty->gidTable)); - if (ret != EOK) { - HiLog::Error(LABEL, "memset_s failed!"); - return nullptr; - } - appProperty->gidCount = ClientSocket::MAX_GIDS; - std::string processName = "processName"; - ret = memcpy_s( - appProperty->processName, sizeof(appProperty->processName), processName.c_str(), processName.length()); - if (ret != EOK) { - HiLog::Error(LABEL, "memcpy_s failed!"); - return nullptr; - } - std::string soPath = "soPath"; - ret = memcpy_s(appProperty->soPath, sizeof(appProperty->soPath), soPath.c_str(), soPath.length()); - if (ret != EOK) { - HiLog::Error(LABEL, "memcpy_s failed!"); - return nullptr; - } - } - - return reinterpret_cast(buf_.get()); -} - -int AppSpawnMsgPeer::GetConnectFd() const -{ - HiLog::Info(LABEL, "GetConnectFd"); - return 0; -} - -int AppSpawnMsgPeer::Response(pid_t pid) -{ - HiLog::Info(LABEL, "Response"); - return 0; -} - -int AppSpawnMsgPeer::MsgPeer() -{ - HiLog::Info(LABEL, "MsgPeer"); - return 0; -} -} // namespace AppSpawn -} // namespace OHOS diff --git a/test/moduletest/BUILD.gn b/test/moduletest/BUILD.gn index 4c5c0a2f..dd1763fe 100644 --- a/test/moduletest/BUILD.gn +++ b/test/moduletest/BUILD.gn @@ -23,6 +23,7 @@ ohos_moduletest("AppSpawnModuleTest") { "//utils/native/base/include", "//third_party/zlib/contrib/minizip", "//third_party/zlib", + "${appexecfwk_path}/interfaces/innerkits/appexecfwk_base/include", ] configs = [ @@ -33,6 +34,7 @@ ohos_moduletest("AppSpawnModuleTest") { deps = [ "${aafwk_path}/interfaces/innerkits/app_manager:app_manager", "${aafwk_path}/services/appmgr:libams", + "${appexecfwk_path}/interfaces/innerkits/appexecfwk_core:appexecfwk_core", "${appspawn_path}/interfaces/innerkits:appspawn_socket_client", "//third_party/googletest:gtest_main", "//utils/native/base:utils", diff --git a/test/moduletest/appspawn_module_test.cpp b/test/moduletest/appspawn_module_test.cpp index 814eee3e..2f232c46 100644 --- a/test/moduletest/appspawn_module_test.cpp +++ b/test/moduletest/appspawn_module_test.cpp @@ -72,11 +72,11 @@ bool readFileInfo(char *buffer, const int32_t &pid, const char *fileName) // Set file path char filePath[FILE_PATH_SIZE]; if (sprintf_s(filePath, sizeof(filePath), "/proc/%d/%s", pid, fileName) <= 0) { - HiLog::Error(LABEL, "filePath sprintf_s failed."); + HiLog::Error(LABEL, "filePath sprintf_s fail ."); return CHECK_ERROR; } if (!checkFileIsExists(filePath)) { - HiLog::Error(LABEL, "file %{public}s not exists.", fileName); + HiLog::Error(LABEL, "file %{public}s is not exists .", fileName); return CHECK_ERROR; } // Open file @@ -207,7 +207,7 @@ bool checkProcName(const int32_t &pid, const AppSpawnStartMsg ¶ms) FILE *fp = nullptr; char cmd[CMD_SIZE]; if (sprintf_s(cmd, sizeof(cmd), "ps -o ARGS=CMD -p %d |grep -v CMD", pid) <= 0) { - HiLog::Error(LABEL, "cmd sprintf_s failed."); + HiLog::Error(LABEL, "cmd sprintf_s fail ."); return CHECK_ERROR; } if(strlen(cmd) > CMD_SIZE) { @@ -246,12 +246,12 @@ bool checkProcessIsDestroyed(const int32_t &pid) { char filePath[FILE_PATH_SIZE]; if (sprintf_s(filePath, sizeof(filePath), "/proc/%d", pid) <= 0) { - HiLog::Error(LABEL, "filePath sprintf_s failed."); + HiLog::Error(LABEL, "filePath sprintf_s fail ."); return CHECK_ERROR; } if (checkFileIsExists(filePath)) { - HiLog::Error(LABEL, "File %{public}d not exists.", pid); + HiLog::Error(LABEL, "File %{public}d is not exists .", pid); return CHECK_ERROR; } @@ -332,7 +332,8 @@ void AppSpawnModuleTest::TearDownTestCase() void AppSpawnModuleTest::SetUp() { newPid = 0; - if (memset_s(buffer, sizeof(buffer), 0x00, BUFFER_SIZE) != EOK) { + auto ret = memset_s(buffer, sizeof(buffer), 0x00, BUFFER_SIZE); + if (ret != EOK) { HiLog::Error(LABEL, "memset_s is failed."); } } @@ -365,7 +366,7 @@ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_001, TestSize.Level0) * FunctionPoints: Process start message monitoring. * EnvConditions: AppSpawn main process has started. * The socket server has been established. - * CaseDescription: 1. Establish a socket client and connect with the AppSpawn server + * CaseDescription: 1. Establish a socket client and connect with the Appspawn server */ HWTEST_F(AppSpawnModuleTest, AppSpawn_HF_listen_002, TestSize.Level0) { diff --git a/test/unittest/app_spawn_msg_peer_test/BUILD.gn b/test/unittest/app_spawn_lite_test/BUILD.gn similarity index 44% rename from test/unittest/app_spawn_msg_peer_test/BUILD.gn rename to test/unittest/app_spawn_lite_test/BUILD.gn index 380c77c4..5cf2eccf 100644 --- a/test/unittest/app_spawn_msg_peer_test/BUILD.gn +++ b/test/unittest/app_spawn_lite_test/BUILD.gn @@ -10,30 +10,37 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +import("//build/lite/config/component/lite_component.gni") +import("//build/lite/config/test.gni") + +unittest("AppSpawnLiteTest") { + output_extension = "bin" + output_dir = "$root_out_dir/test/unittest/startup" + ldflags = [ + "-lstdc++", + "-lpthread", + "-lm", + ] -import("//base/startup/appspawn_standard/appspawn.gni") -import("//build/test.gni") - -ohos_unittest("AppSpawnMsgPeerTest") { - module_out_path = "${module_output_path}" + include_dirs = [ + "//base/startup/appspawn_standard/lite/", + "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog", + "//third_party/bounds_checking_function/include/", + "//third_party/cJSON", + ] sources = [ - "${appspawn_path}/src/appspawn_msg_peer.cpp", - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/server_socket.cpp", + "//base/startup/appspawn_standard/lite/appspawn_message.c", + "app_spawn_lite_test.cpp", ] - sources += [ "app_spawn_msg_peer_test.cpp" ] - - configs = [ "${appspawn_path}:appspawn_config" ] - - deps = [ "${appspawn_path}/test:appspawn_test_source" ] - - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + deps = [ + "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//build/lite/config/component/cJSON:cjson_shared", + "//third_party/bounds_checking_function:libsec_shared", + ] } group("unittest") { - testonly = true - - deps = [ ":AppSpawnMsgPeerTest" ] + deps = [ ":appspawn_test" ] } diff --git a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp new file mode 100644 index 00000000..f07e7243 --- /dev/null +++ b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include +#include "gtest/gtest.h" +#include "appspawn_message.h" + +using namespace testing::ext; + +namespace OHOS { +const unsigned int MALLOC_TEST_LENGTH = 10; +const long NANOSECONDS_PER_SECOND = 1000000000; +const int TEST_UID = 999; +const int TEST_GID = 888; +std::vector g_badStrings; +std::vector g_goodStrings; + +class AppSpawnLiteTest : public testing::Test { +public: + static void SetUpTestCase() + { + // empty + g_badStrings.push_back(std::string("")); + // not json + g_badStrings.push_back(std::string("abcdefghijklmnopqrstuvwxyz")); + g_badStrings.push_back(std::string("0123456789876543210")); + g_badStrings.push_back(std::string("xxxx")); + g_badStrings.push_back(std::string("xxxxssssssssssssssssssss")); + g_badStrings.push_back(std::string("\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"")); + g_badStrings.push_back(std::string(".............................................")); + g_badStrings.push_back(std::string("....%%%....^..***@##.../*--++......$$&&.....")); + // looks like json but format error + g_badStrings.push_back(std::string( + "{bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName:\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV,\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID:\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1,\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID:10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID:10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability:[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]")); + g_badStrings.push_back(std::string( + "\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\"\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\"\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\"\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\"\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\"10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\"10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\"[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]},")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0],}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0,]}")); + // json format correct but fields missing + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000}")); + // field value invalid + g_badStrings.push_back(std::string( + "{\"bundleName\":\"\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":-1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":-1000,\"capability\":[-7]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":1}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0, 3, -9]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[99999999]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":1234,\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":\"1000\",\"gID\":1000,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":\"1000\",\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":\"0\"}")); + g_badStrings.push_back(std::string( + "{\"bundleName\": 250,\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_goodStrings.push_back(std::string( + "{\"bundleName\":\"testvalid1\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); + g_goodStrings.push_back(std::string( + "{\"bundleName\":\"testvalid2\",\"identityID\":\"5678\",\"uID\":1001,\"gID\":1001,\"capability\":[3,5]}")); + g_goodStrings.push_back(std::string( + "{\"bundleName\":\"testvalid3\",\"identityID\":\"91011\",\"uID\":1002,\"gID\":1002,\"capability\":[8,9]}")); + g_goodStrings.push_back(std::string( + "{\"bundleName\":\"testvalid3\",\"identityID\":\"999\",\"uID\":1002,\"gID\":1002,\"capability\":[]}")); + g_goodStrings.push_back(std::string( + "{\"bundleName\":\"testvalid3\",\"identityID\":\"3\",\"uID\":1002,\"gID\":1002,\"capability\":[1,2]}")); + printf("[----------] AppSpawnLiteTest, message func test setup.\n"); + } + + static void TearDownTestCase() + { + g_badStrings.clear(); + g_goodStrings.clear(); + printf("[----------] AppSpawnLiteTest, message func test teardown.\n"); + } + void SetUp() {} + void TearDown() {} +}; + +/* + ** @tc.name: msgFuncFreeTest_001 + ** @tc.desc: free message struct function, nullptr test + ** @tc.type: FUNC + ** @tc.require: AR000F733K + ** @tc.author: ZAL + **/ +HWTEST_F(AppSpawnLiteTest, msgFuncFreeTest_001, TestSize.Level1) +{ + // do not crash here + FreeMessageSt(nullptr); + + MessageSt msgSt = {0}; + FreeMessageSt(&msgSt); + + EXPECT_EQ(msgSt.bundleName, nullptr); + EXPECT_EQ(msgSt.identityID, nullptr); + EXPECT_EQ(msgSt.caps, nullptr); + EXPECT_EQ(msgSt.uID, -1); + EXPECT_EQ(msgSt.gID, -1); + EXPECT_EQ(msgSt.capsCnt, 0); +} + +/* + ** @tc.name: msgFuncFreeTest_002 + ** @tc.desc: free message struct function, function test + ** @tc.type: FUNC + ** @tc.require: AR000F733K + ** @tc.author: ZAL + **/ +HWTEST_F(AppSpawnLiteTest, msgFuncFreeTest_002, TestSize.Level1) +{ + MessageSt msgSt = {0}; + + msgSt.capsCnt = MALLOC_TEST_LENGTH; + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.capsCnt, 0); + + msgSt.uID = TEST_UID; + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.uID, -1); + + msgSt.gID = TEST_GID; + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.gID, -1); + + msgSt.bundleName = (char*)malloc(MALLOC_TEST_LENGTH); + EXPECT_TRUE(msgSt.bundleName != nullptr); + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.bundleName, nullptr); + + msgSt.identityID = (char*)malloc(MALLOC_TEST_LENGTH); + EXPECT_TRUE(msgSt.identityID != nullptr); + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.identityID, nullptr); + + msgSt.caps = (unsigned int*)malloc(MALLOC_TEST_LENGTH * sizeof(unsigned int)); + EXPECT_TRUE(msgSt.caps != nullptr); + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.caps, nullptr); + + // full test + msgSt.bundleName = (char*)malloc(MALLOC_TEST_LENGTH); + msgSt.identityID = (char*)malloc(MALLOC_TEST_LENGTH); + msgSt.caps = (unsigned int*)malloc(MALLOC_TEST_LENGTH * sizeof(unsigned int)); + EXPECT_TRUE(msgSt.bundleName != nullptr); + EXPECT_TRUE(msgSt.identityID != nullptr); + EXPECT_TRUE(msgSt.caps != nullptr); + + msgSt.capsCnt = MALLOC_TEST_LENGTH; + msgSt.uID = TEST_UID; + msgSt.gID = TEST_GID; + + FreeMessageSt(&msgSt); + EXPECT_EQ(msgSt.bundleName, nullptr); + EXPECT_EQ(msgSt.identityID, nullptr); + EXPECT_EQ(msgSt.caps, nullptr); + EXPECT_EQ(msgSt.capsCnt, 0); + EXPECT_EQ(msgSt.uID, -1); + EXPECT_EQ(msgSt.gID, -1); +} + +static void GetCurrentTime(struct timespec* tmCur) +{ + if (tmCur == nullptr) { + return; + } + if (clock_gettime(CLOCK_REALTIME, tmCur) != 0) { + printf("[----------] AppSpawnLiteTest, get time failed! err %d.\n", errno); + } +} + +/* + ** @tc.name: msgFuncSplitTest_001 + ** @tc.desc: split message function, bad strings test + ** @tc.type: FUNC + ** @tc.require: AR000F733K + ** @tc.author: ZAL + **/ +HWTEST_F(AppSpawnLiteTest, msgFuncSplitTest_001, TestSize.Level1) +{ + MessageSt msgSt = {0}; + EXPECT_NE(SplitMessage(nullptr, 0, nullptr), 0); + EXPECT_NE(SplitMessage(nullptr, 0, &msgSt), 0); + + std::string testMsg = "xxxxxxxx"; + EXPECT_NE(SplitMessage(testMsg.c_str(), testMsg.length(), nullptr), 0); + + struct timespec tmStart = {0}; + GetCurrentTime(&tmStart); + + for (size_t i = 0; i < g_badStrings.size(); ++i) { + int ret = SplitMessage(g_badStrings[i].c_str(), g_badStrings[i].length(), &msgSt); + EXPECT_NE(ret, 0); + if (ret == 0) { + printf("[----------] AppSpawnLiteTest, msgFuncSplitTest_001 i = %u.\n", i); + FreeMessageSt(&msgSt); + } + } + + struct timespec tmEnd = {0}; + GetCurrentTime(&tmEnd); + long timeUsed = (tmEnd.tv_sec - tmStart.tv_sec) * NANOSECONDS_PER_SECOND + (tmEnd.tv_nsec - tmStart.tv_nsec); + printf("[----------] AppSpawnLiteTest, msgFuncSplitTest_001, total time %ld ns, strCnt %u.\n", \ + timeUsed, g_badStrings.size()); +} + +/* + ** @tc.name: msgFuncSplitTest_002 + ** @tc.desc: split message function, good strings test + ** @tc.type: FUNC + ** @tc.require: AR000F733K + ** @tc.author: ZAL + **/ +HWTEST_F(AppSpawnLiteTest, msgFuncSplitTest_002, TestSize.Level1) +{ + MessageSt msgSt = {0}; + + struct timespec tmStart = {0}; + GetCurrentTime(&tmStart); + + for (size_t i = 0; i < g_goodStrings.size(); ++i) { + int ret = SplitMessage(g_goodStrings[i].c_str(), g_goodStrings[i].length(), &msgSt); + EXPECT_EQ(ret, 0); + if (ret != 0) { + printf("[----------] AppSpawnLiteTest, msgFuncSplitTest_002 i = %u.\n", i); + } else { + FreeMessageSt(&msgSt); + } + } + + struct timespec tmEnd = {0}; + GetCurrentTime(&tmEnd); + + long timeUsed = (tmEnd.tv_sec - tmStart.tv_sec) * NANOSECONDS_PER_SECOND + (tmEnd.tv_nsec - tmStart.tv_nsec); + printf("[----------] AppSpawnLiteTest, msgFuncSplitTest_002, total time %ld ns, strCnt %u.\n", \ + timeUsed, g_goodStrings.size()); + + // parse one good string and check all results + std::string validStr = + "{\"bundleName\":\"validName\",\"identityID\":\"135\",\"uID\":999,\"gID\":888,\"capability\":[0, 1, 5]}"; + int ret = SplitMessage(validStr.c_str(), validStr.length(), &msgSt); + EXPECT_EQ(ret, 0); + + std::vector caps; + caps.push_back(0); // 0, test capability + caps.push_back(1); // 1, test capability + caps.push_back(5); // 5, test capability + + EXPECT_NE(msgSt.bundleName, nullptr); + EXPECT_NE(msgSt.identityID, nullptr); + EXPECT_EQ(strcmp("validName", msgSt.bundleName), 0); + EXPECT_EQ(strcmp("135", msgSt.identityID), 0); + EXPECT_EQ(TEST_UID, msgSt.uID); + EXPECT_EQ(TEST_GID, msgSt.gID); + EXPECT_EQ(caps.size(), msgSt.capsCnt); + EXPECT_NE(msgSt.caps, nullptr); + for (size_t i = 0; i < caps.size(); ++i) { + EXPECT_EQ(caps[i], msgSt.caps[i]); + } + FreeMessageSt(&msgSt); +} + +HWTEST_F(AppSpawnLiteTest, SetContentFunctionTest_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "SetContentFunctionTest_001 start"; + AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", NULL, 0, 0); + SetContentFunction(content); + char *longProcName = "SetContentFunctionTest_001"; + int64_t longProcNameLen = 1024; + + std::unique_ptr clientExt = std::make_unique(); + clientExt->client.id = 1; + clientExt->client.flag = 0; + clientExt->fd[0] = 123; + clientExt->fd[1] = 456; + clientExt->property.uid = 10002; + clientExt->property.gid = 1000; + clientExt->property.gidCount = 1; + strcpy_s(clientExt->property.processName, APP_LEN_PROC_NAME, "com.ohos.settingsdata"); + strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "com.ohos.settingsdata"); + strcpy_s(clientExt->property.soPath, APP_LEN_SO_PATH, " "); + clientExt->property.accessTokenId = 671201800; + strcpy_s(clientExt->property.apl, APP_APL_MAX_LEN, "system_core"); + strcpy_s(clientExt->property.renderCmd, APP_RENDER_CMD_MAX_LEN, " "); + + clientExt->property.flags = 0; + + content->setProcessName(content, clientExt->client, longProcName, longProcNameLen); + content->setKeepCapabilities(content, clientExt->client); + content->setUidGid(content, clientExt->client); + content->setCapabilities(content, clientExt->client); + content->runChildProcessor(content, clientExt->client); + + GTEST_LOG_(INFO) << "SetContentFunctionTest_001 end"; +} +} // namespace OHOS \ No newline at end of file diff --git a/test/unittest/app_spawn_msg_peer_test/app_spawn_msg_peer_test.cpp b/test/unittest/app_spawn_msg_peer_test/app_spawn_msg_peer_test.cpp deleted file mode 100644 index 518fdab7..00000000 --- a/test/unittest/app_spawn_msg_peer_test/app_spawn_msg_peer_test.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "mock_server_socket.h" -#include "appspawn_msg_peer.h" -#include "server_socket.h" - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppSpawn; - -class AppSpawnMsgPeerTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void AppSpawnMsgPeerTest::SetUpTestCase() -{} - -void AppSpawnMsgPeerTest::TearDownTestCase() -{} - -void AppSpawnMsgPeerTest::SetUp() -{} - -void AppSpawnMsgPeerTest::TearDown() -{} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: GetConnectFd & GetMsg - * FunctionPoints: simple function branch coverage - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify if new AppSpawnMsgPeer with the invalid params and the function GetConnectFd and GetMsg will - * return default value. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_001, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_001 start"; - - std::shared_ptr serverSocket = std::make_shared("ServerSocket"); - int32_t connectFd = -1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(serverSocket, connectFd); - - EXPECT_EQ(-1, appSpawnMsgPeer->GetConnectFd()); - EXPECT_EQ(nullptr, appSpawnMsgPeer->GetMsg()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_001 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: MsgPeer - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function MsgPeer can check the invalid connect fd. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_002, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_002 start"; - - std::shared_ptr serverSocket = std::make_shared("ServerSocket"); - int32_t connectFd = -1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(serverSocket, connectFd); - - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->MsgPeer()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_002 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: MsgPeer - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function MsgPeer can check the invalid server socket. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_003, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_003 start"; - - std::shared_ptr serverSocket = nullptr; - int32_t connectFd = 1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(serverSocket, connectFd); - - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->MsgPeer()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_003 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: Response - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function Response can check the invalid connect fd. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_004, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_004 start"; - - std::shared_ptr serverSocket = std::make_shared("ServerSocket"); - int32_t connectFd = -1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(serverSocket, connectFd); - - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->Response(1)); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_004 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: Response - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function Response can check the invalid server socket. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_005, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_005 start"; - - std::shared_ptr serverSocket = nullptr; - int32_t connectFd = 1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(serverSocket, connectFd); - - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->Response(1)); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_005 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: MsgPeer - * FunctionPoints: read socket message - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function MsgPeer can check the the invalid message read. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_006, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_006 start"; - - std::shared_ptr mockServerSocket = std::make_shared("MockServerSocket"); - int32_t connectFd = 1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(mockServerSocket, connectFd); - - EXPECT_CALL(*mockServerSocket, ReadSocketMessage(_, _, _)).WillOnce(Return(-1)); - EXPECT_CALL(*mockServerSocket, CloseConnection(_)).WillOnce(Return()); - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->MsgPeer()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_006 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: MsgPeer - * FunctionPoints: read socket message - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function MsgPeer can check the the too long message read. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_007, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_007 start"; - - std::shared_ptr mockServerSocket = std::make_shared("MockServerSocket"); - int32_t connectFd = 1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(mockServerSocket, connectFd); - - EXPECT_CALL(*mockServerSocket, ReadSocketMessage(_, _, _)).WillOnce(Return(sizeof(ClientSocket::AppProperty) + 1)); - EXPECT_CALL(*mockServerSocket, CloseConnection(_)).WillOnce(Return()); - EXPECT_EQ(-EINVAL, appSpawnMsgPeer->MsgPeer()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_007 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnMsgPeer - * SubFunction: MsgPeer - * FunctionPoints: read socket message - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function MsgPeer read socket message. - */ -HWTEST(AppSpawnMsgPeerTest, App_Spawn_Msg_Peer_008, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_008 start"; - - std::shared_ptr mockServerSocket = std::make_shared("MockServerSocket"); - int32_t connectFd = 1; - std::unique_ptr appSpawnMsgPeer = std::make_unique(mockServerSocket, connectFd); - - EXPECT_EQ(nullptr, appSpawnMsgPeer->GetMsg()); - EXPECT_CALL(*mockServerSocket, ReadSocketMessage(_, _, _)) - .WillOnce(Invoke(mockServerSocket.get(), &MockServerSocket::ReadImplValid)); - EXPECT_CALL(*mockServerSocket, CloseConnection(_)).WillOnce(Return()); - EXPECT_EQ(0, appSpawnMsgPeer->MsgPeer()); - EXPECT_NE(nullptr, appSpawnMsgPeer->GetMsg()); - - GTEST_LOG_(INFO) << "App_Spawn_Msg_Peer_008 end"; -} diff --git a/test/unittest/app_spawn_server_test/BUILD.gn b/test/unittest/app_spawn_server_test/BUILD.gn deleted file mode 100644 index 7d70e2c7..00000000 --- a/test/unittest/app_spawn_server_test/BUILD.gn +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2021-2022 Huawei Device Co., Ltd. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import("//base/startup/appspawn_standard/appspawn.gni") -import("//build/test.gni") - -ohos_unittest("AppSpawnServerOverrideTest") { - module_out_path = "${module_output_path}" - - include_dirs = [ - "//base/security/access_token/interfaces/innerkits/token_setproc/include", - "//base/startup/init_lite/services/log", - "//base/startup/init_lite/interfaces/innerkits/include", - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", - ] - - sources = [ - "${appspawn_path}/src/appspawn_server.cpp", - "${appspawn_path}/src/socket/appspawn_socket.cpp", - ] - - sources += [ - "${appspawn_path}/test/mock/src/appspawn_msg_peer.cpp", - "${appspawn_path}/test/mock/src/main_thread.cpp", - "${appspawn_path}/test/mock/src/server_socket.cpp", - "app_spawn_server_override_test.cpp", - ] - - deps = [ - "${appspawn_path}/test:appspawn_test_source", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", - "//base/startup/init_lite/interfaces/innerkits:libbegetutil", - "//base/startup/init_lite/services/log:init_log", - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", - ] - - external_deps = [ - "ability_base:want", - "hilog_native:libhilog", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - "safwk:system_ability_fwk", - "samgr_standard:samgr_proxy", - ] - - if (build_selinux) { - external_deps += [ "selinux:libhap_restorecon" ] - cflags = [ "-DWITH_SELINUX" ] - } -} - -ohos_unittest("AppSpawnServerMockTest") { - module_out_path = "${module_output_path}" - - include_dirs = [ - "//base/security/access_token/interfaces/innerkits/token_setproc/include", - "//base/startup/init_lite/services/log", - "//base/startup/init_lite/interfaces/innerkits/include", - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara/include", - ] - - sources = [ - "${appspawn_path}/src/appspawn_msg_peer.cpp", - "${appspawn_path}/src/appspawn_server.cpp", - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/server_socket.cpp", - ] - - sources += [ - "${appspawn_path}/test/mock/src/main_thread.cpp", - "app_spawn_server_mock_test.cpp", - ] - - deps = [ - "${appspawn_path}/test:appspawn_test_source", - "//base/security/access_token/interfaces/innerkits/token_setproc:libtoken_setproc", - "//base/startup/init_lite/interfaces/innerkits:libbegetutil", - "//base/startup/init_lite/interfaces/innerkits/socket:libsocket_static", - "//base/startup/init_lite/services/log:init_log", - "//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara", - ] - - external_deps = [ - "ability_base:want", - "hilog_native:libhilog", - "hiviewdfx_hilog_native:libhilog", - "ipc:ipc_core", - "safwk:system_ability_fwk", - "samgr_standard:samgr_proxy", - ] - - if (build_selinux) { - external_deps += [ "selinux:libhap_restorecon" ] - cflags = [ "-DWITH_SELINUX" ] - } -} - -group("unittest") { - testonly = true - - deps = [ - ":AppSpawnServerMockTest", - ":AppSpawnServerOverrideTest", - ] -} diff --git a/test/unittest/app_spawn_server_test/app_spawn_server_mock_test.cpp b/test/unittest/app_spawn_server_test/app_spawn_server_mock_test.cpp deleted file mode 100644 index cb6dd3be..00000000 --- a/test/unittest/app_spawn_server_test/app_spawn_server_mock_test.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "mock_server_socket.h" - -// redefine private and protected since testcase need to invoke and test private function -#define private public -#define protected public -#include "appspawn_server.h" -#undef private -#undef protected - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppSpawn; - -static constexpr int TEST_WAIT_TIME = 50 * 1000; // 50 ms - -class AppSpawnServerMockTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -protected: - std::unique_ptr appSpawnServer_ = nullptr; - std::shared_ptr mockServerSocket_ = nullptr; -}; - -void AppSpawnServerMockTest::SetUpTestCase() -{} - -void AppSpawnServerMockTest::TearDownTestCase() -{} - -void AppSpawnServerMockTest::SetUp() -{ - if (mockServerSocket_ == nullptr) { - mockServerSocket_ = std::make_shared("MockServerSocket"); - } - - if (appSpawnServer_ == nullptr) { - appSpawnServer_ = std::make_unique("AppSpawnServerMockTest"); - appSpawnServer_->SetServerSocket(mockServerSocket_); - } -} - -void AppSpawnServerMockTest::TearDown() -{} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: ServerMain - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify if the socket name is empty, the function ServerMain start fail. - */ -HWTEST_F(AppSpawnServerMockTest, App_Spawn_Server_001, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_001 start"; - - std::unique_ptr appSpawnServer = std::make_unique(""); - char argv[20] = "LongNameTest"; - EXPECT_EQ(false, appSpawnServer->ServerMain(argv, sizeof(argv))); - - GTEST_LOG_(INFO) << "App_Spawn_Server_001 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: ServerMain - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function ServerMain can check the gidcount > max. - */ -HWTEST_F(AppSpawnServerMockTest, App_Spawn_Server_002, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_002 start"; - - char argv[20] = "LongNameTest"; - - testing::Mock::AllowLeak(mockServerSocket_.get()); - EXPECT_CALL(*mockServerSocket_, RegisterServerSocket()).WillOnce(Return(0)); - EXPECT_CALL(*mockServerSocket_, WaitForConnection()).WillRepeatedly(Return(1)); - EXPECT_CALL(*mockServerSocket_, SaveConnection(_)).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, ReadSocketMessage(_, _, _)) - .WillRepeatedly(Invoke(mockServerSocket_.get(), &MockServerSocket::ReadImplGidCountMax)); - EXPECT_CALL(*mockServerSocket_, CloseConnection(_)).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, CloseServerMonitor()).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, WriteSocketMessage(_, _, _)).WillRepeatedly(Return(sizeof(pid_t))); - - auto func = [&]() { - // wait ServerMain unit test case - usleep(TEST_WAIT_TIME); - appSpawnServer_->SetRunning(false); - }; - - std::thread(func).detach(); - EXPECT_EQ(false, appSpawnServer_->ServerMain(argv, sizeof(argv))); - - // wait release - usleep(TEST_WAIT_TIME); - - GTEST_LOG_(INFO) << "App_Spawn_Server_002 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: ServerMain - * FunctionPoints: check params - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function ServerMain can check the process name is empty. - */ -HWTEST_F(AppSpawnServerMockTest, App_Spawn_Server_003, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_003 start"; - - char argv[20] = "LongNameTest"; - - testing::Mock::AllowLeak(mockServerSocket_.get()); - EXPECT_CALL(*mockServerSocket_, RegisterServerSocket()).WillOnce(Return(0)); - EXPECT_CALL(*mockServerSocket_, WaitForConnection()).WillRepeatedly(Return(1)); - EXPECT_CALL(*mockServerSocket_, SaveConnection(_)).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, ReadSocketMessage(_, _, _)) - .WillRepeatedly(Invoke(mockServerSocket_.get(), &MockServerSocket::ReadImplProcessName)); - EXPECT_CALL(*mockServerSocket_, CloseConnection(_)).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, CloseServerMonitor()).WillRepeatedly(Return()); - EXPECT_CALL(*mockServerSocket_, WriteSocketMessage(_, _, _)).WillRepeatedly(Return(sizeof(pid_t))); - - auto func = [=]() { - // wait ServerMain unit test case - usleep(TEST_WAIT_TIME); - appSpawnServer_->SetRunning(false); - }; - - std::thread(func).detach(); - EXPECT_EQ(false, appSpawnServer_->ServerMain(argv, sizeof(argv))); - - // wait release - usleep(TEST_WAIT_TIME); - - GTEST_LOG_(INFO) << "App_Spawn_Server_003 end"; -} diff --git a/test/unittest/app_spawn_server_test/app_spawn_server_override_test.cpp b/test/unittest/app_spawn_server_test/app_spawn_server_override_test.cpp deleted file mode 100644 index dafa83f4..00000000 --- a/test/unittest/app_spawn_server_test/app_spawn_server_override_test.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -// redefine private and protected since testcase need to invoke and test private function -#define private public -#define protected public -#include "appspawn_server.h" -#undef private -#undef protected - -#include -#include - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppSpawn; - -static constexpr int TEST_WAIT_TIME = 50 * 1000; // 50 ms - -class AppSpawnServerOverrideTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -protected: - std::unique_ptr appSpawnServer_ = nullptr; -}; - -void AppSpawnServerOverrideTest::SetUpTestCase() -{} - -void AppSpawnServerOverrideTest::TearDownTestCase() -{} - -void AppSpawnServerOverrideTest::SetUp() -{ - if (appSpawnServer_ == nullptr) { - appSpawnServer_ = std::make_unique("AppSpawnServerOverrideTest"); - } -} - -void AppSpawnServerOverrideTest::TearDown() -{} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: ServerMain - * FunctionPoints: fork app process - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function ServerMain fork app process success. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_001, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_001 start"; - - char argv[20] = "LongNameTest"; - auto func = [&]() { - // wait ServerMain unit test case - usleep(TEST_WAIT_TIME); - appSpawnServer_->SetRunning(false); - }; - std::thread(func).detach(); - EXPECT_EQ(false, appSpawnServer_->ServerMain(argv, sizeof(argv))); - - // wait release - usleep(TEST_WAIT_TIME); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_001 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and longProcName param is nullptr. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_002, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_002 start"; - - char *longProcName = nullptr; - int64_t longProcNameLen = sizeof(longProcName); - char processName[16] = "LongNameTest"; - int32_t len = sizeof(processName); - - EXPECT_EQ(-EINVAL, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_002 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and processName param is nullptr. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_003, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_003 start"; - - char longProcName[20] = "longProcName"; - int64_t longProcNameLen = sizeof(longProcName); - char *processName = nullptr; - int32_t len = sizeof(processName); - - EXPECT_EQ(-EINVAL, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_003 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and len param is 0. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_004, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_004 start"; - - char longProcName[20] = "longProcName"; - int64_t longProcNameLen = sizeof(longProcName); - char processName[16] = "processName"; - int32_t len = 0; - - EXPECT_EQ(-EINVAL, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_004 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and len param is -1. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_005, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_005 start"; - - char longProcName[20] = "longProcName"; - int64_t longProcNameLen = sizeof(longProcName); - char processName[16] = "processName"; - int32_t len = -1; - - EXPECT_EQ(-EINVAL, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_005 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and processName length < 16. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_006, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_006 start"; - - char longProcName[20] = "longProcName"; - int64_t longProcNameLen = sizeof(longProcName); - char processName[16] = "processName"; - int32_t len = sizeof(processName); - - EXPECT_EQ(0, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_006 end"; -} - -/* - * Feature: AppSpawn - * Function: AppSpawnServer - * SubFunction: SetProcessName - * FunctionPoints: set process name - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function SetProcessName and processName length > 16. - */ -HWTEST_F(AppSpawnServerOverrideTest, App_Spawn_Server_Override_007, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_007 start"; - - char longProcName[20] = "longProcName"; - int64_t longProcNameLen = strlen(longProcName); - char processName[32] = "processName0123456789"; - int32_t len = sizeof(processName); - - EXPECT_EQ(0, appSpawnServer_->SetProcessName(longProcName, longProcNameLen, processName, len)); - - GTEST_LOG_(INFO) << "App_Spawn_Server_Override_007 end"; -} diff --git a/test/unittest/app_spawn_socket_test/BUILD.gn b/test/unittest/app_spawn_socket_test/BUILD.gn index 7ac188da..c90d9872 100644 --- a/test/unittest/app_spawn_socket_test/BUILD.gn +++ b/test/unittest/app_spawn_socket_test/BUILD.gn @@ -17,7 +17,8 @@ import("//build/test.gni") ohos_unittest("AppSpawnSocketTest") { module_out_path = "${module_output_path}" - sources = [ "${appspawn_path}/src/socket/appspawn_socket.cpp" ] + sources = + [ "${appspawn_path}/interfaces/innerkits/client/appspawn_socket.cpp" ] sources += [ "app_spawn_socket_test.cpp" ] diff --git a/test/unittest/server_socket_test/BUILD.gn b/test/unittest/app_spawn_standard_test/BUILD.gn similarity index 47% rename from test/unittest/server_socket_test/BUILD.gn rename to test/unittest/app_spawn_standard_test/BUILD.gn index abe6805c..31b92140 100644 --- a/test/unittest/server_socket_test/BUILD.gn +++ b/test/unittest/app_spawn_standard_test/BUILD.gn @@ -14,27 +14,47 @@ import("//base/startup/appspawn_standard/appspawn.gni") import("//build/test.gni") -ohos_unittest("ServerSocketTest") { +ohos_unittest("AppSpawnStandardTest") { module_out_path = "${module_output_path}" - defines = [ "usleep(time) = MockSleep(time)" ] - - sources = [ - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/server_socket.cpp", + defines = [ + "usleep(time) = MockSleep(time)", + "APPSPAWN_TEST", ] - sources += [ "server_socket_test.cpp" ] + include_dirs = [ + "${appspawn_path}/standard/", + "${appspawn_path}/common/", + ] configs = [ "${appspawn_path}:appspawn_config" ] - deps = [ "${appspawn_path}/test:appspawn_test_source" ] + sources = [ + "${appspawn_path}/adapter/appspawn_ace.cpp", + "${appspawn_path}/standard/appspawn_process.c", + "${appspawn_path}/standard/appspawn_service.c", + "app_spawn_standard_test.cpp", + ] + + deps = [ + "${appspawn_path}:appspawn_server", + "${appspawn_path}/test:appspawn_test_source", + "//base/startup/init_lite/interfaces/innerkits:libbegetutil", + "//base/startup/init_lite/interfaces/innerkits/sandbox:libsandbox", + "//foundation/aafwk/standard/frameworks/kits/appkit:appkit_native", + ] - external_deps = [ "hiviewdfx_hilog_native:libhilog" ] + external_deps = [ + "ability_base:want", + "ability_runtime:app_manager", + "hiviewdfx_hilog_native:libhilog", + "ipc:ipc_core", + "utils_base:utils", + ] } group("unittest") { testonly = true - deps = [ ":ServerSocketTest" ] + deps = [ ":AppSpawnStandardTest" ] } diff --git a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp new file mode 100644 index 00000000..0cca5b0a --- /dev/null +++ b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include + +// redefine private and protected since testcase need to invoke and test private function +#define private public +#define protected public +#include "appspawn_service.h" +#undef private +#undef protected + +#include "securec.h" +#include "appspawn_adapter.h" +#include "appspawn_server.h" + +using namespace testing; +using namespace testing::ext; + +namespace OHOS { +class AppSpawnStandardTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void AppSpawnStandardTest::SetUpTestCase() +{} + +void AppSpawnStandardTest::TearDownTestCase() +{} + +void AppSpawnStandardTest::SetUp() +{} + +void AppSpawnStandardTest::TearDown() +{} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_001, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_001 start"; + string longProcName = "AppSpawnStandardTest1"; + int64_t longProcNameLen = longProcName.length(); + int cold = 1; + AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", (char*)longProcName.c_str(), longProcNameLen, cold); + EXPECT_TRUE(content); + content->loadExtendLib = LoadExtendLib; + content->runChildProcessor = RunChildProcessor; + + char *const argv[] = {}; + content->initAppSpawn(content); + AppSpawnColdRun(content, 1, argv); + + GTEST_LOG_(INFO) << "App_Spawn_Standard_001 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_002, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_002 start"; + string longProcName = "AppSpawnStandardTest2"; + int64_t longProcNameLen = longProcName.length(); + + AppSpawnClientExt* client = (AppSpawnClientExt*)malloc(sizeof(AppSpawnClientExt)); + client->client.id = 1; + client->client.flags = 1; + if (strcpy_s(client->property.apl, APP_APL_MAX_LEN, "system_basic") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + pid_t pid = 100; + AppSpawnContentExt* appSpawnContent = (AppSpawnContentExt*)malloc(sizeof(AppSpawnContentExt)); + EXPECT_TRUE(appSpawnContent); + if (strcpy_s(appSpawnContent->content.longProcName, longProcNameLen, longProcName.c_str()) != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + }; + appSpawnContent->content.longProcNameLen = longProcNameLen; + appSpawnContent->timer = NULL; + appSpawnContent->content.runAppSpawn = NULL; + appSpawnContent->content.initAppSpawn = NULL; + appSpawnContent->content.registerAppSandbox = NULL; + AppSpawnProcessMsg(&appSpawnContent->content, &client->client, &pid); + free(appSpawnContent); + free(client); + GTEST_LOG_(INFO) << "App_Spawn_Standard_002 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_003, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_003 start"; + string longProcName = "AppSpawnStandardTest3"; + int64_t longProcNameLen = longProcName.length(); + std::unique_ptr clientExt = std::make_unique(); + + clientExt->client.id = 1; + clientExt->client.flags = 0; + clientExt->fd[0] = 123; + clientExt->fd[1] = 456; + clientExt->property.uid = 10002; + clientExt->property.gid = 1000; + clientExt->property.gidCount = 1; + if (strcpy_s(clientExt->property.processName, APP_LEN_PROC_NAME, "com.ohos.settingsdata") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "com.ohos.settingsdata") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(clientExt->property.soPath, APP_LEN_SO_PATH, "/test") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + clientExt->property.accessTokenId = 671201800; + if (strcpy_s(clientExt->property.apl, APP_APL_MAX_LEN, "system_core") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(clientExt->property.renderCmd, APP_RENDER_CMD_MAX_LEN, "cmd_test") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + clientExt->property.flags = 0; + + AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", (char*)longProcName.c_str(), longProcNameLen, 1); + content->loadExtendLib = LoadExtendLib; + content->runChildProcessor = RunChildProcessor; + + SetContentFunction(content); + content->clearEnvironment(content, &clientExt->client); + EXPECT_EQ(content->setProcessName(content, &clientExt->client, (char*)longProcName.c_str(), longProcNameLen), 0); + EXPECT_EQ(content->setKeepCapabilities(content, &clientExt->client), 0); + EXPECT_EQ(content->setUidGid(content, &clientExt->client), 0); + EXPECT_EQ(content->setCapabilities(content, &clientExt->client), 0); + content->setAppSandbox(content, &clientExt->client); + content->setAppAccessToken(content, &clientExt->client); + EXPECT_EQ(content->coldStartApp(content, &clientExt->client), 0); + DoStartApp(content, &clientExt->client, (char*)longProcName.c_str(), longProcNameLen); + free(content); + GTEST_LOG_(INFO) << "App_Spawn_Standard_003 end"; +} + +HWTEST(AppSpawnStandardTest, App_Spawn_Standard_004, TestSize.Level0) +{ + GTEST_LOG_(INFO) << "App_Spawn_Standard_004 start"; + + AppSpawnClientExt* client = (AppSpawnClientExt*)malloc(sizeof(AppSpawnClientExt)); + client->client.id = 1; + client->client.flags = 0; + client->fd[0] = 1; + client->fd[1] = 2; + client->property.uid = 10000; + client->property.gid = 1000; + client->property.gidCount = 1; + if (strcpy_s(client->property.processName, APP_LEN_PROC_NAME, "test4") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(client->property.bundleName, APP_LEN_BUNDLE_NAME, "test4") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(client->property.soPath, APP_LEN_SO_PATH, "test4") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + client->property.accessTokenId = 671201800; + if (strcpy_s(client->property.apl, APP_APL_MAX_LEN, "system_core") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + if (strcpy_s(client->property.renderCmd, APP_RENDER_CMD_MAX_LEN, "test4") != 0) { + GTEST_LOG_(INFO) << "strcpy_s failed"; + } + client->property.flags = 0; + + char* argv[] = {(char*)"AppSpawnStandardTest4", (char*)"test4"}; + int argc = sizeof(argv)/sizeof(argv[0]); + + EXPECT_EQ(GetAppSpawnClientFromArg(argc, argv, client), -1); + free(client); + GTEST_LOG_(INFO) << "App_Spawn_Standard_004 end"; +} +} // namespace OHOS diff --git a/test/unittest/client_socket_test/BUILD.gn b/test/unittest/client_socket_test/BUILD.gn index 45ca7431..d5ba067a 100644 --- a/test/unittest/client_socket_test/BUILD.gn +++ b/test/unittest/client_socket_test/BUILD.gn @@ -20,8 +20,8 @@ ohos_unittest("ClientSocketTest") { defines = [ "usleep(time) = MockSleep(time)" ] sources = [ - "${appspawn_path}/src/socket/appspawn_socket.cpp", - "${appspawn_path}/src/socket/client_socket.cpp", + "${appspawn_path}/interfaces/innerkits/client/appspawn_socket.cpp", + "${appspawn_path}/interfaces/innerkits/client/client_socket.cpp", ] sources += [ "client_socket_test.cpp" ] diff --git a/test/unittest/server_socket_test/server_socket_test.cpp b/test/unittest/server_socket_test/server_socket_test.cpp deleted file mode 100644 index 8bca5c6e..00000000 --- a/test/unittest/server_socket_test/server_socket_test.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -// redefine private and protected since testcase need to invoke and test private function -#define private public -#define protected public -#include "server_socket.h" -#undef private -#undef protected - -#include "securec.h" - -using namespace testing; -using namespace testing::ext; -using namespace OHOS::AppSpawn; - -class ServerSocketTest : public testing::Test { -public: - static void SetUpTestCase(); - static void TearDownTestCase(); - void SetUp(); - void TearDown(); -}; - -void ServerSocketTest::SetUpTestCase() -{} - -void ServerSocketTest::TearDownTestCase() -{} - -void ServerSocketTest::SetUp() -{} - -void ServerSocketTest::TearDown() -{} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: RegisterServerSocket - * FunctionPoints: create server socket - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function RegisterServerSocket can called twice, but the socket fd is same. - */ -HWTEST(ServerSocketTest, Server_Socket_001, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_001 start"; - - std::unique_ptr serverSocket = std::make_unique("ServerSocketTest"); - - EXPECT_EQ(-1, serverSocket->GetSocketFd()); - EXPECT_EQ(0, serverSocket->RegisterServerSocket()); - int32_t socketFd = serverSocket->GetSocketFd(); - EXPECT_LE(0, socketFd); - EXPECT_EQ(0, serverSocket->RegisterServerSocket()); - EXPECT_EQ(socketFd, serverSocket->GetSocketFd()); - - GTEST_LOG_(INFO) << "Server_Socket_001 end"; -} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: RegisterServerSocket - * FunctionPoints: create server socket - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function RegisterServerSocket create server socket fail with the empty socket name. - */ -HWTEST(ServerSocketTest, Server_Socket_002, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_002 start"; - - std::unique_ptr serverSocket = std::make_unique(""); - EXPECT_EQ(-EINVAL, serverSocket->RegisterServerSocket()); - - GTEST_LOG_(INFO) << "Server_Socket_002 end"; -} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: WaitForConnection - * FunctionPoints: accept socket - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function WaitForConnection accept fail when don't create server socket. - */ -HWTEST(ServerSocketTest, Server_Socket_003, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_003 start"; - - std::unique_ptr serverSocket = std::make_unique("ServerSocketTest"); - EXPECT_EQ(-ENOTSOCK, serverSocket->WaitForConnection(0)); - - GTEST_LOG_(INFO) << "Server_Socket_003 end"; -} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: SaveConnection & VerifyConnection & CloseConnection - * FunctionPoints: connect fd - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the connect fd which be saved or not saved, then close the saved connect fd and verify them. - */ -HWTEST(ServerSocketTest, Server_Socket_004, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_004 start"; - - std::unique_ptr serverSocket = std::make_unique("ServerSocketTest"); - int32_t connectFd1 = 111; - int32_t connectFd2 = 222; - int32_t connectFd3 = 333; - - serverSocket->SaveConnection(connectFd1); - serverSocket->SaveConnection(connectFd2); - EXPECT_EQ(0, serverSocket->VerifyConnection(connectFd1)); - EXPECT_EQ(0, serverSocket->VerifyConnection(connectFd2)); - EXPECT_EQ(-1, serverSocket->VerifyConnection(connectFd3)); - serverSocket->CloseConnection(connectFd2); - EXPECT_EQ(-1, serverSocket->VerifyConnection(connectFd2)); - - GTEST_LOG_(INFO) << "Server_Socket_004 end"; -} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: CloseServerMonitor - * FunctionPoints: close the server socket - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function CloseServerMonitor which can close the server socket which has created - * successfully. - */ -HWTEST(ServerSocketTest, Server_Socket_005, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_005 start"; - - std::unique_ptr serverSocket = std::make_unique("ServerSocketTest"); - - EXPECT_EQ(0, serverSocket->RegisterServerSocket()); - EXPECT_LE(0, serverSocket->GetSocketFd()); - serverSocket->CloseServerMonitor(); - EXPECT_EQ(-1, serverSocket->GetSocketFd()); - - GTEST_LOG_(INFO) << "Server_Socket_005 end"; -} - -/* - * Feature: AppSpawn - * Function: ServerSocket - * SubFunction: RegisterServerSocket - * FunctionPoints: bind socket fail - * EnvConditions: mobile that can run ohos test framework - * CaseDescription: Verify the function RegisterServerSocket BindSocket fail and close the socket fd. - */ -HWTEST(ServerSocketTest, Server_Socket_006, TestSize.Level0) -{ - GTEST_LOG_(INFO) << "Server_Socket_006 start"; - - std::string invalidSocketName = - "InvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalid" - "InvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalidInvalid"; - std::unique_ptr serverSocket = std::make_unique(invalidSocketName.c_str()); - - EXPECT_EQ(-ENOENT, serverSocket->RegisterServerSocket()); - EXPECT_EQ(-1, serverSocket->GetSocketFd()); - - GTEST_LOG_(INFO) << "Server_Socket_006 end"; -} diff --git a/tools/appspawn_start_app.cpp b/tools/appspawn_start_app.cpp deleted file mode 100644 index 634f67aa..00000000 --- a/tools/appspawn_start_app.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2021-2022 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - -#include "appspawn_server.h" -#include "client_socket.h" -#include "hilog/log.h" -#include "securec.h" - -using namespace OHOS; -using namespace OHOS::HiviewDFX; -static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnServer"}; -static const int DECIMAL = 10; - -int main(int argc, char *const argv[]) -{ - if (argc <= 11) { // 11 min argc - HiLog::Error(LABEL, "Invalid argc %{public}d", argc); - return -1; - } - HiLog::Debug(LABEL, "AppSpawnServer argc %{public}d app:%{public}s", argc, argv[4]); // 4 name index - // calculate child process long name size - uintptr_t start = reinterpret_cast(argv[0]); - uintptr_t end = reinterpret_cast(strchr(argv[argc - 1], 0)); - if (end == 0) { - return -1; - } - uintptr_t argvSize = end - start; - - auto appProperty = std::make_unique(); - if (appProperty == nullptr) { - HiLog::Error(LABEL, "Failed to create app property %{public}s", argv[4]); // 4 name index - return -1; - } - int index = 1; - int fd = strtoul(argv[index++], nullptr, DECIMAL); - appProperty->uid = strtoul(argv[index++], nullptr, DECIMAL); - appProperty->gid = strtoul(argv[index++], nullptr, DECIMAL); - (void)strcpy_s(appProperty->processName, sizeof(appProperty->processName), argv[index++]); - (void)strcpy_s(appProperty->bundleName, sizeof(appProperty->bundleName), argv[index++]); - (void)strcpy_s(appProperty->soPath, sizeof(appProperty->soPath), argv[index++]); - appProperty->accessTokenId = strtoul(argv[index++], nullptr, DECIMAL); - (void)strcpy_s(appProperty->apl, sizeof(appProperty->apl), argv[index++]); - (void)strcpy_s(appProperty->renderCmd, sizeof(appProperty->renderCmd), argv[index++]); - appProperty->flags = strtoul(argv[index++], nullptr, DECIMAL); - appProperty->gidCount = strtoul(argv[index++], nullptr, DECIMAL); - uint32_t i = 0; - while ((i < appProperty->gidCount) && (i < sizeof(appProperty->gidTable) / sizeof(appProperty->gidTable[0]))) { - if (index >= argc) { - HiLog::Error(LABEL, "Invalid arg %{public}d %{public}d", index, argc); - return -1; - } - appProperty->gidTable[i++] = strtoul(argv[index++], nullptr, DECIMAL); - } - auto appspawnServer = std::make_shared("AppSpawn"); - if (appspawnServer != nullptr) { - int ret = appspawnServer->AppColdStart(argv[0], argvSize, appProperty.get(), fd); - if (ret != 0) { - HiLog::Error(LABEL, "Cold start %{public}s fail.", appProperty->bundleName); - } - } - return 0; -} -- Gitee From df4949c17b9a5e33b32a6de49f5b930d764cda13 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 11:22:13 +0800 Subject: [PATCH 02/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- standard/appspawn_service.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 511a5bf1..872c650c 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -205,14 +205,14 @@ static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty) return result; } -static void StartColdApp(const AppSpawnClientExt *appProperty) +static void StartColdApp(AppSpawnClientExt *appProperty) { if (appProperty == NULL) { return; } if (appProperty->property.flags & 0x01) { char cold[10] = {0}; // 10 cold - ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); + int ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { appProperty->client.flags |= APP_COLD_START; @@ -226,7 +226,7 @@ static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) if (appProperty == NULL) { return -1; } - if (appProperty->property.code == GET_RENDER_TERMINATION_STATUS) { + if (appProperty->property.code == AppOperateCode::GET_RENDER_TERMINATION_STATUS) { int exitStatus = 0; int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); if (ret) { @@ -235,7 +235,8 @@ static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) SendResponse(appProperty, (char *)&exitStatus, sizeof(exitStatus)); } APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s", - exitStatus, appProperty->property.pid, appProperty->property.uid, appProperty->property.processName, appProperty->property.bundleName); + exitStatus, appProperty->property.pid, appProperty->property.uid, + appProperty->property.processName, appProperty->property.bundleName); return 0; } #endif @@ -399,7 +400,7 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) g_appSpawnContent = NULL; } -static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) +static int CreateHashForApp(AppSpawnContentExt *appSpawnContent) { HashInfo hashInfo = { AppInfoHashNodeCompare, @@ -409,8 +410,9 @@ static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) AppInfoHashNodeFree, APP_HASH_BUTT }; - int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); APPSPAWN_CHECK(ret == 0, free(appSpawnContent); - return NULL, "Failed to create hash for app"); + int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return -1, "Failed to create hash for app"); + return 0; } @@ -438,7 +440,7 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam appSpawnContent->content.runAppSpawn = AppSpawnRun; // create hash for app - CreateHashForApp(appSpawnContent); + APPSPAWN_CHECK(CreateHashForApp(appSpawnContent) == 0, return NULL, "Failed to create hash for app"); char path[128] = {0}; // 128 max path int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); -- Gitee From c3612af27828719aa4743ec7ee0fa24af7730df5 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 13:36:31 +0800 Subject: [PATCH 03/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9Lite=20Ut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_nweb.cpp | 1 + interfaces/innerkits/include/appspawn_msg.h | 8 +- lite/BUILD.gn | 6 ++ lite/bundle.json | 3 + standard/appspawn_service.c | 5 +- test/unittest/app_spawn_lite_test/BUILD.gn | 28 ++++++- .../app_spawn_lite_test.cpp | 84 +++++++++++-------- .../app_spawn_standard_test.cpp | 2 +- 8 files changed, 93 insertions(+), 44 deletions(-) diff --git a/adapter/appspawn_nweb.cpp b/adapter/appspawn_nweb.cpp index 3274c362..f08323e5 100644 --- a/adapter/appspawn_nweb.cpp +++ b/adapter/appspawn_nweb.cpp @@ -17,6 +17,7 @@ #include #include +#include #ifdef NWEB_SPAWN #define RENDER_PROCESS_MAX_NUM 16 diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 4a325f65..1c468ac0 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -35,15 +35,15 @@ extern "C" { #define APPSPAWN_SOCKET_NAME "AppSpawn" #endif -enum AppType { +typedef enum { APP_TYPE_DEFAULT = 0, // JavaScript app APP_TYPE_NATIVE // Native C++ app -}; +} AppType; -enum AppOperateCode { +typedef enum { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, -}; +} AppOperateCode; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length diff --git a/lite/BUILD.gn b/lite/BUILD.gn index 1fbe1d5c..6ca7eae0 100644 --- a/lite/BUILD.gn +++ b/lite/BUILD.gn @@ -81,3 +81,9 @@ executable("appspawn") { include_dirs += [] } } + +if (ohos_build_type == "debug") { + group("unittest") { + deps = [ "//base/startup/appspawn_standard/test/unittest/app_spawn_lite_test:unittest" ] + } +} \ No newline at end of file diff --git a/lite/bundle.json b/lite/bundle.json index e183e850..843ec327 100644 --- a/lite/bundle.json +++ b/lite/bundle.json @@ -38,6 +38,9 @@ "build": { "sub_component": [ "//base/startup/appspawn_standard/lite:appspawn_lite" + ], + "test": [ + "//base/startup/appspawn_standard/test/unittest/app_spawn_lite_test:unittest" ] } } diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 872c650c..88f02aae 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -35,6 +35,7 @@ static AppSpawnContentExt *g_appSpawnContent = NULL; static const int TV_SEC = 60; +static const int SPECIAL_BUNDLE_NUMBER = 2; static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2) { @@ -142,7 +143,7 @@ static void SignalHandler(const struct signalfd_siginfo *siginfo) RemoveAppInfo(pid); #ifdef NWEB_SPAWN RecordRenderProcessExitedStatus(pid, status); -#endif +#endif } break; } @@ -170,7 +171,7 @@ static void HandleSpecial(AppSpawnClientExt *appProperty) "com.ohos.medialibrary.MediaLibraryDataA", "com.ohos.medialibrary.MediaScannerAbilityA" }; - for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) { + for (size_t i = 0; i < SPECIAL_BUNDLE_NUMBER; i++) { if (strcmp(appProperty->property.processName, specialBundleNames[i]) == 0) { if (appProperty->property.gidCount < APP_MAX_GIDS) { appProperty->property.gidTable[appProperty->property.gidCount] = GID_USER_DATA_RW; diff --git a/test/unittest/app_spawn_lite_test/BUILD.gn b/test/unittest/app_spawn_lite_test/BUILD.gn index 5cf2eccf..58b51906 100644 --- a/test/unittest/app_spawn_lite_test/BUILD.gn +++ b/test/unittest/app_spawn_lite_test/BUILD.gn @@ -23,24 +23,50 @@ unittest("AppSpawnLiteTest") { ] include_dirs = [ + "//base/startup/appspawn_standard/interfaces/innerkits/include", + "//base/startup/appspawn_standard/common/", "//base/startup/appspawn_standard/lite/", + "//base/startup/init_lite/interfaces/innerkits/include", "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", + "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", "//third_party/bounds_checking_function/include/", "//third_party/cJSON", + "${aafwk_lite_path}/interfaces/innerkits/abilitymgr_lite", + "//utils/native/lite/include", ] sources = [ + "//base/startup/appspawn_standard/common/appspawn_server.c", "//base/startup/appspawn_standard/lite/appspawn_message.c", + "//base/startup/appspawn_standard/lite/appspawn_process.c", + "//base/startup/appspawn_standard/lite/appspawn_service.c", "app_spawn_lite_test.cpp", ] deps = [ + "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite", "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", + "//base/startup/init_lite/interfaces/innerkits:libbegetutil", "//build/lite/config/component/cJSON:cjson_shared", + "//foundation/communication/ipc_lite:liteipc_adapter", + "//foundation/distributedschedule/samgr_lite/samgr:samgr", "//third_party/bounds_checking_function:libsec_shared", + "//utils/native/lite/kv_store:kv_store", ] + + deps += [ + "//foundation/ace/ace_engine_lite/frameworks:ace_lite", + "//foundation/graphic/surface:lite_surface", + "//foundation/graphic/ui:lite_ui", + "//foundation/graphic/utils:lite_graphic_utils", + ] + + if (ohos_kernel_type == "liteos_a") { + deps += [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared" ] + } } group("unittest") { - deps = [ ":appspawn_test" ] + deps = [ ":AppSpawnLiteTest" ] } diff --git a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp index f07e7243..aa714fb2 100644 --- a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp +++ b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp @@ -15,12 +15,14 @@ #include #include #include -#include +#include #include #include #include #include "gtest/gtest.h" #include "appspawn_message.h" +#include "appspawn_service.h" +#include "appspawn_msg.h" using namespace testing::ext; @@ -46,6 +48,23 @@ public: g_badStrings.push_back(std::string("\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"")); g_badStrings.push_back(std::string(".............................................")); g_badStrings.push_back(std::string("....%%%....^..***@##.../*--++......$$&&.....")); + StructuralFormatErrJson(); + StructuralFieldMisJson(); + StructuralFieldInvalidJson(); + printf("[----------] AppSpawnLiteTest, message func test setup.\n"); + } + + static void TearDownTestCase() + { + g_badStrings.clear(); + g_goodStrings.clear(); + printf("[----------] AppSpawnLiteTest, message func test teardown.\n"); + } + void SetUp() {} + void TearDown() {} + + static void StructuralFormatErrJson(void) + { // looks like json but format error g_badStrings.push_back(std::string( "{bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); @@ -109,6 +128,10 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0],}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0,]}")); + } + + static void StructuralFieldMisJson(void) + { // json format correct but fields missing g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); @@ -132,6 +155,10 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000}")); + } + + static void StructuralFieldInvalidJson(void) + { // field value invalid g_badStrings.push_back(std::string( "{\"bundleName\":\"\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); @@ -167,17 +194,7 @@ public: "{\"bundleName\":\"testvalid3\",\"identityID\":\"999\",\"uID\":1002,\"gID\":1002,\"capability\":[]}")); g_goodStrings.push_back(std::string( "{\"bundleName\":\"testvalid3\",\"identityID\":\"3\",\"uID\":1002,\"gID\":1002,\"capability\":[1,2]}")); - printf("[----------] AppSpawnLiteTest, message func test setup.\n"); - } - - static void TearDownTestCase() - { - g_badStrings.clear(); - g_goodStrings.clear(); - printf("[----------] AppSpawnLiteTest, message func test teardown.\n"); } - void SetUp() {} - void TearDown() {} }; /* @@ -368,31 +385,26 @@ HWTEST_F(AppSpawnLiteTest, SetContentFunctionTest_001, TestSize.Level0) GTEST_LOG_(INFO) << "SetContentFunctionTest_001 start"; AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", NULL, 0, 0); SetContentFunction(content); - char *longProcName = "SetContentFunctionTest_001"; - int64_t longProcNameLen = 1024; - - std::unique_ptr clientExt = std::make_unique(); - clientExt->client.id = 1; - clientExt->client.flag = 0; - clientExt->fd[0] = 123; - clientExt->fd[1] = 456; - clientExt->property.uid = 10002; - clientExt->property.gid = 1000; - clientExt->property.gidCount = 1; - strcpy_s(clientExt->property.processName, APP_LEN_PROC_NAME, "com.ohos.settingsdata"); - strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "com.ohos.settingsdata"); - strcpy_s(clientExt->property.soPath, APP_LEN_SO_PATH, " "); - clientExt->property.accessTokenId = 671201800; - strcpy_s(clientExt->property.apl, APP_APL_MAX_LEN, "system_core"); - strcpy_s(clientExt->property.renderCmd, APP_RENDER_CMD_MAX_LEN, " "); - - clientExt->property.flags = 0; - - content->setProcessName(content, clientExt->client, longProcName, longProcNameLen); - content->setKeepCapabilities(content, clientExt->client); - content->setUidGid(content, clientExt->client); - content->setCapabilities(content, clientExt->client); - content->runChildProcessor(content, clientExt->client); + string longProcName = "SetContentFunctionTest_001"; + int64_t longProcNameLen = longProcName.length(); + + AppSpawnClientLite *liteClient = (AppSpawnClientLite *)malloc(sizeof(AppSpawnClientLite)); + liteClient->client.id = 1; + liteClient->client.flags = 0; + + liteClient->message.bundleName = "com.ohos.settingsdata"; + liteClient->message.identityID = "123456789"; + liteClient->message.uID = 10003; + liteClient->message.gID = 1000; + liteClient->message.capsCnt = 0; + + EXPECT_NE(content->setProcessName(content, &liteClient->client, (char*)longProcName.c_str(), + longProcNameLen), 0); + EXPECT_EQ(content->setKeepCapabilities(content, &liteClient->client), 0); + EXPECT_EQ(content->setUidGid(content, &liteClient->client), -1); + EXPECT_EQ(content->setCapabilities(content, &liteClient->client), -1); + content->runChildProcessor(content, &liteClient->client); + free(liteClient); GTEST_LOG_(INFO) << "SetContentFunctionTest_001 end"; } diff --git a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp index 0cca5b0a..e4c34524 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp @@ -179,7 +179,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_004, TestSize.Level0) } client->property.flags = 0; - char* argv[] = {(char*)"AppSpawnStandardTest4", (char*)"test4"}; + char* argv[] = {const_cast("AppSpawnStandardTest4"), const_cast("test4")}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(GetAppSpawnClientFromArg(argc, argv, client), -1); -- Gitee From 05e59a83184ce7a182727989c7c088110b71650d Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 14:09:24 +0800 Subject: [PATCH 04/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- lite/BUILD.gn | 2 +- standard/appspawn_process.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lite/BUILD.gn b/lite/BUILD.gn index 6ca7eae0..e00dbe1d 100644 --- a/lite/BUILD.gn +++ b/lite/BUILD.gn @@ -86,4 +86,4 @@ if (ohos_build_type == "debug") { group("unittest") { deps = [ "//base/startup/appspawn_standard/test/unittest/app_spawn_lite_test:unittest" ] } -} \ No newline at end of file +} diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index 2f2d8789..d0f00c70 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -310,7 +310,7 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_LOGE("Failed to execv, errno = %d", errno); } } - + Free(argv); return ret; } -- Gitee From c5f48cf9df9f924d559909ac9656ac5c6c8ca985 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 14:37:15 +0800 Subject: [PATCH 05/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 4 ++-- interfaces/innerkits/include/client_socket.h | 1 + standard/appspawn_service.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 1c468ac0..d0e6d33b 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -43,7 +43,7 @@ typedef enum { typedef enum { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, -} AppOperateCode; +} AppOperateType; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length @@ -70,7 +70,7 @@ typedef struct AppParameter_ { char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; int32_t pid; // query render process exited status by render process pid - AppOperateCode code; + AppOperateType code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 0a839117..2228c5fa 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -94,6 +94,7 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; + using AppOperateCode = AppOperateType; private: /** * Connects a client socket. diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 88f02aae..6ba6761d 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -227,7 +227,7 @@ static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) if (appProperty == NULL) { return -1; } - if (appProperty->property.code == AppOperateCode::GET_RENDER_TERMINATION_STATUS) { + if (appProperty->property.code == AppOperateType::GET_RENDER_TERMINATION_STATUS) { int exitStatus = 0; int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); if (ret) { -- Gitee From bad7bab27a2ab30ff5ab31b99e6435b60d8f6e79 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 15:11:58 +0800 Subject: [PATCH 06/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_adapter.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adapter/appspawn_adapter.h b/adapter/appspawn_adapter.h index 267c8e1c..bf57a81a 100644 --- a/adapter/appspawn_adapter.h +++ b/adapter/appspawn_adapter.h @@ -28,9 +28,10 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient * void SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client); void LoadExtendLib(AppSpawnContent *content); void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); - void RegisterAppSandbox(struct AppSpawnContent_ *content, AppSpawnClient *client); +int GetRenderProcessTerminationStatus(int32_t pid, int *status); +void RecordRenderProcessExitedStatus(pid_t pid, int status); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif -- Gitee From 8637e6290abf6d871ec82c8fe3ee05e7e28dd27d Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 19:43:35 +0800 Subject: [PATCH 07/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9lite=20UT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- lite/appspawn_process.c | 2 ++ standard/appspawn_service.c | 4 +-- test/unittest/app_spawn_lite_test/BUILD.gn | 2 ++ .../app_spawn_lite_test.cpp | 32 ++++++------------- 4 files changed, 15 insertions(+), 25 deletions(-) diff --git a/lite/appspawn_process.c b/lite/appspawn_process.c index 46802eaf..c0206f31 100644 --- a/lite/appspawn_process.c +++ b/lite/appspawn_process.c @@ -167,10 +167,12 @@ static void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) appProperty->message.bundleName, appProperty->message.identityID, appProperty->message.uID, appProperty->message.gID); +#ifndef APPSPAWN_TEST if (AbilityMain(appProperty->message.identityID) != 0) { APPSPAWN_LOGE("[appspawn] AbilityMain execute failed, pid %d.", getpid()); exit(0x7f); // 0x7f: user specified } +#endif } void SetContentFunction(AppSpawnContent *content) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 6ba6761d..8b709cea 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -412,9 +412,9 @@ static int CreateHashForApp(AppSpawnContentExt *appSpawnContent) APP_HASH_BUTT }; int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); - APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return -1, "Failed to create hash for app"); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return -1, "Failed to create hash for app"); return 0; - } AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode) diff --git a/test/unittest/app_spawn_lite_test/BUILD.gn b/test/unittest/app_spawn_lite_test/BUILD.gn index 58b51906..3fbe3b0a 100644 --- a/test/unittest/app_spawn_lite_test/BUILD.gn +++ b/test/unittest/app_spawn_lite_test/BUILD.gn @@ -44,6 +44,8 @@ unittest("AppSpawnLiteTest") { "app_spawn_lite_test.cpp", ] + defines = [ "APPSPAWN_TEST" ] + deps = [ "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite", "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", diff --git a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp index aa714fb2..3c1d0948 100644 --- a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp +++ b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp @@ -70,12 +70,6 @@ public: "{bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName:\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV,\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV\",identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID:\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( @@ -86,10 +80,6 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1\",uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID:10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID:10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,capability\":[0]}")); g_badStrings.push_back(std::string( @@ -108,10 +98,6 @@ public: "{\"bundleName\"\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\"\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV\",\"identityID\"\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); - g_badStrings.push_back(std::string( - "{\"bundleName\":\"nameV\",\"identityID\":\"1\"\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\"10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( @@ -385,24 +371,24 @@ HWTEST_F(AppSpawnLiteTest, SetContentFunctionTest_001, TestSize.Level0) GTEST_LOG_(INFO) << "SetContentFunctionTest_001 start"; AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", NULL, 0, 0); SetContentFunction(content); + string longProcName = "SetContentFunctionTest_001"; int64_t longProcNameLen = longProcName.length(); - AppSpawnClientLite *liteClient = (AppSpawnClientLite *)malloc(sizeof(AppSpawnClientLite)); + EXPECT_TRUE(liteClient); liteClient->client.id = 1; liteClient->client.flags = 0; - liteClient->message.bundleName = "com.ohos.settingsdata"; - liteClient->message.identityID = "123456789"; - liteClient->message.uID = 10003; - liteClient->message.gID = 1000; - liteClient->message.capsCnt = 0; + std::string validStr = + "{\"bundleName\":\"validName\",\"identityID\":\"135\",\"uID\":999,\"gID\":888,\"capability\":[0, 1, 5]}"; + int ret = SplitMessage(validStr.c_str(), validStr.length(), &liteClient->message); + EXPECT_EQ(ret, 0); - EXPECT_NE(content->setProcessName(content, &liteClient->client, (char*)longProcName.c_str(), + EXPECT_EQ(content->setProcessName(content, &liteClient->client, (char*)longProcName.c_str(), longProcNameLen), 0); EXPECT_EQ(content->setKeepCapabilities(content, &liteClient->client), 0); - EXPECT_EQ(content->setUidGid(content, &liteClient->client), -1); - EXPECT_EQ(content->setCapabilities(content, &liteClient->client), -1); + EXPECT_EQ(content->setUidGid(content, &liteClient->client), 0); + EXPECT_EQ(content->setCapabilities(content, &liteClient->client), 0); content->runChildProcessor(content, &liteClient->client); free(liteClient); -- Gitee From 0f6d093959740ba27e889c7fd2960c327d6116f9 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 21:25:52 +0800 Subject: [PATCH 08/21] =?UTF-8?q?=E7=95=8C=E9=9D=A2=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=BF=9B=E5=85=A5=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- standard/appspawn_service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 8b709cea..9390735d 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -142,7 +142,7 @@ static void SignalHandler(const struct signalfd_siginfo *siginfo) APPSPAWN_LOGI("SignalHandler pid %d status %d", pid, status); RemoveAppInfo(pid); #ifdef NWEB_SPAWN - RecordRenderProcessExitedStatus(pid, status); + //RecordRenderProcessExitedStatus(pid, status); #endif } break; @@ -221,7 +221,7 @@ static void StartColdApp(AppSpawnClientExt *appProperty) } } -static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) +int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) { #ifdef NWEB_SPAWN if (appProperty == NULL) { @@ -280,7 +280,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); // get render process termination status - APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); +// APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); pid_t pid = 0; int result = AppSpawnProcessMsg(&g_appSpawnContent->content, &appProperty->client, &pid); -- Gitee From 09f8f251cf3e75e1e1cb5f906b693c74e8388efa Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Mon, 25 Apr 2022 21:55:44 +0800 Subject: [PATCH 09/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BB=93=E6=9E=84?= =?UTF-8?q?=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 4 ++-- interfaces/innerkits/include/client_socket.h | 6 +++++- standard/appspawn_service.c | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index d0e6d33b..1c468ac0 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -43,7 +43,7 @@ typedef enum { typedef enum { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, -} AppOperateType; +} AppOperateCode; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length @@ -70,7 +70,7 @@ typedef struct AppParameter_ { char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; int32_t pid; // query render process exited status by render process pid - AppOperateType code; + AppOperateCode code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 2228c5fa..f728ec2b 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -84,6 +84,11 @@ public: APP_TYPE_NATIVE // Native C++ app }; + enum AppOperateCode { + DEFAULT = 0, + GET_RENDER_TERMINATION_STATUS, + }; + static constexpr int APPSPAWN_MSG_MAX_SIZE = APP_MSG_MAX_SIZE; // appspawn message max size static constexpr int LEN_PROC_NAME = APP_LEN_PROC_NAME; // process name length static constexpr int LEN_BUNDLE_NAME = APP_LEN_BUNDLE_NAME; // bundle name length @@ -94,7 +99,6 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; - using AppOperateCode = AppOperateType; private: /** * Connects a client socket. diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 9390735d..e04b6f03 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -142,7 +142,7 @@ static void SignalHandler(const struct signalfd_siginfo *siginfo) APPSPAWN_LOGI("SignalHandler pid %d status %d", pid, status); RemoveAppInfo(pid); #ifdef NWEB_SPAWN - //RecordRenderProcessExitedStatus(pid, status); + RecordRenderProcessExitedStatus(pid, status); #endif } break; @@ -221,13 +221,13 @@ static void StartColdApp(AppSpawnClientExt *appProperty) } } -int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) +static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) { #ifdef NWEB_SPAWN if (appProperty == NULL) { return -1; } - if (appProperty->property.code == AppOperateType::GET_RENDER_TERMINATION_STATUS) { + if (appProperty->property.code == AppOperateCode::GET_RENDER_TERMINATION_STATUS) { int exitStatus = 0; int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); if (ret) { @@ -280,7 +280,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); // get render process termination status -// APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); + APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); pid_t pid = 0; int result = AppSpawnProcessMsg(&g_appSpawnContent->content, &appProperty->client, &pid); -- Gitee From 4869c1adc33b7a207aa254d887840cba66959826 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 09:56:57 +0800 Subject: [PATCH 10/21] =?UTF-8?q?=E5=9B=9E=E9=80=80=E5=A4=A7=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E6=8B=86=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 4 +-- interfaces/innerkits/include/client_socket.h | 6 +--- standard/appspawn_service.c | 35 ++++++++++++++++---- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 1c468ac0..d0e6d33b 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -43,7 +43,7 @@ typedef enum { typedef enum { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, -} AppOperateCode; +} AppOperateType; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length @@ -70,7 +70,7 @@ typedef struct AppParameter_ { char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; int32_t pid; // query render process exited status by render process pid - AppOperateCode code; + AppOperateType code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index f728ec2b..2228c5fa 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -84,11 +84,6 @@ public: APP_TYPE_NATIVE // Native C++ app }; - enum AppOperateCode { - DEFAULT = 0, - GET_RENDER_TERMINATION_STATUS, - }; - static constexpr int APPSPAWN_MSG_MAX_SIZE = APP_MSG_MAX_SIZE; // appspawn message max size static constexpr int LEN_PROC_NAME = APP_LEN_PROC_NAME; // process name length static constexpr int LEN_BUNDLE_NAME = APP_LEN_BUNDLE_NAME; // bundle name length @@ -99,6 +94,7 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; + using AppOperateCode = AppOperateType; private: /** * Connects a client socket. diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index e04b6f03..4ffb889f 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -206,7 +206,7 @@ static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty) return result; } -static void StartColdApp(AppSpawnClientExt *appProperty) +void StartColdApp(AppSpawnClientExt *appProperty) { if (appProperty == NULL) { return; @@ -227,7 +227,7 @@ static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) if (appProperty == NULL) { return -1; } - if (appProperty->property.code == AppOperateCode::GET_RENDER_TERMINATION_STATUS) { + if (appProperty->property.code == AppOperateType::GET_RENDER_TERMINATION_STATUS) { int exitStatus = 0; int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); if (ret) { @@ -265,7 +265,16 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, } // cold start app - StartColdApp(appProperty); + //StartColdApp(appProperty); + + if (appProperty->property.flags & 0x01) { + char cold[10] = {0}; // 10 cold + ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); + APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); + if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { + appProperty->client.flags |= APP_COLD_START; + } + } // create pipe for commication from child if (pipe(appProperty->fd) == -1) { @@ -280,7 +289,7 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); // get render process termination status - APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); + // APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); pid_t pid = 0; int result = AppSpawnProcessMsg(&g_appSpawnContent->content, &appProperty->client, &pid); @@ -401,7 +410,7 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) g_appSpawnContent = NULL; } -static int CreateHashForApp(AppSpawnContentExt *appSpawnContent) +int CreateHashForApp(AppSpawnContentExt *appSpawnContent) { HashInfo hashInfo = { AppInfoHashNodeCompare, @@ -441,10 +450,22 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam appSpawnContent->content.runAppSpawn = AppSpawnRun; // create hash for app - APPSPAWN_CHECK(CreateHashForApp(appSpawnContent) == 0, return NULL, "Failed to create hash for app"); + // APPSPAWN_CHECK(CreateHashForApp(appSpawnContent) == 0, return NULL, "Failed to create hash for app"); + + HashInfo hashInfo = { + AppInfoHashNodeCompare, + TestHashKeyCompare, + AppInfoHashNodeFunction, + AppInfoHashKeyFunction, + AppInfoHashNodeFree, + APP_HASH_BUTT + }; + int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to create hash for app"); char path[128] = {0}; // 128 max path - int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); + ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); APPSPAWN_CHECK(ret >= 0, free(appSpawnContent); return NULL, "Failed to snprintf_s %d", ret); int socketId = GetControlSocket(socketName); -- Gitee From 2634b10937f2c4e61023fd1a38a9a1ecc0938b93 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 10:12:12 +0800 Subject: [PATCH 11/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- standard/appspawn_service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 4ffb889f..a7443d2a 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -221,7 +221,7 @@ void StartColdApp(AppSpawnClientExt *appProperty) } } -static int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) +int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) { #ifdef NWEB_SPAWN if (appProperty == NULL) { -- Gitee From a224e8ad7c1597c8682673e7a5db66c82b45f455 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 11:06:54 +0800 Subject: [PATCH 12/21] =?UTF-8?q?=E5=9B=9E=E9=80=80=E4=BB=A3=E7=A0=812?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_sandbox.cpp | 14 +++++++++++++- standard/appspawn_process.c | 10 ++++++++-- standard/appspawn_service.c | 2 +- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index 51dcee01..1355b58c 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -352,7 +352,19 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient * int rc = 0; APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; - MatchSandbox(appProperty); + //MatchSandbox(appProperty); + + if (strcmp("system_basic", appProperty->property.apl) == 0) { + EnterSandbox("priv-app"); + } else if (strcmp("normal", appProperty->property.apl) == 0) { + EnterSandbox("app"); + } else if (strcmp("system_core ", appProperty->property.apl) == 0) { + EnterSandbox("app"); + } else { + APPSPAWN_LOGE("AppSpawnServer::Failed to match appspawn sandbox %s", appProperty->property.apl); + EnterSandbox("app"); + } + // create /mnt/sandbox/ path�?later put it to rootfs module std::string sandboxPackagePath = "/"; sandboxPackagePath += appProperty->property.bundleName; diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index d0f00c70..2a5db4a7 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -242,7 +242,7 @@ static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClie return 0; } -static void Free(char **argv) +void Free(char **argv) { argv[0] = NULL; for (int i = 0; i < NULL_INDEX; i++) { @@ -310,7 +310,13 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_LOGE("Failed to execv, errno = %d", errno); } } - Free(argv); + argv[0] = NULL; + for (int i = 0; i < NULL_INDEX; i++) { + if (argv[i] != NULL) { + free(argv[i]); + } + } + free(argv); return ret; } diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index a7443d2a..d74a04dc 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -142,7 +142,7 @@ static void SignalHandler(const struct signalfd_siginfo *siginfo) APPSPAWN_LOGI("SignalHandler pid %d status %d", pid, status); RemoveAppInfo(pid); #ifdef NWEB_SPAWN - RecordRenderProcessExitedStatus(pid, status); + // RecordRenderProcessExitedStatus(pid, status); #endif } break; -- Gitee From 94d9ab4bff1517b7f91c3ece9716f9d58954cddc Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 11:18:07 +0800 Subject: [PATCH 13/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_sandbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index 1355b58c..dba9c511 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -330,7 +330,7 @@ static int32_t DoSandboxRootFolderCreate(const std::string &sandboxPackagePath) return 0; } -static void MatchSandbox(AppSpawnClientExt *appProperty) +void MatchSandbox(AppSpawnClientExt *appProperty) { if (appProperty == nullptr) { return; -- Gitee From abdc1938a248ce070928ea8cd101caa307223775 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 14:32:29 +0800 Subject: [PATCH 14/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_adapter.h | 5 +- adapter/appspawn_nweb.cpp | 56 --------------- adapter/appspawn_sandbox.cpp | 16 +---- interfaces/innerkits/include/appspawn_msg.h | 11 +-- interfaces/innerkits/include/client_socket.h | 1 - standard/appspawn_process.c | 10 +-- standard/appspawn_service.c | 71 +++---------------- test/unittest/app_spawn_lite_test/BUILD.gn | 30 +------- .../app_spawn_lite_test.cpp | 71 ++++++++++++------- 9 files changed, 62 insertions(+), 209 deletions(-) diff --git a/adapter/appspawn_adapter.h b/adapter/appspawn_adapter.h index bf57a81a..267c8e1c 100644 --- a/adapter/appspawn_adapter.h +++ b/adapter/appspawn_adapter.h @@ -28,10 +28,9 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient * void SetAppAccessToken(struct AppSpawnContent_ *content, AppSpawnClient *client); void LoadExtendLib(AppSpawnContent *content); void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client); + void RegisterAppSandbox(struct AppSpawnContent_ *content, AppSpawnClient *client); -int GetRenderProcessTerminationStatus(int32_t pid, int *status); -void RecordRenderProcessExitedStatus(pid_t pid, int status); #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/adapter/appspawn_nweb.cpp b/adapter/appspawn_nweb.cpp index f08323e5..623c0514 100644 --- a/adapter/appspawn_nweb.cpp +++ b/adapter/appspawn_nweb.cpp @@ -17,19 +17,6 @@ #include #include -#include - -#ifdef NWEB_SPAWN -#define RENDER_PROCESS_MAX_NUM 16 -#define RENDER_PROCESS_ARRAY_IDLE 0 - -typedef struct { - int32_t pid; - int exitStatus; -} RenderProcessNode; - -static RenderProcessNode g_renderProcessArray[RENDER_PROCESS_MAX_NUM]; -#endif void *g_nwebHandle = nullptr; @@ -73,47 +60,4 @@ void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) return; } funcNWebRenderMain(appProperty->property.renderCmd); -} - -static void DumpRenderProcessExitedArray() -{ - APPSPAWN_LOGI("dump render process exited array:"); - for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { - APPSPAWN_LOGI("[pid, exitedStatus] = [%d, %d]", - g_renderProcessArray[i].pid, g_renderProcessArray[i].exitStatus); - } -} - -void RecordRenderProcessExitedStatus(pid_t pid, int status) -{ - int i = 0; - for (; i < RENDER_PROCESS_MAX_NUM; i++) { - if (g_renderProcessArray[i].pid == RENDER_PROCESS_ARRAY_IDLE) { - g_renderProcessArray[i].exitStatus = status; - g_renderProcessArray[i].pid = pid; - break; - } - } - if (i == RENDER_PROCESS_MAX_NUM) { - APPSPAWN_LOGE("no empty space in render process exited array"); - DumpRenderProcessExitedArray(); - } -} - -int GetRenderProcessTerminationStatus(int32_t pid, int *status) -{ - if (status == nullptr) { - return -EINVAL; - } - - for (int i = 0; i < RENDER_PROCESS_MAX_NUM; i++) { - if (g_renderProcessArray[i].pid == pid) { - *status = g_renderProcessArray[i].exitStatus; - g_renderProcessArray[i].pid = RENDER_PROCESS_ARRAY_IDLE; - return 0; - } - } - APPSPAWN_LOGE("not find pid[%d] in render process exited arrary", pid); - DumpRenderProcessExitedArray(); - return -EINVAL; } \ No newline at end of file diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index dba9c511..51dcee01 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -330,7 +330,7 @@ static int32_t DoSandboxRootFolderCreate(const std::string &sandboxPackagePath) return 0; } -void MatchSandbox(AppSpawnClientExt *appProperty) +static void MatchSandbox(AppSpawnClientExt *appProperty) { if (appProperty == nullptr) { return; @@ -352,19 +352,7 @@ int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient * int rc = 0; APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; - //MatchSandbox(appProperty); - - if (strcmp("system_basic", appProperty->property.apl) == 0) { - EnterSandbox("priv-app"); - } else if (strcmp("normal", appProperty->property.apl) == 0) { - EnterSandbox("app"); - } else if (strcmp("system_core ", appProperty->property.apl) == 0) { - EnterSandbox("app"); - } else { - APPSPAWN_LOGE("AppSpawnServer::Failed to match appspawn sandbox %s", appProperty->property.apl); - EnterSandbox("app"); - } - + MatchSandbox(appProperty); // create /mnt/sandbox/ path�?later put it to rootfs module std::string sandboxPackagePath = "/"; sandboxPackagePath += appProperty->property.bundleName; diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index d0e6d33b..4b8cad0d 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -35,15 +35,10 @@ extern "C" { #define APPSPAWN_SOCKET_NAME "AppSpawn" #endif -typedef enum { +enum AppType { APP_TYPE_DEFAULT = 0, // JavaScript app APP_TYPE_NATIVE // Native C++ app -} AppType; - -typedef enum { - DEFAULT = 0, - GET_RENDER_TERMINATION_STATUS, -} AppOperateType; +}; #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length @@ -69,8 +64,6 @@ typedef struct AppParameter_ { char apl[APP_APL_MAX_LEN]; char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; - int32_t pid; // query render process exited status by render process pid - AppOperateType code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 2228c5fa..0a839117 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -94,7 +94,6 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; - using AppOperateCode = AppOperateType; private: /** * Connects a client socket. diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index 2a5db4a7..d0f00c70 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -242,7 +242,7 @@ static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClie return 0; } -void Free(char **argv) +static void Free(char **argv) { argv[0] = NULL; for (int i = 0; i < NULL_INDEX; i++) { @@ -310,13 +310,7 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_LOGE("Failed to execv, errno = %d", errno); } } - argv[0] = NULL; - for (int i = 0; i < NULL_INDEX; i++) { - if (argv[i] != NULL) { - free(argv[i]); - } - } - free(argv); + Free(argv); return ret; } diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index d74a04dc..8caa79e2 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -35,7 +35,6 @@ static AppSpawnContentExt *g_appSpawnContent = NULL; static const int TV_SEC = 60; -static const int SPECIAL_BUNDLE_NUMBER = 2; static int AppInfoHashNodeCompare(const HashNode *node1, const HashNode *node2) { @@ -141,9 +140,6 @@ static void SignalHandler(const struct signalfd_siginfo *siginfo) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { APPSPAWN_LOGI("SignalHandler pid %d status %d", pid, status); RemoveAppInfo(pid); -#ifdef NWEB_SPAWN - // RecordRenderProcessExitedStatus(pid, status); -#endif } break; } @@ -171,7 +167,7 @@ static void HandleSpecial(AppSpawnClientExt *appProperty) "com.ohos.medialibrary.MediaLibraryDataA", "com.ohos.medialibrary.MediaScannerAbilityA" }; - for (size_t i = 0; i < SPECIAL_BUNDLE_NUMBER; i++) { + for (size_t i = 0; i < sizeof(specialBundleNames) / sizeof(specialBundleNames[0]); i++) { if (strcmp(appProperty->property.processName, specialBundleNames[i]) == 0) { if (appProperty->property.gidCount < APP_MAX_GIDS) { appProperty->property.gidTable[appProperty->property.gidCount] = GID_USER_DATA_RW; @@ -206,7 +202,7 @@ static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty) return result; } -void StartColdApp(AppSpawnClientExt *appProperty) +static void StartColdApp(AppSpawnClientExt *appProperty) { if (appProperty == NULL) { return; @@ -221,29 +217,6 @@ void StartColdApp(AppSpawnClientExt *appProperty) } } -int GetProcessTerminationStatus(AppSpawnClientExt *appProperty) -{ -#ifdef NWEB_SPAWN - if (appProperty == NULL) { - return -1; - } - if (appProperty->property.code == AppOperateType::GET_RENDER_TERMINATION_STATUS) { - int exitStatus = 0; - int ret = GetRenderProcessTerminationStatus(appProperty->property.pid, &exitStatus); - if (ret) { - SendResponse(appProperty, (char *)&ret, sizeof(ret)); - } else { - SendResponse(appProperty, (char *)&exitStatus, sizeof(exitStatus)); - } - APPSPAWN_LOGI("AppSpawnServer::get render process termination status, status = %d pid = %d uid %d %s %s", - exitStatus, appProperty->property.pid, appProperty->property.uid, - appProperty->property.processName, appProperty->property.bundleName); - return 0; - } -#endif - return -1; -} - static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) { APPSPAWN_CHECK(buffer != NULL && buffLen >= sizeof(AppParameter), LE_CloseTask(LE_GetDefaultLoop(), taskHandle); @@ -263,18 +236,8 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, LE_StopTimer(LE_GetDefaultLoop(), g_appSpawnContent->timer); g_appSpawnContent->timer = NULL; } - // cold start app - //StartColdApp(appProperty); - - if (appProperty->property.flags & 0x01) { - char cold[10] = {0}; // 10 cold - ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); - APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); - if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { - appProperty->client.flags |= APP_COLD_START; - } - } + StartColdApp(appProperty); // create pipe for commication from child if (pipe(appProperty->fd) == -1) { @@ -287,10 +250,6 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, buffLen, appProperty->property.flags); fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); - - // get render process termination status - // APPSPAWN_CHECK(GetProcessTerminationStatus(appProperty) != 0, return, "Invalid appspawn content"); - pid_t pid = 0; int result = AppSpawnProcessMsg(&g_appSpawnContent->content, &appProperty->client, &pid); if (result == 0) { // wait child process resutl @@ -410,7 +369,7 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) g_appSpawnContent = NULL; } -int CreateHashForApp(AppSpawnContentExt *appSpawnContent) +static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) { HashInfo hashInfo = { AppInfoHashNodeCompare, @@ -420,10 +379,8 @@ int CreateHashForApp(AppSpawnContentExt *appSpawnContent) AppInfoHashNodeFree, APP_HASH_BUTT }; - int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); - APPSPAWN_CHECK(ret == 0, free(appSpawnContent); - return -1, "Failed to create hash for app"); - return 0; + int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to create hash for app"); } AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode) @@ -450,22 +407,10 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam appSpawnContent->content.runAppSpawn = AppSpawnRun; // create hash for app - // APPSPAWN_CHECK(CreateHashForApp(appSpawnContent) == 0, return NULL, "Failed to create hash for app"); - - HashInfo hashInfo = { - AppInfoHashNodeCompare, - TestHashKeyCompare, - AppInfoHashNodeFunction, - AppInfoHashKeyFunction, - AppInfoHashNodeFree, - APP_HASH_BUTT - }; - int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); - APPSPAWN_CHECK(ret == 0, free(appSpawnContent); - return NULL, "Failed to create hash for app"); + CreateHashForApp(appSpawnContent); char path[128] = {0}; // 128 max path - ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); + int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); APPSPAWN_CHECK(ret >= 0, free(appSpawnContent); return NULL, "Failed to snprintf_s %d", ret); int socketId = GetControlSocket(socketName); diff --git a/test/unittest/app_spawn_lite_test/BUILD.gn b/test/unittest/app_spawn_lite_test/BUILD.gn index 3fbe3b0a..5cf2eccf 100644 --- a/test/unittest/app_spawn_lite_test/BUILD.gn +++ b/test/unittest/app_spawn_lite_test/BUILD.gn @@ -23,52 +23,24 @@ unittest("AppSpawnLiteTest") { ] include_dirs = [ - "//base/startup/appspawn_standard/interfaces/innerkits/include", - "//base/startup/appspawn_standard/common/", "//base/startup/appspawn_standard/lite/", - "//base/startup/init_lite/interfaces/innerkits/include", "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits/hilog", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/samgr", - "//foundation/distributedschedule/samgr_lite/interfaces/kits/registry", "//third_party/bounds_checking_function/include/", "//third_party/cJSON", - "${aafwk_lite_path}/interfaces/innerkits/abilitymgr_lite", - "//utils/native/lite/include", ] sources = [ - "//base/startup/appspawn_standard/common/appspawn_server.c", "//base/startup/appspawn_standard/lite/appspawn_message.c", - "//base/startup/appspawn_standard/lite/appspawn_process.c", - "//base/startup/appspawn_standard/lite/appspawn_service.c", "app_spawn_lite_test.cpp", ] - defines = [ "APPSPAWN_TEST" ] - deps = [ - "${aafwk_lite_path}/frameworks/ability_lite:aafwk_abilitykit_lite", "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", - "//base/startup/init_lite/interfaces/innerkits:libbegetutil", "//build/lite/config/component/cJSON:cjson_shared", - "//foundation/communication/ipc_lite:liteipc_adapter", - "//foundation/distributedschedule/samgr_lite/samgr:samgr", "//third_party/bounds_checking_function:libsec_shared", - "//utils/native/lite/kv_store:kv_store", - ] - - deps += [ - "//foundation/ace/ace_engine_lite/frameworks:ace_lite", - "//foundation/graphic/surface:lite_surface", - "//foundation/graphic/ui:lite_ui", - "//foundation/graphic/utils:lite_graphic_utils", ] - - if (ohos_kernel_type == "liteos_a") { - deps += [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared" ] - } } group("unittest") { - deps = [ ":AppSpawnLiteTest" ] + deps = [ ":appspawn_test" ] } diff --git a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp index 3c1d0948..5f64f6f4 100644 --- a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp +++ b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp @@ -15,14 +15,12 @@ #include #include #include -#include +#include #include #include #include #include "gtest/gtest.h" #include "appspawn_message.h" -#include "appspawn_service.h" -#include "appspawn_msg.h" using namespace testing::ext; @@ -51,6 +49,8 @@ public: StructuralFormatErrJson(); StructuralFieldMisJson(); StructuralFieldInvalidJson(); + + printf("[----------] AppSpawnLiteTest, message func test setup.\n"); } @@ -63,13 +63,19 @@ public: void SetUp() {} void TearDown() {} - static void StructuralFormatErrJson(void) + void StructuralFormatErrJson(void) { // looks like json but format error g_badStrings.push_back(std::string( "{bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName:\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV,\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID:\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( @@ -80,6 +86,10 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1\",uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID:10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID:10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,capability\":[0]}")); g_badStrings.push_back(std::string( @@ -98,6 +108,10 @@ public: "{\"bundleName\"\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\"\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\"\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); + g_badStrings.push_back(std::string( + "{\"bundleName\":\"nameV\",\"identityID\":\"1\"\"uID\":10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\"10,\"gID\":10,\"capability\":[0]}")); g_badStrings.push_back(std::string( @@ -116,7 +130,7 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0,]}")); } - static void StructuralFieldMisJson(void) + void StructuralFieldMisJson(void) { // json format correct but fields missing g_badStrings.push_back(std::string( @@ -143,7 +157,7 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000}")); } - static void StructuralFieldInvalidJson(void) + void StructuralFieldInvalidJson(void) { // field value invalid g_badStrings.push_back(std::string( @@ -371,26 +385,31 @@ HWTEST_F(AppSpawnLiteTest, SetContentFunctionTest_001, TestSize.Level0) GTEST_LOG_(INFO) << "SetContentFunctionTest_001 start"; AppSpawnContent *content = AppSpawnCreateContent("AppSpawn", NULL, 0, 0); SetContentFunction(content); - - string longProcName = "SetContentFunctionTest_001"; - int64_t longProcNameLen = longProcName.length(); - AppSpawnClientLite *liteClient = (AppSpawnClientLite *)malloc(sizeof(AppSpawnClientLite)); - EXPECT_TRUE(liteClient); - liteClient->client.id = 1; - liteClient->client.flags = 0; - - std::string validStr = - "{\"bundleName\":\"validName\",\"identityID\":\"135\",\"uID\":999,\"gID\":888,\"capability\":[0, 1, 5]}"; - int ret = SplitMessage(validStr.c_str(), validStr.length(), &liteClient->message); - EXPECT_EQ(ret, 0); - - EXPECT_EQ(content->setProcessName(content, &liteClient->client, (char*)longProcName.c_str(), - longProcNameLen), 0); - EXPECT_EQ(content->setKeepCapabilities(content, &liteClient->client), 0); - EXPECT_EQ(content->setUidGid(content, &liteClient->client), 0); - EXPECT_EQ(content->setCapabilities(content, &liteClient->client), 0); - content->runChildProcessor(content, &liteClient->client); - free(liteClient); + char *longProcName = "SetContentFunctionTest_001"; + int64_t longProcNameLen = 1024; + + std::unique_ptr clientExt = std::make_unique(); + clientExt->client.id = 1; + clientExt->client.flag = 0; + clientExt->fd[0] = 123; + clientExt->fd[1] = 456; + clientExt->property.uid = 10002; + clientExt->property.gid = 1000; + clientExt->property.gidCount = 1; + strcpy_s(clientExt->property.processName, APP_LEN_PROC_NAME, "com.ohos.settingsdata"); + strcpy_s(clientExt->property.bundleName, APP_LEN_BUNDLE_NAME, "com.ohos.settingsdata"); + strcpy_s(clientExt->property.soPath, APP_LEN_SO_PATH, " "); + clientExt->property.accessTokenId = 671201800; + strcpy_s(clientExt->property.apl, APP_APL_MAX_LEN, "system_core"); + strcpy_s(clientExt->property.renderCmd, APP_RENDER_CMD_MAX_LEN, " "); + + clientExt->property.flags = 0; + + content->setProcessName(content, clientExt->client, longProcName, longProcNameLen); + content->setKeepCapabilities(content, clientExt->client); + content->setUidGid(content, clientExt->client); + content->setCapabilities(content, clientExt->client); + content->runChildProcessor(content, clientExt->client); GTEST_LOG_(INFO) << "SetContentFunctionTest_001 end"; } -- Gitee From cb2137c140923c3e72247c7fe590e29ee15baeb5 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 15:07:40 +0800 Subject: [PATCH 15/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- lite/BUILD.gn | 6 ------ lite/appspawn_process.c | 2 -- lite/bundle.json | 3 --- 3 files changed, 11 deletions(-) diff --git a/lite/BUILD.gn b/lite/BUILD.gn index e00dbe1d..1fbe1d5c 100644 --- a/lite/BUILD.gn +++ b/lite/BUILD.gn @@ -81,9 +81,3 @@ executable("appspawn") { include_dirs += [] } } - -if (ohos_build_type == "debug") { - group("unittest") { - deps = [ "//base/startup/appspawn_standard/test/unittest/app_spawn_lite_test:unittest" ] - } -} diff --git a/lite/appspawn_process.c b/lite/appspawn_process.c index c0206f31..46802eaf 100644 --- a/lite/appspawn_process.c +++ b/lite/appspawn_process.c @@ -167,12 +167,10 @@ static void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) appProperty->message.bundleName, appProperty->message.identityID, appProperty->message.uID, appProperty->message.gID); -#ifndef APPSPAWN_TEST if (AbilityMain(appProperty->message.identityID) != 0) { APPSPAWN_LOGE("[appspawn] AbilityMain execute failed, pid %d.", getpid()); exit(0x7f); // 0x7f: user specified } -#endif } void SetContentFunction(AppSpawnContent *content) diff --git a/lite/bundle.json b/lite/bundle.json index 843ec327..e183e850 100644 --- a/lite/bundle.json +++ b/lite/bundle.json @@ -38,9 +38,6 @@ "build": { "sub_component": [ "//base/startup/appspawn_standard/lite:appspawn_lite" - ], - "test": [ - "//base/startup/appspawn_standard/test/unittest/app_spawn_lite_test:unittest" ] } } -- Gitee From 07bee9060de7268f8e77bad482e9cb0ce89d5944 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 15:21:44 +0800 Subject: [PATCH 16/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- standard/appspawn_service.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 8caa79e2..2094094e 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -369,7 +369,7 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) g_appSpawnContent = NULL; } -static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) +static int CreateHashForApp(AppSpawnContentExt *appSpawnContent) { HashInfo hashInfo = { AppInfoHashNodeCompare, @@ -381,6 +381,7 @@ static void CreateHashForApp(AppSpawnContentExt *appSpawnContent) }; int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); APPSPAWN_CHECK(ret == 0, free(appSpawnContent); return NULL, "Failed to create hash for app"); + return 0; } AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode) -- Gitee From 112e3da506f23f6b2fdf6a31618753d31b1345d0 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 15:41:31 +0800 Subject: [PATCH 17/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- adapter/appspawn_sandbox.cpp | 17 ++---- standard/appspawn_process.c | 22 +++---- standard/appspawn_service.c | 58 +++++++------------ .../app_spawn_lite_test.cpp | 37 ++++-------- .../app_spawn_standard_test.cpp | 2 +- 5 files changed, 46 insertions(+), 90 deletions(-) diff --git a/adapter/appspawn_sandbox.cpp b/adapter/appspawn_sandbox.cpp index 51dcee01..c2f10eba 100644 --- a/adapter/appspawn_sandbox.cpp +++ b/adapter/appspawn_sandbox.cpp @@ -330,11 +330,11 @@ static int32_t DoSandboxRootFolderCreate(const std::string &sandboxPackagePath) return 0; } -static void MatchSandbox(AppSpawnClientExt *appProperty) +int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) { - if (appProperty == nullptr) { - return; - } + int rc = 0; + APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; if (strcmp("system_basic", appProperty->property.apl) == 0) { EnterSandbox("priv-app"); } else if (strcmp("normal", appProperty->property.apl) == 0) { @@ -345,15 +345,8 @@ static void MatchSandbox(AppSpawnClientExt *appProperty) APPSPAWN_LOGE("AppSpawnServer::Failed to match appspawn sandbox %s", appProperty->property.apl); EnterSandbox("app"); } -} -int32_t SetAppSandboxProperty(struct AppSpawnContent_ *content, AppSpawnClient *client) -{ - int rc = 0; - APPSPAWN_CHECK(client != NULL, return -1, "Invalid appspwn client"); - AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; - MatchSandbox(appProperty); - // create /mnt/sandbox/ path�?later put it to rootfs module + // create /mnt/sandbox/ pathï¿?later put it to rootfs module std::string sandboxPackagePath = "/"; sandboxPackagePath += appProperty->property.bundleName; mkdir(sandboxPackagePath.c_str(), FILE_MODE); diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c index d0f00c70..770f0194 100644 --- a/standard/appspawn_process.c +++ b/standard/appspawn_process.c @@ -162,7 +162,7 @@ static void InitDebugParams(struct AppSpawnContent_ *content, AppSpawnClient *cl } bool ret = (*initParam)(appProperty->property.processName); if (!ret) { - APPSPAWN_LOGV("init parameters failed."); + APPSPAWN_LOGV("init parameters failed."); } dlclose(handle); } @@ -242,18 +242,6 @@ static int32_t SetFileDescriptors(struct AppSpawnContent_ *content, AppSpawnClie return 0; } -static void Free(char **argv) -{ - argv[0] = NULL; - for (int i = 0; i < NULL_INDEX; i++) { - if (argv[i] != NULL) { - free(argv[i]); - argv[i] = NULL; - } - } - free(argv); -} - static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client) { AppParameter *appProperty = &((AppSpawnClientExt *)client)->property; @@ -310,7 +298,13 @@ static int ColdStartApp(struct AppSpawnContent_ *content, AppSpawnClient *client APPSPAWN_LOGE("Failed to execv, errno = %d", errno); } } - Free(argv); + argv[0] = NULL; + for (int i = 0; i < NULL_INDEX; i++) { + if (argv[i] != NULL) { + free(argv[i]); + } + } + free(argv); return ret; } diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c index 2094094e..de3cb333 100644 --- a/standard/appspawn_service.c +++ b/standard/appspawn_service.c @@ -202,21 +202,6 @@ static int WaitChild(int fd, int pid, const AppSpawnClientExt *appProperty) return result; } -static void StartColdApp(AppSpawnClientExt *appProperty) -{ - if (appProperty == NULL) { - return; - } - if (appProperty->property.flags & 0x01) { - char cold[10] = {0}; // 10 cold - int ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); - APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); - if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { - appProperty->client.flags |= APP_COLD_START; - } - } -} - static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, uint32_t buffLen) { APPSPAWN_CHECK(buffer != NULL && buffLen >= sizeof(AppParameter), LE_CloseTask(LE_GetDefaultLoop(), taskHandle); @@ -237,7 +222,14 @@ static void OnReceiveRequest(const TaskHandle taskHandle, const uint8_t *buffer, g_appSpawnContent->timer = NULL; } // cold start app - StartColdApp(appProperty); + if (appProperty->property.flags & 0x01) { + char cold[10] = {0}; // 10 cold + ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); + APPSPAWN_LOGV("appspawn.cold.boot %s %d ", cold, ret); + if (ret > 0 && (strcmp(cold, "true") == 0 || strcmp(cold, "1") == 0 || strcmp(cold, "enable") == 0)) { + appProperty->client.flags |= APP_COLD_START; + } + } // create pipe for commication from child if (pipe(appProperty->fd) == -1) { @@ -333,8 +325,7 @@ void AppSpawnColdRun(AppSpawnContent *content, int argc, char *const argv[]) int ret = GetAppSpawnClientFromArg(argc, argv, client); APPSPAWN_CHECK(ret == 0, free(client); return, "Failed to get client from arg"); - APPSPAWN_LOGI("Cold running %d processName %s %u ", getpid(), client->property.processName, - content->longProcNameLen); + APPSPAWN_LOGI("Cold running %d processName %s %u ", getpid(), client->property.processName, content->longProcNameLen); ret = DoStartApp(content, &client->client, content->longProcName, content->longProcNameLen); if (ret == 0 && content->runChildProcessor != NULL) { @@ -369,21 +360,6 @@ static void AppSpawnRun(AppSpawnContent *content, int argc, char *const argv[]) g_appSpawnContent = NULL; } -static int CreateHashForApp(AppSpawnContentExt *appSpawnContent) -{ - HashInfo hashInfo = { - AppInfoHashNodeCompare, - TestHashKeyCompare, - AppInfoHashNodeFunction, - AppInfoHashKeyFunction, - AppInfoHashNodeFree, - APP_HASH_BUTT - }; - int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); APPSPAWN_CHECK(ret == 0, free(appSpawnContent); - return NULL, "Failed to create hash for app"); - return 0; -} - AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, uint32_t longProcNameLen, int mode) { APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop"); @@ -398,7 +374,7 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam appSpawnContent->timer = NULL; appSpawnContent->flags = 0; appSpawnContent->server = NULL; - appSpawnContent->sigHandler = NULL; + appSpawnContent->sigHandler = NULL; appSpawnContent->content.initAppSpawn = AppSpawnInit; if (mode) { @@ -408,10 +384,20 @@ AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcNam appSpawnContent->content.runAppSpawn = AppSpawnRun; // create hash for app - CreateHashForApp(appSpawnContent); + HashInfo hashInfo = { + AppInfoHashNodeCompare, + TestHashKeyCompare, + AppInfoHashNodeFunction, + AppInfoHashKeyFunction, + AppInfoHashNodeFree, + APP_HASH_BUTT + }; + int ret = HashMapCreate(&appSpawnContent->appMap, &hashInfo); + APPSPAWN_CHECK(ret == 0, free(appSpawnContent); + return NULL, "Failed to create hash for app"); char path[128] = {0}; // 128 max path - int ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); + ret = snprintf_s(path, sizeof(path), sizeof(path) - 1, "%s%s", SOCKET_DIR, socketName); APPSPAWN_CHECK(ret >= 0, free(appSpawnContent); return NULL, "Failed to snprintf_s %d", ret); int socketId = GetControlSocket(socketName); diff --git a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp index 5f64f6f4..f07e7243 100644 --- a/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp +++ b/test/unittest/app_spawn_lite_test/app_spawn_lite_test.cpp @@ -46,25 +46,6 @@ public: g_badStrings.push_back(std::string("\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"")); g_badStrings.push_back(std::string(".............................................")); g_badStrings.push_back(std::string("....%%%....^..***@##.../*--++......$$&&.....")); - StructuralFormatErrJson(); - StructuralFieldMisJson(); - StructuralFieldInvalidJson(); - - - printf("[----------] AppSpawnLiteTest, message func test setup.\n"); - } - - static void TearDownTestCase() - { - g_badStrings.clear(); - g_goodStrings.clear(); - printf("[----------] AppSpawnLiteTest, message func test teardown.\n"); - } - void SetUp() {} - void TearDown() {} - - void StructuralFormatErrJson(void) - { // looks like json but format error g_badStrings.push_back(std::string( "{bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0]}")); @@ -128,10 +109,6 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0],}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1\",\"uID\":10,\"gID\":10,\"capability\":[0,]}")); - } - - void StructuralFieldMisJson(void) - { // json format correct but fields missing g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); @@ -155,10 +132,6 @@ public: "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"\":[0]}")); g_badStrings.push_back(std::string( "{\"bundleName\":\"nameV\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000}")); - } - - void StructuralFieldInvalidJson(void) - { // field value invalid g_badStrings.push_back(std::string( "{\"bundleName\":\"\",\"identityID\":\"1234\",\"uID\":1000,\"gID\":1000,\"capability\":[0]}")); @@ -194,7 +167,17 @@ public: "{\"bundleName\":\"testvalid3\",\"identityID\":\"999\",\"uID\":1002,\"gID\":1002,\"capability\":[]}")); g_goodStrings.push_back(std::string( "{\"bundleName\":\"testvalid3\",\"identityID\":\"3\",\"uID\":1002,\"gID\":1002,\"capability\":[1,2]}")); + printf("[----------] AppSpawnLiteTest, message func test setup.\n"); } + + static void TearDownTestCase() + { + g_badStrings.clear(); + g_goodStrings.clear(); + printf("[----------] AppSpawnLiteTest, message func test teardown.\n"); + } + void SetUp() {} + void TearDown() {} }; /* diff --git a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp index e4c34524..0cca5b0a 100644 --- a/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp +++ b/test/unittest/app_spawn_standard_test/app_spawn_standard_test.cpp @@ -179,7 +179,7 @@ HWTEST(AppSpawnStandardTest, App_Spawn_Standard_004, TestSize.Level0) } client->property.flags = 0; - char* argv[] = {const_cast("AppSpawnStandardTest4"), const_cast("test4")}; + char* argv[] = {(char*)"AppSpawnStandardTest4", (char*)"test4"}; int argc = sizeof(argv)/sizeof(argv[0]); EXPECT_EQ(GetAppSpawnClientFromArg(argc, argv, client), -1); -- Gitee From f0ecdb7185be51990db8adba9ddb7cf8f17ff99e Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 16:05:27 +0800 Subject: [PATCH 18/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=BC=96=E8=AF=91?= =?UTF-8?q?=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 7 +++++++ interfaces/innerkits/include/client_socket.h | 1 + 2 files changed, 8 insertions(+) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 4b8cad0d..ff1b2fbe 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -40,6 +40,11 @@ enum AppType { APP_TYPE_NATIVE // Native C++ app }; +enum AppOperateType { + DEFAULT = 0, + GET_RENDER_TERMINATION_STATUS, +}; + #define APP_MSG_MAX_SIZE 4096 // appspawn message max size #define APP_LEN_PROC_NAME 256 // process name length #define APP_LEN_BUNDLE_NAME 256 // bundle name length @@ -64,6 +69,8 @@ typedef struct AppParameter_ { char apl[APP_APL_MAX_LEN]; char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; + int32_t pid; // query render process exited status by render process pid + AppOperateType code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 0a839117..2228c5fa 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -94,6 +94,7 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; + using AppOperateCode = AppOperateType; private: /** * Connects a client socket. -- Gitee From f165db9b58ccf15d4ec2b4cab64bbb8b952cc973 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 16:21:44 +0800 Subject: [PATCH 19/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 4 ++-- interfaces/innerkits/include/client_socket.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index ff1b2fbe..4cc23485 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -40,7 +40,7 @@ enum AppType { APP_TYPE_NATIVE // Native C++ app }; -enum AppOperateType { +enum AppOperateTypeValue { DEFAULT = 0, GET_RENDER_TERMINATION_STATUS, }; @@ -70,7 +70,7 @@ typedef struct AppParameter_ { char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; int32_t pid; // query render process exited status by render process pid - AppOperateType code; + AppOperateTypeValue code; } AppParameter; #ifdef __cplusplus diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 2228c5fa..87e10da3 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -94,7 +94,7 @@ public: static constexpr int APPSPAWN_COLD_BOOT = APP_COLD_BOOT; using AppProperty = AppParameter; - using AppOperateCode = AppOperateType; + using AppOperateCode = AppOperateTypeValue; private: /** * Connects a client socket. -- Gitee From 00d1d90285f1dbe5719c04b46cc8df8013693101 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 16:31:22 +0800 Subject: [PATCH 20/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 4cc23485..44664cef 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -70,7 +70,7 @@ typedef struct AppParameter_ { char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; int32_t pid; // query render process exited status by render process pid - AppOperateTypeValue code; + enum AppOperateTypeValue code; } AppParameter; #ifdef __cplusplus -- Gitee From 11b32a8215e79d04b6ce5f043d7612833dc42722 Mon Sep 17 00:00:00 2001 From: xlei1030 Date: Tue, 26 Apr 2022 17:46:52 +0800 Subject: [PATCH 21/21] =?UTF-8?q?=E4=BF=AE=E6=94=B9bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xlei1030 --- interfaces/innerkits/include/appspawn_msg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h index 44664cef..5c0435f1 100644 --- a/interfaces/innerkits/include/appspawn_msg.h +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -69,8 +69,8 @@ typedef struct AppParameter_ { char apl[APP_APL_MAX_LEN]; char renderCmd[APP_RENDER_CMD_MAX_LEN]; uint32_t flags; - int32_t pid; // query render process exited status by render process pid - enum AppOperateTypeValue code; + // int32_t pid; // query render process exited status by render process pid + // enum AppOperateTypeValue code; } AppParameter; #ifdef __cplusplus -- Gitee