diff --git a/src/appspawn_server.cpp b/src/appspawn_server.cpp index 2acb6818de5f3490b45fa2d15eeef9673baaed39..4807ae3e507ed6fec16656b5274db6314ccba6bb 100644 --- a/src/appspawn_server.cpp +++ b/src/appspawn_server.cpp @@ -19,9 +19,13 @@ #include #include #include +#include #include #include +#include #include +#include +#include #include "errors.h" #include "hilog/log.h" @@ -30,8 +34,11 @@ #include #include +#include +#include #define GRAPHIC_PERMISSION_CHECK +constexpr static mode_t FILE_MODE = 0711; namespace OHOS { namespace AppSpawn { @@ -95,14 +102,14 @@ static void InstallSigHandler() static void UninstallSigHandler() { struct sigaction sa = {}; - sa.sa_handler = SIG_DFL; + sa.sa_handler = nullptr; int err = sigaction(SIGCHLD, &sa, nullptr); if (err < 0) { HiLog::Error(LABEL, "Error uninstalling SIGCHLD handler: %d", errno); } struct sigaction sah = {}; - sah.sa_handler = SIG_DFL; + sah.sa_handler = nullptr; err = sigaction(SIGHUP, &sah, nullptr); if (err < 0) { HiLog::Error(LABEL, "Error uninstalling SIGHUP handler: %d", errno); @@ -386,6 +393,151 @@ void AppSpawnServer::SetServerSocket(const std::shared_ptr &server 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, NULL); + if (rc) { + return rc; + } + + rc = mount(NULL, destinationPath.c_str(), NULL, MS_PRIVATE, NULL); + if (rc) { + return rc; + } + + return 0; +} + +int32_t AppSpawnServer::DoAppSandboxMount(const ClientSocket::AppProperty *appProperty, std::string rootPath) +{ + std::string oriInstallPath = "/data/app/el1/bundle/"; + std::string oriDataPath = "/data/app/el2/0/base/"; + std::string oriDatabasePath = "/data/app/el2/0/database/"; + std::string destAPI7InstallPath = rootPath + "/data/accounts/account_0/applications"; + std::string destDatabasePath = rootPath + "/data/storage/el2/database"; + std::string destInstallPath = rootPath + "/data/storage/el1/0/bundle"; + std::string destDataPath = rootPath + "/data/storage/el2/base"; + int rc = 0; + + oriInstallPath += appProperty->processName; + oriDataPath += appProperty->processName; + oriDatabasePath += appProperty->processName; + + std::map mountMap; + mountMap[oriInstallPath] = destAPI7InstallPath; + mountMap[oriDatabasePath] = destDatabasePath; + mountMap[oriInstallPath] = destInstallPath; + mountMap[oriDataPath] = destDataPath; + + std::map::iterator iter; + for (iter = mountMap.begin(); iter != mountMap.end(); iter++) { + rc = DoAppSandboxMountOnce(iter->first.c_str(), iter->second.c_str()); + if (rc) { + return rc; + } + } + + return 0; +} + +void AppSpawnServer::DoAppSandboxMkdir(std::string sandboxPackagePath, const ClientSocket::AppProperty *appProperty) +{ + // to create /mnt/sandbox//data/storage/el1 related path, later should delete this code. + std::string dirPath = sandboxPackagePath + "/data/"; + + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el1"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el1/0"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el1/0/bundle"; + mkdir(dirPath.c_str(), FILE_MODE); + + // to create /mnt/sandbox//data/storage/el1 related path, later should delete this code. + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el2"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el2/base"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/storage/el2/database"; + mkdir(dirPath.c_str(), FILE_MODE); + + // create applications folder for compatibility purpose + dirPath = sandboxPackagePath + "/data/accounts"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/accounts/account_0"; + mkdir(dirPath.c_str(), FILE_MODE); + dirPath = sandboxPackagePath + "/data/accounts/account_0/applications"; + mkdir(dirPath.c_str(), FILE_MODE); +} + +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->processName; + 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; + } + + rc = mount(NULL, "/", NULL, MS_REC | MS_SLAVE, NULL); + if (rc) { + HiLog::Error(LABEL, "set propagation slave failed, packagename is %{public}s", appProperty->processName); + return rc; + } + + // bind mount "/" to /mnt/sandbox/ path + // rootfs: to do more resouces 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, packagename is %{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 = 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; +} + bool AppSpawnServer::SetAppProcProperty(int connectFd, const ClientSocket::AppProperty *appProperty, char *longProcName, int64_t longProcNameLen, const int32_t fd[FDLEN2]) { @@ -393,6 +545,7 @@ bool AppSpawnServer::SetAppProcProperty(int connectFd, const ClientSocket::AppPr HiLog::Error(LABEL, "appProperty is nullptr"); return false; } + pid_t newPid = getpid(); HiLog::Debug(LABEL, "AppSpawnServer::Success to fork new process, pid = %{public}d", newPid); // close socket connection and peer socket in child process @@ -402,6 +555,13 @@ bool AppSpawnServer::SetAppProcProperty(int connectFd, const ClientSocket::AppPr UninstallSigHandler(); int32_t ret = ERR_OK; + + ret = SetAppSandboxProperty(appProperty); + if (FAILED(ret)) { + NotifyResToParentProc(fd[1], ret); + return false; + } + ret = SetKeepCapabilities(appProperty->uid); if (FAILED(ret)) { NotifyResToParentProc(fd[1], ret); diff --git a/src/include/appspawn_server.h b/src/include/appspawn_server.h index 8ec6190925d897d93f5b51a65a0151b358933617..bb61bb830b2e29f8bddee8f21770f8da50c81637 100644 --- a/src/include/appspawn_server.h +++ b/src/include/appspawn_server.h @@ -122,6 +122,26 @@ private: */ int32_t SetCapabilities(); + /** + * 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 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. */