From ec77c2977598069a75fb022a34e4163f239bd660 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Wed, 2 Mar 2022 20:55:30 +0800 Subject: [PATCH] =?UTF-8?q?Add:=20ClientSocket=E7=B1=BB=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=88=90=E5=91=98=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: xionglei6 --- BUILD.gn | 14 +++ bundle.json | 1 + interfaces/innerkits/include/client_socket.h | 2 + src/appspawn_server.cpp | 113 +++++++++++++++---- src/include/appspawn_server.h | 6 +- tools/appspawn_start_app.cpp | 75 ++++++++++++ 6 files changed, 188 insertions(+), 23 deletions(-) create mode 100644 tools/appspawn_start_app.cpp diff --git a/BUILD.gn b/BUILD.gn index 9f0e9b9b..1a1a33e1 100755 --- a/BUILD.gn +++ b/BUILD.gn @@ -95,6 +95,20 @@ 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" diff --git a/bundle.json b/bundle.json index 502b4725..ead2fb03 100644 --- a/bundle.json +++ b/bundle.json @@ -37,6 +37,7 @@ "//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:webview", "//base/startup/appspawn_standard/interfaces/innerkits:appspawn_socket_client" ], diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index 7be38b87..dc459bc7 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -90,6 +90,7 @@ public: 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; struct AppProperty { uint32_t uid; // the UNIX uid that the child process setuid() to after fork() @@ -102,6 +103,7 @@ public: uint32_t accessTokenId; char apl[APL_MAX_LEN]; char renderCmd[RENDER_CMD_MAX_LEN]; + uint32_t flags; }; private: diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp index e5679e6a..4f99f948 100644 --- a/src/appspawn_server.cpp +++ b/src/appspawn_server.cpp @@ -40,6 +40,7 @@ #include "system_ability_definition.h" #include "token_setproc.h" #include "parameter.h" +#include "parameters.h" #include "beget_ext.h" #ifdef WITH_SELINUX #include "hap_restorecon.h" @@ -246,6 +247,56 @@ void AppSpawnServer::LoadAceLib() #endif } +static void ClearEnvironment(void) +{ + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGTERM); + 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 != 0) { + HiLog::Error(LABEL, "Failed to execv, errno = %{public}d", errno); + NotifyResToParentProc(fd, -1); + } + return 0; +} + int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, ClientSocket::AppProperty *appProperty, int connectFd, pid_t &pid) { @@ -274,8 +325,15 @@ int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, socket_->CloseServerMonitor(); } close(fd[0]); // close read fd + ClearEnvironment(); UninstallSigHandler(); - SetAppProcProperty(appProperty, longProcName, longProcNameLen, fd); + 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); } read(fd[0], &buff, sizeof(buff)); // wait child process resutl @@ -327,7 +385,8 @@ bool AppSpawnServer::ServerMain(char *longProcName, int64_t longProcNameLen) appMap_[pid] = appProperty->processName; } socket_->CloseConnection(connectFd); // close socket connection - APPSPAWN_LOGI("AppSpawnServer::parent process create app finish, pid = %d %s", pid, appProperty->processName); + APPSPAWN_LOGI("AppSpawnServer::parent process create app finish, pid = %d uid %d %s %s", + pid, appProperty->uid, appProperty->processName, appProperty->bundleName); } while (appMap_.size() > 0) { @@ -794,66 +853,64 @@ int32_t AppSpawnServer::SetAppSandboxProperty(const ClientSocket::AppProperty *a void AppSpawnServer::SetAppAccessToken(const ClientSocket::AppProperty *appProperty) { int32_t ret = SetSelfTokenID(appProperty->accessTokenId); - if (ret != 0) { - HiLog::Error(LABEL, "AppSpawnServer::Failed to set access token id, errno = %{public}d", errno); - } + 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 != 0) { - HiLog::Error(LABEL, "AppSpawnServer::Failed to hap domain set context, errno = %{public}d", errno); + 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[FDLEN2]) + int64_t longProcNameLen, const int32_t fd) { - pid_t newPid = getpid(); - HiLog::Debug(LABEL, "AppSpawnServer::Success to fork new process, pid = %{public}d", newPid); - int32_t ret = ERR_OK; - - ret = SetAppSandboxProperty(appProperty); + HiLog::Debug(LABEL, "AppSpawnServer::Success to fork new process, pid = %{public}d", getpid()); + int32_t ret = SetAppSandboxProperty(appProperty); if (FAILED(ret)) { - NotifyResToParentProc(fd[1], ret); + NotifyResToParentProc(fd, ret); return false; } ret = SetKeepCapabilities(appProperty->uid); if (FAILED(ret)) { - NotifyResToParentProc(fd[1], ret); + NotifyResToParentProc(fd, ret); return false; } - SetAppAccessToken(appProperty); - ret = SetProcessName(longProcName, longProcNameLen, appProperty->processName, strlen(appProperty->processName) + 1); if (FAILED(ret)) { - NotifyResToParentProc(fd[1], 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[1], ret); + NotifyResToParentProc(fd, ret); return false; } #endif ret = SetFileDescriptors(); if (FAILED(ret)) { - NotifyResToParentProc(fd[1], ret); + NotifyResToParentProc(fd, ret); return false; } ret = SetCapabilities(); if (FAILED(ret)) { - NotifyResToParentProc(fd[1], ret); + NotifyResToParentProc(fd, ret); return false; } // notify success to father process and start app process - NotifyResToParentProc(fd[1], ret); + NotifyResToParentProc(fd, ret); #ifdef WEBVIEW_SPAWN using FuncType = void (*)(const char *cmd); @@ -867,7 +924,7 @@ bool AppSpawnServer::SetAppProcProperty(const ClientSocket::AppProperty *appProp AppExecFwk::MainThread::Start(); #endif - HiLog::Error(LABEL, "Failed to start process, pid = %{public}d", newPid); + HiLog::Error(LABEL, "Failed to start process, pid = %{public}d", getpid()); return false; } @@ -927,5 +984,17 @@ bool AppSpawnServer::CheckAppProperty(const ClientSocket::AppProperty *appProper 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_server.h b/src/include/appspawn_server.h index 6e2192a8..694b3e43 100644 --- a/src/include/appspawn_server.h +++ b/src/include/appspawn_server.h @@ -70,7 +70,11 @@ public: */ 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; @@ -162,7 +166,7 @@ private: * Sets app process property. */ bool SetAppProcProperty(const ClientSocket::AppProperty *appProperty, char *longProcName, - int64_t longProcNameLen, const int32_t fd[FDLEN2]); + int64_t longProcNameLen, const int32_t fd); /** * Notify diff --git a/tools/appspawn_start_app.cpp b/tools/appspawn_start_app.cpp new file mode 100644 index 00000000..3f91515f --- /dev/null +++ b/tools/appspawn_start_app.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 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; +} \ No newline at end of file -- Gitee