From 8696d99eb33f263f276d646ee287859547d5954f Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Thu, 24 Mar 2022 14:42:59 +0800 Subject: [PATCH 1/3] fix: pipe error Signed-off-by: xionglei6 --- src/appspawn_server.cpp | 31 ++++++++++++++++++++++++++----- src/socket/client_socket.cpp | 9 +++++---- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp index 38008a33..9d16e302 100644 --- a/src/appspawn_server.cpp +++ b/src/appspawn_server.cpp @@ -69,6 +69,8 @@ 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 int32_t RETRY_TIME = 10; +constexpr int32_t DELAY_US = 10 * 1000; // 10ms constexpr std::string_view BUNDLE_NAME_MEDIA_LIBRARY("com.ohos.medialibrary.MediaLibraryDataA"); constexpr std::string_view BUNDLE_NAME_SCANNER("com.ohos.medialibrary.MediaScannerAbilityA"); @@ -315,6 +317,27 @@ int AppSpawnServer::DoColdStartApp(ClientSocket::AppProperty *appProperty, int f return 0; } +static int WaitChild(int fd, int pid, ClientSocket::AppProperty *appProperty) +{ + int result = 0; + int count = 0; + while (count < RETRY_TIME) { // wait child process resutl + int readLen = read(fd, &result, sizeof(result)); + if (readLen == sizeof(result)) { + break; + } + usleep(DELAY_US); + count++; + } + if (count >= RETRY_TIME) { + APPSPAWN_LOGI("Time out for child %d %s ", appProperty->processName, pid); + result = ERR_OK; + } + HiLog::Info(LABEL, "child process %{public}s %{public}s pid %{public}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) { @@ -322,11 +345,11 @@ int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, return -EINVAL; } int32_t fd[FDLEN2] = {FD_INIT_VALUE, FD_INIT_VALUE}; - int32_t buff = 0; if (pipe(fd) == -1) { HiLog::Error(LABEL, "create pipe fail, errno = %{public}d", errno); return ERR_PIPE_FAIL; } + fcntl(fd[0], F_SETFL, O_NONBLOCK); InstallSigHandler(); pid = fork(); @@ -354,12 +377,10 @@ int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, } _exit(0); } - read(fd[0], &buff, sizeof(buff)); // wait child process resutl + int ret = WaitChild(fd[0], pid, appProperty); close(fd[0]); close(fd[1]); - - HiLog::Info(LABEL, "child process init %{public}s", (buff == ERR_OK) ? "success" : "fail"); - return (buff == ERR_OK) ? 0 : buff; + return ret; } void AppSpawnServer::QuickExitMain() diff --git a/src/socket/client_socket.cpp b/src/socket/client_socket.cpp index 308f389c..699bbaf9 100644 --- a/src/socket/client_socket.cpp +++ b/src/socket/client_socket.cpp @@ -63,20 +63,17 @@ int ClientSocket::ConnectSocket(int connectFd) } if (PackSocketAddr() != 0) { - CloseSocket(connectFd); return -1; } if ((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, "Client: Failed to set opt of socket %d, err %d", connectFd, errno); - CloseSocket(connectFd); return -1; } if (connect(connectFd, reinterpret_cast(&socketAddr_), socketAddrLen_) < 0) { HiLog::Warn(LABEL, "Client: Connect on socket fd %d, failed: %d", connectFd, errno); - CloseSocket(connectFd); return -1; } @@ -86,7 +83,11 @@ int ClientSocket::ConnectSocket(int connectFd) int ClientSocket::ConnectSocket() { - return ConnectSocket(socketFd_); + int ret = ConnectSocket(socketFd_); + if (ret != 0) { + CloseClient(); + } + return ret; } int ClientSocket::WriteSocketMessage(const void *buf, int len) -- Gitee From 84ea012c0b9a8c89c992b967adb5d1f1944ea23a Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 25 Mar 2022 12:39:59 +0800 Subject: [PATCH 2/3] fix: pipe error Signed-off-by: xionglei6 --- src/appspawn_server.cpp | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp index 9d16e302..c47b3756 100644 --- a/src/appspawn_server.cpp +++ b/src/appspawn_server.cpp @@ -69,8 +69,6 @@ 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 int32_t RETRY_TIME = 10; -constexpr int32_t DELAY_US = 10 * 1000; // 10ms constexpr std::string_view BUNDLE_NAME_MEDIA_LIBRARY("com.ohos.medialibrary.MediaLibraryDataA"); constexpr std::string_view BUNDLE_NAME_SCANNER("com.ohos.medialibrary.MediaScannerAbilityA"); @@ -319,21 +317,24 @@ int AppSpawnServer::DoColdStartApp(ClientSocket::AppProperty *appProperty, int f static int WaitChild(int fd, int pid, ClientSocket::AppProperty *appProperty) { - int result = 0; - int count = 0; - while (count < RETRY_TIME) { // wait child process resutl - int readLen = read(fd, &result, sizeof(result)); - if (readLen == sizeof(result)) { - break; - } - usleep(DELAY_US); - count++; - } - if (count >= RETRY_TIME) { + 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(1, &rd, nullptr, nullptr, &tv); + if (ret == 0) { // timeout APPSPAWN_LOGI("Time out for child %d %s ", appProperty->processName, pid); result = ERR_OK; + } else if (ret == -1) { + APPSPAWN_LOGI("Error for child %d %s ", appProperty->processName, pid); + result = ERR_OK; + } else { + ret = read(fd, &result, sizeof(result)); } - HiLog::Info(LABEL, "child process %{public}s %{public}s pid %{public}d", + APPSPAWN_LOGI("child process %s %s pid %d", appProperty->processName, (result == ERR_OK) ? "success" : "fail", pid); return (result == ERR_OK) ? 0 : result; } -- Gitee From 0e3404c6af79eafcc3c166b31054b4f562c985c3 Mon Sep 17 00:00:00 2001 From: xionglei6 Date: Fri, 25 Mar 2022 13:02:30 +0800 Subject: [PATCH 3/3] fix: pipe error Signed-off-by: xionglei6 --- .../innerkits/client/appspawn_socket.cpp | 155 ++++++++++ interfaces/innerkits/client/client_socket.cpp | 102 +++++++ interfaces/innerkits/include/appspawn_msg.h | 75 +++++ .../innerkits/include/appspawn_socket.h | 2 +- interfaces/innerkits/include/client_socket.h | 2 +- src/appspawn_msg_peer.cpp | 4 +- src/appspawn_server.cpp | 80 ++++-- src/include/appspawn_msg_peer.h | 2 +- src/include/appspawn_server.h | 4 +- src/include/server_socket.h | 2 +- src/socket/appspawn_socket.cpp | 19 +- src/socket/client_socket.cpp | 13 +- src/socket/server_socket.cpp | 36 +-- standard/appspawn_process.c | 184 ++++++++++++ standard/appspawn_service.c | 270 ++++++++++++++++++ standard/appspawn_service.h | 56 ++++ standard/main.c | 83 ++++++ test/clienttest/appspawn_sample.cpp | 0 test/clienttest/appspawn_sample.h | 0 test/clienttest/main.cpp | 0 tools/appspawn_start_app.cpp | 150 +++++----- 21 files changed, 1103 insertions(+), 136 deletions(-) create mode 100755 interfaces/innerkits/client/appspawn_socket.cpp create mode 100755 interfaces/innerkits/client/client_socket.cpp create mode 100755 interfaces/innerkits/include/appspawn_msg.h create mode 100755 standard/appspawn_process.c create mode 100755 standard/appspawn_service.c create mode 100755 standard/appspawn_service.h create mode 100755 standard/main.c create mode 100755 test/clienttest/appspawn_sample.cpp create mode 100755 test/clienttest/appspawn_sample.h create mode 100755 test/clienttest/main.cpp diff --git a/interfaces/innerkits/client/appspawn_socket.cpp b/interfaces/innerkits/client/appspawn_socket.cpp new file mode 100755 index 00000000..a42a8a89 --- /dev/null +++ b/interfaces/innerkits/client/appspawn_socket.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2021 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_socket.h" + +#include +#include +#include + +#include "hilog/log.h" +#include "pubdef.h" +#include "securec.h" + +namespace OHOS { +namespace AppSpawn { +using namespace OHOS::HiviewDFX; +static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "AppSpawnSocket"}; + +AppSpawnSocket::AppSpawnSocket(const std::string &name) +{ + socketName_ = name; +} + +AppSpawnSocket::~AppSpawnSocket() +{ + if (socketFd_ > 0) { + CloseSocket(socketFd_); + socketFd_ = -1; + } +} + +int AppSpawnSocket::GetSocketFd() const +{ + return socketFd_; +} + +int AppSpawnSocket::PackSocketAddr() +{ + if (socketName_.empty()) { + HiLog::Error(LABEL, "Invalid socket name: empty"); + return -EINVAL; + } + + if (memset_s(&socketAddr_, sizeof(socketAddr_), 0, sizeof(socketAddr_)) != EOK) { + HiLog::Error(LABEL, "Failed to memset socket addr"); + return -1; + } + + socklen_t pathLen = 0; + if (socketName_[0] == '/') { + pathLen = socketName_.length(); + } else { + pathLen = socketDir_.length() + socketName_.length(); + } + socklen_t pathSize = sizeof(socketAddr_.sun_path); + if (pathLen >= pathSize) { + HiLog::Error(LABEL, "Invalid socket name: '%s' too long", socketName_.c_str()); + return -1; + } + + int len = 0; + if (socketName_[0] == '/') { + len = snprintf_s(socketAddr_.sun_path, pathSize, (pathSize - 1), "%s", socketName_.c_str()); + } else { + len = snprintf_s(socketAddr_.sun_path, pathSize, (pathSize - 1), "%s%s", + socketDir_.c_str(), socketName_.c_str()); + } + if (static_cast(pathLen) != len) { + HiLog::Error(LABEL, "Failed to copy socket path"); + return -1; + } + + socketAddr_.sun_family = AF_LOCAL; + socketAddrLen_ = offsetof(struct sockaddr_un, sun_path) + pathLen + 1; + + return 0; +} + +int AppSpawnSocket::CreateSocket() +{ + int socketFd = socket(AF_UNIX, SOCK_STREAM, 0); // SOCK_SEQPACKET + if (socketFd < 0) { + HiLog::Error(LABEL, "Failed to create socket: %d", errno); + return (-errno); + } + + HiLog::Debug(LABEL, "Created socket with fd %d", socketFd); + return socketFd; +} + +void AppSpawnSocket::CloseSocket(int &socketFd) +{ + if (socketFd >= 0) { + HiLog::Debug(LABEL, "Closed socket with fd %d", socketFd); + close(socketFd); + socketFd = -1; + } +} + +int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len) +{ + if (socketFd < 0 || len <= 0 || buf == nullptr) { + HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len); + return -1; + } + + if (memset_s(buf, len, 0, len) != EOK) { + HiLog::Warn(LABEL, "Failed to memset read buf"); + return -1; + } + + ssize_t rLen = TEMP_FAILURE_RETRY(read(socketFd, buf, len)); + if (rLen < 0) { + HiLog::Error(LABEL, "Read message from fd %d error %zd: %d", socketFd, rLen, errno); + return -EFAULT; + } + + return rLen; +} + +int AppSpawnSocket::WriteSocketMessage(int socketFd, const void *buf, int len) +{ + if (socketFd < 0 || len <= 0 || buf == nullptr) { + HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len); + return -1; + } + + ssize_t written = 0; + ssize_t remain = static_cast(len); + const uint8_t *offset = reinterpret_cast(buf); + for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) { + wLen = write(socketFd, offset, remain); + HiLog::Debug(LABEL, "socket fd %d, wLen %zd", socketFd, wLen); + if ((wLen <= 0) && (errno != EINTR)) { + HiLog::Error(LABEL, "Failed to write message to fd %d, error %zd: %d", socketFd, wLen, errno); + return (-errno); + } + } + + return written; +} +} // namespace AppSpawn +} // namespace OHOS diff --git a/interfaces/innerkits/client/client_socket.cpp b/interfaces/innerkits/client/client_socket.cpp new file mode 100755 index 00000000..308f389c --- /dev/null +++ b/interfaces/innerkits/client/client_socket.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2021 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 "client_socket.h" + +#include +#include +#include + +#include "hilog/log.h" +#include "securec.h" + +namespace OHOS { +namespace AppSpawn { +using namespace OHOS::HiviewDFX; +static constexpr HiLogLabel LABEL = {LOG_CORE, 0, "ClientSocket"}; + +ClientSocket::ClientSocket(const std::string &client) : AppSpawnSocket(client) +{} + +int ClientSocket::CreateClient() +{ + if (socketFd_ < 0) { + socketFd_ = CreateSocket(); + if (socketFd_ < 0) { + HiLog::Error(LABEL, "Client: Create socket failed"); + return socketFd_; + } + } + + HiLog::Debug(LABEL, "Client: CreateClient socket fd %d", socketFd_); + return 0; +} + +void ClientSocket::CloseClient() +{ + if (socketFd_ < 0) { + HiLog::Error(LABEL, "Client: Invalid connectFd %d", socketFd_); + return; + } + + CloseSocket(socketFd_); + socketFd_ = -1; +} + +int ClientSocket::ConnectSocket(int connectFd) +{ + if (connectFd < 0) { + HiLog::Error(LABEL, "Client: Invalid socket fd: %d", connectFd); + return -1; + } + + if (PackSocketAddr() != 0) { + CloseSocket(connectFd); + return -1; + } + + if ((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, "Client: Failed to set opt of socket %d, err %d", connectFd, errno); + CloseSocket(connectFd); + return -1; + } + + if (connect(connectFd, reinterpret_cast(&socketAddr_), socketAddrLen_) < 0) { + HiLog::Warn(LABEL, "Client: Connect on socket fd %d, failed: %d", connectFd, errno); + CloseSocket(connectFd); + return -1; + } + + HiLog::Debug(LABEL, "Client: Connected on socket fd %d, name '%s'", connectFd, socketAddr_.sun_path); + return 0; +} + +int ClientSocket::ConnectSocket() +{ + return ConnectSocket(socketFd_); +} + +int ClientSocket::WriteSocketMessage(const void *buf, int len) +{ + return WriteSocketMessage(socketFd_, buf, len); +} + +int ClientSocket::ReadSocketMessage(void *buf, int len) +{ + return ReadSocketMessage(socketFd_, buf, len); +} +} // namespace AppSpawn +} // namespace OHOS diff --git a/interfaces/innerkits/include/appspawn_msg.h b/interfaces/innerkits/include/appspawn_msg.h new file mode 100755 index 00000000..f7ca8dff --- /dev/null +++ b/interfaces/innerkits/include/appspawn_msg.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021 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 +#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 +}; + +#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; +} AppParameter; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/interfaces/innerkits/include/appspawn_socket.h b/interfaces/innerkits/include/appspawn_socket.h index 6edf8b72..ceb1800a 100644 --- a/interfaces/innerkits/include/appspawn_socket.h +++ b/interfaces/innerkits/include/appspawn_socket.h @@ -108,7 +108,7 @@ protected: const std::string socketDir_ = "/dev/socket/"; #endif const unsigned int listenBacklog_ = 50; // 50: max num of clients - static constexpr struct timeval SOCKET_TIMEOUT = {5, 0}; // 5, 0: { 5 sec, 0 msec } for timeout + static constexpr struct timeval SOCKET_TIMEOUT = {2, 0}; // 2, 0: { 2 sec, 0 msec } for timeout }; } // namespace AppSpawn } // namespace OHOS diff --git a/interfaces/innerkits/include/client_socket.h b/interfaces/innerkits/include/client_socket.h index dc459bc7..85e979a6 100644 --- a/interfaces/innerkits/include/client_socket.h +++ b/interfaces/innerkits/include/client_socket.h @@ -29,7 +29,7 @@ public: explicit ClientSocket(const std::string &client); /** - * Destructor used to destory a ClientSocket + * Destructor used to destroy a ClientSocket */ virtual ~ClientSocket() = default; diff --git a/src/appspawn_msg_peer.cpp b/src/appspawn_msg_peer.cpp index e658e755..dec21fb6 100644 --- a/src/appspawn_msg_peer.cpp +++ b/src/appspawn_msg_peer.cpp @@ -49,12 +49,12 @@ int AppSpawnMsgPeer::GetConnectFd() const int AppSpawnMsgPeer::Response(pid_t pid) { if ((socket_ == nullptr) || (connectFd_ < 0)) { - HiLog::Error(LABEL, "Invalid socket params: connectFd %d", connectFd_); + 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 %d", connectFd_); + HiLog::Error(LABEL, "Failed to write message: connectFd %{public}d", connectFd_); return (-errno); } diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp index c47b3756..55fd04c5 100644 --- a/src/appspawn_server.cpp +++ b/src/appspawn_server.cpp @@ -15,6 +15,7 @@ #include "appspawn_server.h" +#include #include #include #include @@ -72,6 +73,8 @@ 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; @@ -114,14 +117,14 @@ static void UninstallSigHandler() sa.sa_handler = nullptr; int err = sigaction(SIGCHLD, &sa, nullptr); if (err < 0) { - HiLog::Error(LABEL, "Error uninstalling SIGCHLD handler: %d", errno); + 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: %d", errno); + HiLog::Error(LABEL, "Error uninstalling SIGHUP handler: %{public}d", errno); } } #ifdef __cplusplus @@ -139,7 +142,7 @@ 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 %d, %d", connectFd, errno); + HiLog::Error(LABEL, "Failed to listen connection %{public}d, %{public}d", connectFd, errno); return; } @@ -266,6 +269,31 @@ void AppSpawnServer::LoadAceLib() #endif } +static void InitDebugParams(const ClientSocket::AppProperty *appProperty) +{ + if (access("/system/lib/libhidebug.so", F_OK) != 0) { + HiLog::Error(LABEL, "access failed, errno = %{public}d", errno); + return; + } + void* handle = dlopen("/system/lib/libhidebug.so", 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; @@ -308,7 +336,7 @@ int AppSpawnServer::DoColdStartApp(ClientSocket::AppProperty *appProperty, int f extractedCmds.push_back(nullptr); APPSPAWN_LOGI("DoColdStartApp extractedCmds %d", extractedCmds.size()); int ret = execv(extractedCmds[0], extractedCmds.data()); - if (ret != 0) { + if (ret) { HiLog::Error(LABEL, "Failed to execv, errno = %{public}d", errno); NotifyResToParentProc(fd, -1); } @@ -350,7 +378,7 @@ int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, HiLog::Error(LABEL, "create pipe fail, errno = %{public}d", errno); return ERR_PIPE_FAIL; } - fcntl(fd[0], F_SETFL, O_NONBLOCK); + fcntl(fd[0], F_SETFL, O_NDELAY); InstallSigHandler(); pid = fork(); @@ -360,6 +388,7 @@ int AppSpawnServer::StartApp(char *longProcName, int64_t longProcNameLen, 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) { @@ -426,7 +455,7 @@ bool AppSpawnServer::ServerMain(char *longProcName, int64_t longProcNameLen) ClientSocket::AppProperty *appProperty = msg->GetMsg(); pid_t pid = 0; int ret = StartApp(longProcName, longProcNameLen, appProperty, connectFd, pid); - if (ret != 0) { + if (ret) { msg->Response(ret); } else { msg->Response(pid); @@ -642,12 +671,10 @@ int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appPr std::string oriel1DataPath = "/data/app/el1/" + currentUserId + "/base/"; std::string oriel2DataPath = "/data/app/el2/" + currentUserId + "/base/"; std::string oriDatabasePath = "/data/app/el2/" + currentUserId + "/database/"; - const std::string oriappdataPath = "/data/accounts/account_0/appdata/"; 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"; - std::string destappdataPath = rootPath + oriappdataPath; int rc = 0; @@ -662,7 +689,6 @@ int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appPr mountMap[destInstallPath] = oriInstallPath; mountMap[destel1DataPath] = oriel1DataPath; mountMap[destel2DataPath] = oriel2DataPath; - mountMap[destappdataPath] = oriappdataPath; std::map::iterator iter; for (iter = mountMap.begin(); iter != mountMap.end(); ++iter) { @@ -676,6 +702,7 @@ int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appPr 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]; @@ -690,15 +717,23 @@ int32_t AppSpawnServer::DoAppSandboxMountCustomized(const ClientSocket::AppPrope 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; + } - // 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()); + 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()); + // 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; @@ -719,6 +754,12 @@ int32_t AppSpawnServer::DoAppSandboxMountCustomized(const ClientSocket::AppPrope 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"; @@ -753,7 +794,6 @@ void AppSpawnServer::DoAppSandboxMkdir(std::string sandboxPackagePath, const Cli mkdirInfo.push_back("/data/accounts"); mkdirInfo.push_back("/data/accounts/account_0"); mkdirInfo.push_back("/data/accounts/account_0/applications/"); - mkdirInfo.push_back("/data/accounts/account_0/appdata/"); mkdirInfo.push_back("/data/bundles/"); for (int i = 0; i < mkdirInfo.size(); i++) { @@ -771,7 +811,7 @@ int32_t AppSpawnServer::DoSandboxRootFolderCreateAdapt(std::string sandboxPackag } // bind mount "/" to /mnt/sandbox/ path - // rootfs: to do more resouces bind mount here to get more strict resources constraints + // 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"); @@ -800,7 +840,7 @@ int32_t AppSpawnServer::DoSandboxRootFolderCreate(std::string sandboxPackagePath vecInfo.push_back("/dev"); vecInfo.push_back("/proc"); vecInfo.push_back("/sys"); - vecInfo.push_back("/sys-prod"); + vecInfo.push_back("/sys_prod"); vecInfo.push_back("/system"); for (int i = 0; i < vecInfo.size(); i++) { @@ -914,7 +954,7 @@ void AppSpawnServer::SetAppAccessToken(const ClientSocket::AppProperty *appPrope #ifdef WITH_SELINUX HapContext hapContext; ret = hapContext.HapDomainSetcontext(appProperty->apl, appProperty->processName); - if (ret != 0) { + if (ret) { HiLog::Error(LABEL, "AppSpawnServer::Failed to hap domain set context, errno = %{public}d %{public}s", errno, appProperty->apl); } else { diff --git a/src/include/appspawn_msg_peer.h b/src/include/appspawn_msg_peer.h index 0aa10c19..d81b124d 100644 --- a/src/include/appspawn_msg_peer.h +++ b/src/include/appspawn_msg_peer.h @@ -37,7 +37,7 @@ public: AppSpawnMsgPeer(const std::shared_ptr &socket, int connectFd); /** - * Destructor used to destory a AppSpawnMsgPeer + * Destructor used to destroy a AppSpawnMsgPeer */ ~AppSpawnMsgPeer(); diff --git a/src/include/appspawn_server.h b/src/include/appspawn_server.h index 5836b32d..cda398e7 100644 --- a/src/include/appspawn_server.h +++ b/src/include/appspawn_server.h @@ -39,7 +39,7 @@ public: explicit AppSpawnServer(const std::string &socketName); /** - * Destructor used to destory a AppSpawnServer + * Destructor used to destroy a AppSpawnServer */ ~AppSpawnServer() = default; @@ -93,7 +93,7 @@ private: void ConnectionPeer(); /** - * Sets a name for an applicaiton process. + * Sets a name for an application process. * * @param longProcName Indicates the length of long process name. * @param longProcNameLen Indicates the long process name. diff --git a/src/include/server_socket.h b/src/include/server_socket.h index 84c965cf..8bfe2ce4 100644 --- a/src/include/server_socket.h +++ b/src/include/server_socket.h @@ -34,7 +34,7 @@ public: explicit ServerSocket(const std::string &server); /** - * Destructor used to destory a ServerSocket + * Destructor used to destroy a ServerSocket */ virtual ~ServerSocket(); diff --git a/src/socket/appspawn_socket.cpp b/src/socket/appspawn_socket.cpp index 4c0caf6a..096fed00 100755 --- a/src/socket/appspawn_socket.cpp +++ b/src/socket/appspawn_socket.cpp @@ -66,7 +66,7 @@ int AppSpawnSocket::PackSocketAddr() } socklen_t pathSize = sizeof(socketAddr_.sun_path); if (pathLen >= pathSize) { - HiLog::Error(LABEL, "Invalid socket name: '%s' too long", socketName_.c_str()); + HiLog::Error(LABEL, "Invalid socket name: '%{public}s' too long", socketName_.c_str()); return -1; } @@ -92,18 +92,18 @@ int AppSpawnSocket::CreateSocket() { int socketFd = socket(AF_LOCAL, SOCK_SEQPACKET, 0); if (socketFd < 0) { - HiLog::Error(LABEL, "Failed to create socket: %d", errno); + HiLog::Error(LABEL, "Failed to create socket: %{public}d", errno); return (-errno); } - HiLog::Debug(LABEL, "Created socket with fd %d", socketFd); + HiLog::Debug(LABEL, "Created socket with fd %{public}d", socketFd); return socketFd; } void AppSpawnSocket::CloseSocket(int &socketFd) { if (socketFd >= 0) { - HiLog::Debug(LABEL, "Closed socket with fd %d", socketFd); + HiLog::Debug(LABEL, "Closed socket with fd %{public}d", socketFd); close(socketFd); socketFd = -1; } @@ -112,7 +112,7 @@ void AppSpawnSocket::CloseSocket(int &socketFd) int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len) { if (socketFd < 0 || len <= 0 || buf == nullptr) { - HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len); + HiLog::Error(LABEL, "Invalid args: socket %{public}d, len %{public}d, buf might be nullptr", socketFd, len); return -1; } @@ -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 %d error %zd: %d", socketFd, rLen, errno); + HiLog::Error(LABEL, "Read message from fd %{public}d error %zd: %{public}d", socketFd, rLen, errno); return -EFAULT; } @@ -133,7 +133,7 @@ int AppSpawnSocket::ReadSocketMessage(int socketFd, void *buf, int len) int AppSpawnSocket::WriteSocketMessage(int socketFd, const void *buf, int len) { if (socketFd < 0 || len <= 0 || buf == nullptr) { - HiLog::Error(LABEL, "Invalid args: socket %d, len %d, buf might be nullptr", socketFd, len); + HiLog::Error(LABEL, "Invalid args: socket %{public}d, len %{public}d, buf might be nullptr", socketFd, len); return -1; } @@ -142,9 +142,10 @@ int AppSpawnSocket::WriteSocketMessage(int socketFd, const void *buf, int len) const uint8_t *offset = reinterpret_cast(buf); for (ssize_t wLen = 0; remain > 0; offset += wLen, remain -= wLen, written += wLen) { wLen = write(socketFd, offset, remain); - HiLog::Debug(LABEL, "socket fd %d, wLen %zd", socketFd, wLen); + HiLog::Debug(LABEL, "socket fd %{public}d, wLen %zd", socketFd, wLen); if ((wLen <= 0) && (errno != EINTR)) { - HiLog::Error(LABEL, "Failed to write message to fd %d, error %zd: %d", socketFd, wLen, errno); + HiLog::Error(LABEL, "Failed to write message to fd %{public}d, error %zd: %{public}d", + socketFd, wLen, errno); return (-errno); } } diff --git a/src/socket/client_socket.cpp b/src/socket/client_socket.cpp index 699bbaf9..3c240bde 100644 --- a/src/socket/client_socket.cpp +++ b/src/socket/client_socket.cpp @@ -40,14 +40,14 @@ int ClientSocket::CreateClient() } } - HiLog::Debug(LABEL, "Client: CreateClient socket fd %d", socketFd_); + HiLog::Debug(LABEL, "Client: CreateClient socket fd %{public}d", socketFd_); return 0; } void ClientSocket::CloseClient() { if (socketFd_ < 0) { - HiLog::Error(LABEL, "Client: Invalid connectFd %d", socketFd_); + HiLog::Error(LABEL, "Client: Invalid connectFd %{public}d", socketFd_); return; } @@ -58,7 +58,7 @@ void ClientSocket::CloseClient() int ClientSocket::ConnectSocket(int connectFd) { if (connectFd < 0) { - HiLog::Error(LABEL, "Client: Invalid socket fd: %d", connectFd); + HiLog::Error(LABEL, "Client: Invalid socket fd: %{public}d", connectFd); return -1; } @@ -68,16 +68,17 @@ int ClientSocket::ConnectSocket(int connectFd) if ((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, "Client: Failed to set opt of socket %d, err %d", connectFd, errno); + HiLog::Warn(LABEL, "Client: Failed to set opt of socket %{public}d, err %{public}d", connectFd, errno); return -1; } if (connect(connectFd, reinterpret_cast(&socketAddr_), socketAddrLen_) < 0) { - HiLog::Warn(LABEL, "Client: Connect on socket fd %d, failed: %d", connectFd, errno); + HiLog::Warn(LABEL, "Client: Connect on socket fd %{public}d, failed: %{public}d", connectFd, errno); return -1; } - HiLog::Debug(LABEL, "Client: Connected on socket fd %d, name '%s'", connectFd, socketAddr_.sun_path); + HiLog::Debug(LABEL, "Client: Connected on socket fd %{public}d, name '%{public}s'", + connectFd, socketAddr_.sun_path); return 0; } diff --git a/src/socket/server_socket.cpp b/src/socket/server_socket.cpp index 7a0b1444..0917613c 100644 --- a/src/socket/server_socket.cpp +++ b/src/socket/server_socket.cpp @@ -51,7 +51,7 @@ int ServerSocket::VerifyConnection(int connectFd) void ServerSocket::CloseConnection(int connectFd) { if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid connectFd %d", connectFd); + HiLog::Error(LABEL, "Server: Invalid connectFd %{public}d", connectFd); return; } @@ -65,7 +65,7 @@ void ServerSocket::CloseConnection(int connectFd) close(connectFd); connectFds_.erase(it); - HiLog::Debug(LABEL, "Server: Erase connect fd %d from list", connectFd); + HiLog::Debug(LABEL, "Server: Erase connect fd %{public}d from list", connectFd); } void ServerSocket::SaveConnection(int connectFd) @@ -81,12 +81,12 @@ void ServerSocket::CloseServer() std::lock_guard lock(mutexConnect_); for (const int &fd : connectFds_) { - HiLog::Debug(LABEL, "Server: Closed connection fd %d", fd); + 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 %d", errno); + HiLog::Error(LABEL, "Server: Failed to unlink, err %{public}d", errno); } connectFds_.clear(); @@ -107,7 +107,7 @@ void ServerSocket::CloseServerMonitor() int ServerSocket::BindSocket(int connectFd) { if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid socket fd: %d", connectFd); + HiLog::Error(LABEL, "Server: Invalid socket fd: %{public}d", connectFd); return -EINVAL; } @@ -116,7 +116,7 @@ int ServerSocket::BindSocket(int connectFd) } if ((unlink(socketAddr_.sun_path) != 0) && (errno != ENOENT)) { - HiLog::Error(LABEL, "Server: Failed to unlink, err %d", errno); + HiLog::Error(LABEL, "Server: Failed to unlink, err %{public}d", errno); return (-errno); } @@ -124,25 +124,25 @@ int ServerSocket::BindSocket(int connectFd) 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 %d, err %d", connectFd, errno); + 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 %d, failed: %d", connectFd, errno); + 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 %d, failed: %d", connectFd, errno); + 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 %d, failed: %d", connectFd, errno); + 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 %d success", connectFd); + HiLog::Debug(LABEL, "Server: Bind socket fd %{public}d success", connectFd); return 0; } @@ -165,26 +165,26 @@ int ServerSocket::RegisterServerSocket(int &connectFd) #ifndef NWEB_SPAWN if ((BindSocket(connectFd) != 0) || (listen(connectFd, listenBacklog_) < 0)) { HiLog::Error(LABEL, - "Server: Register socket fd %d with backlog %d error: %d", + "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 %d", errno); + 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 %d", connectFd); + 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 %d", socketFd_); + HiLog::Info(LABEL, "Server: Already register server socket %{public}d", socketFd_); return 0; } @@ -194,7 +194,7 @@ int ServerSocket::RegisterServerSocket() int ServerSocket::WaitForConnection(int connectFd) { if (connectFd < 0) { - HiLog::Error(LABEL, "Server: Invalid args: connectFd %d", connectFd); + HiLog::Error(LABEL, "Server: Invalid args: connectFd %{public}d", connectFd); return -EINVAL; } @@ -212,12 +212,12 @@ int ServerSocket::WaitForConnection(int connectFd) 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 %d, err %d", connFd, errno); + 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 %d", connFd); + HiLog::Debug(LABEL, "Server: Connection accepted, connect fd %{public}d", connFd); return connFd; } diff --git a/standard/appspawn_process.c b/standard/appspawn_process.c new file mode 100755 index 00000000..2db0f258 --- /dev/null +++ b/standard/appspawn_process.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2021 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 "appspawn_server.h" +#include "securec.h" + +int setProcessName(struct AppSpawnContent_ *content, AppSpawnClient *client, + char *longProcName, int64_t longProcNameLen) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + size_t len = strlen(appProperty->property.processName) + 1; + if (longProcName == NULL || longProcNameLen <= 0 || len <= 1) { + 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->property.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->property.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->property.processName), appProperty->property.processName, len) != EOK) { + APPSPAWN_LOGE("strncpy_s long name error: %d longProcNameLen %d", errno, longProcNameLen); + return -EINVAL; + } + + return 0; +} + +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; +} + +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 ClearEnvironment(AppSpawnContent *content, AppSpawnClient *client) +{ + APPSPAWN_LOGI("ClearEnvironment id %d", client->id); + sigset_t mask; + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + sigaddset(&mask, SIGTERM); + sigprocmask(SIG_UNBLOCK, &mask, NULL); + + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + // close child fd + close(appProperty->fd[0]); + return; +} + +int setUidGid(struct AppSpawnContent_ *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + if (strlen(appProperty->property.gidTable) == 0) { + APPSPAWN_LOGE("gitTable is nullptr"); + return (-errno); + } + + // 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); + } + + return 0; +} + +void SetContentFunction(AppSpawnContent *content) +{ + APPSPAWN_LOGI("SetContentFunction"); + content->clearEnvironment = ClearEnvironment; + content->setProcessName = setProcessName; + content->setKeepCapabilities = setKeepCapabilities; + content->setUidGid = setUidGid; +} diff --git a/standard/appspawn_service.c b/standard/appspawn_service.c new file mode 100755 index 00000000..8d3dcc5b --- /dev/null +++ b/standard/appspawn_service.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2021 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_socket.h" +#include "parameter.h" +#include "securec.h" + +static AppSpawnContentExt *g_appSpawnContent = NULL; + +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 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); + memcpy_s(buffer, bufferSize, buff, buffSize); + return LE_Send(LE_GetDefaultLoop(), client->stream, handle, buffSize); +} + +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; + int count = 0; + while (count < RETRY_TIME) { // wait child process resutl + int readLen = read(fd, &result, sizeof(result)); + if (readLen == sizeof(result)) { + break; + } + usleep(DELAY_US); + count++; + } + if (count >= RETRY_TIME) { + APPSPAWN_LOGI("Time out for child %d %s ", appProperty->property.processName, pid); + result = 0; + } + APPSPAWN_LOGI("child process %s %s pid %d", + appProperty->property.processName, (result == 0) ? "success" : "fail", pid); + return result; +} + +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, "Failed to alloc client"); + 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, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Invalid gidCount %u", appProperty->property.gidCount); + APPSPAWN_CHECK(strlen(appProperty->property.processName) > 0, LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return, "Invalid processName %s", appProperty->property.processName); + APPSPAWN_LOGI("OnReceiveRequest client.id %d appProperty %d processname %s", + appProperty->client.id, appProperty->property.uid, appProperty->property.processName); + // special handle bundle name medialibrary and scanner + HandleSpecial(appProperty); + + // cold start app + if (appProperty->property.flags & 0x01) { + char cold[10] = {0}; // 10 cold + ret = GetParameter("appspawn.cold.boot", "false", cold, sizeof(cold)); + 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) { + APPSPAWN_LOGE("create pipe fail, errno = %d", errno); + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); + return; + } + fcntl(appProperty->fd[0], F_SETFL, O_NONBLOCK); + + int pid = 0; + int result = AppSpawnProcessMsg(g_appSpawnContent, &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]); + // send response + if (result == 0) { + SendResponse(appProperty, (char *)&pid, sizeof(pid)); + } else { + SendResponse(appProperty, (char *)&result, sizeof(result)); + } + // release + LE_CloseTask(LE_GetDefaultLoop(), taskHandle); +} + +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 = NULL; + 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; + APPSPAWN_LOGI("OnConnection client fd %d Id %d", LE_GetSocketFd(stream), client->client.id); + return 0; +} + +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", pid); + } + break; + } + case SIGTERM: { // appswapn killed, use kill without parameter + LE_StopLoop(LE_GetDefaultLoop()); + break; + } + default: + APPSPAWN_LOGI("SigHandler, unsupported signal %d.", siginfo->ssi_signo); + break; + } +} + +static int NotifyResToParent(struct AppSpawnContent_ *content, AppSpawnClient *client, int result) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + APPSPAWN_LOGI("NotifyResToParent %s result %d", appProperty->property.processName, result); + write(appProperty->fd[1], &result, sizeof(result)); + // close write + close(appProperty->fd[1]); + return 0; +} + +static void AppSpawnInit(AppSpawnContent *content) +{ + AppSpawnContentExt *appSpawnContent = (AppSpawnContentExt *)content; + APPSPAWN_CHECK(appSpawnContent != NULL, return, "Failed to alloc memory for appspawn"); + + LE_STATUS ret = LE_CreateSignalTask(LE_GetDefaultLoop(), &appSpawnContent->sigHandler, SignalHandler); + if (ret == 0) { + ret = LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGCHLD); + ret = LE_AddSignal(LE_GetDefaultLoop(), appSpawnContent->sigHandler, SIGTERM); + } + + APPSPAWN_LOGI("AppSpawnInit"); + if (content->loadExtendLib) { + content->loadExtendLib(content); + } + content->notifyResToParent = NotifyResToParent; + // set private function + SetContentFunction(content); +} + +static void AppSpawnRun(AppSpawnContent *content) +{ + APPSPAWN_LOGI("AppSpawnRun"); + LE_RunLoop(LE_GetDefaultLoop()); + + APPSPAWN_LOGI("AppSpawnRun exit "); + // release resource + free(content); + g_appSpawnContent = NULL; +} + +AppSpawnContent *AppSpawnCreateContent(const char *socketName, char *longProcName, int64_t longProcNameLen) +{ + APPSPAWN_CHECK(LE_GetDefaultLoop() != NULL, return NULL, "Invalid default loop"); + APPSPAWN_CHECK(socketName != NULL && longProcName != NULL, return NULL, "Invalid name"); + APPSPAWN_LOGI("AppSpawnCreateContent %s", socketName); + + 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; + int ret = strcpy_s(appSpawnContent->content.socketName, sizeof(appSpawnContent->content.socketName), socketName); + APPSPAWN_CHECK(ret >= 0, free(appSpawnContent); return NULL, "Failed to strcpy_s %d", ret); + + char path[128] = {0}; // 128 max path + 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); + + 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->servcer, &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); + appSpawnContent->content.runAppSpawn = AppSpawnRun; + appSpawnContent->content.initAppSpawn = AppSpawnInit; + APPSPAWN_LOGI("AppSpawnCreateContent path %s fd %d", path, LE_GetSocketFd(appSpawnContent->servcer)); + g_appSpawnContent = appSpawnContent; + return &g_appSpawnContent->content; +} diff --git a/standard/appspawn_service.h b/standard/appspawn_service.h new file mode 100755 index 00000000..56794337 --- /dev/null +++ b/standard/appspawn_service.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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 RETRY_TIME 10 +#define DELAY_US 10 * 1000 // 10ms + +typedef struct { + AppSpawnClient client; + TaskHandle stream; + int32_t fd[2]; // 2 fd count + AppParameter property; +} AppSpawnClientExt; + +typedef struct { + HashNode hashNode; + uint32_t pid; + char *appName; +} AppInfo; + +typedef struct { + AppSpawnContent content; + TaskHandle servcer; + SignalHandle sigHandler; + HashMapHandle appMap; // save app pid and name +} AppSpawnContentExt; + +void SetContentFunction(AppSpawnContent *content); + +#ifdef __cplusplus +} +#endif +#endif // APPSPAWN_SERVICE_H diff --git a/standard/main.c b/standard/main.c new file mode 100755 index 00000000..2aaf0920 --- /dev/null +++ b/standard/main.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021 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 "appspawn_msg.h" +#include "appspawn_adapter.h" + +extern void * g_nwebHandle; + +#ifdef NWEB_SPAWN +void LoadExtendLib(AppSpawnContent *content) +{ + LoadAceLib(); +} + +void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) +{ + AppSpawnClientExt *appProperty = (AppSpawnClientExt *)client; + typedef void (*FuncType) (const char *cmd); + FuncType funcNWebRenderMain = (FuncType)(dlsym(g_nwebHandle, "NWebRenderMain")); + if (funcNWebRenderMain == NULL) { + APPSPAWN_LOGI("webviewspawn dlsym ERROR=%s", dlerror()); + return; + } + funcNWebRenderMain(appProperty->property.renderCmd); +} + +#else +void LoadExtendLib(AppSpawnContent *content) +{ + const char* acelibdir = "/system/lib/libace.z.so"; + void *AceAbilityLib = NULL; + APPSPAWN_LOGI("MainThread::LoadAbilityLibrary. Start calling dlopen acelibdir."); + AceAbilityLib = dlopen(acelibdir, RTLD_NOW | RTLD_GLOBAL); + if (AceAbilityLib == NULL) { + APPSPAWN_LOGE("Fail to dlopen %s, [%s]", acelibdir, dlerror()); + } else { + APPSPAWN_LOGI("Success to dlopen %s", acelibdir); + } + APPSPAWN_LOGI("MainThread::LoadAbilityLibrary. End calling dlopen."); +} + +void RunChildProcessor(AppSpawnContent *content, AppSpawnClient *client) +{ + StartMainThread(); +} +#endif + +int main(int argc, char *const argv[]) +{ + SetInitLogLevel(1); + if (argc > 0) { + // calculate child process long name size + uintptr_t start = (uintptr_t)argv[0]; + uintptr_t end = (uintptr_t)strchr(argv[argc - 1], 0); + int64_t argvSize = end - start; + AppSpawnContent *content = AppSpawnCreateContent(APPSPAWN_SOCKET_NAME, argv[0], argvSize); + APPSPAWN_CHECK(content != NULL, return -1, "Invalid content for appspawn"); + APPSPAWN_CHECK(content->runAppSpawn != NULL, return -1, "Invalid content for appspawn"); + APPSPAWN_CHECK(content->initAppSpawn != NULL, return -1, "Invalid content for appspawn"); + + // set common operation + content->loadExtendLib = LoadExtendLib; + content->runChildProcessor = RunChildProcessor; + + content->initAppSpawn(content); + // run, to start loop and wait message + content->runAppSpawn(content); + } + return 0; +} diff --git a/test/clienttest/appspawn_sample.cpp b/test/clienttest/appspawn_sample.cpp new file mode 100755 index 00000000..e69de29b diff --git a/test/clienttest/appspawn_sample.h b/test/clienttest/appspawn_sample.h new file mode 100755 index 00000000..e69de29b diff --git a/test/clienttest/main.cpp b/test/clienttest/main.cpp new file mode 100755 index 00000000..e69de29b diff --git a/tools/appspawn_start_app.cpp b/tools/appspawn_start_app.cpp index 3f91515f..072e69f9 100644 --- a/tools/appspawn_start_app.cpp +++ b/tools/appspawn_start_app.cpp @@ -1,75 +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 +/* + * 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; +} -- Gitee