From 0db43d37a34d6a41e4b485204dc73662c422667c Mon Sep 17 00:00:00 2001 From: Junghyun Yeon Date: Mon, 4 Jul 2016 21:34:34 +0900 Subject: [PATCH] tpk/wgt backend will run as system session Related changes [slp-pkgmgr] https://review.tizen.org/gerrit/80764 [pkgmgr-server] https://review.tizen.org/gerrit/#/c/78205/ [app-installers] https://review.tizen.org/gerrit/#/c/78206/ [wgt-backend] https://review.tizen.org/gerrit/#/c/81099/ Change-Id: I0bd615388f539da3dc25594deb9b9eab999603a9 Signed-off-by: Junghyun Yeon --- src/common/CMakeLists.txt | 1 + src/common/pkgmgr_interface.cc | 4 + src/common/pkgmgr_interface.h | 7 ++ src/common/pkgmgr_query.cc | 4 +- src/common/pkgmgr_query.h | 3 +- src/common/pkgmgr_signal.cc | 2 +- src/common/request.cc | 19 +-- src/common/request.h | 4 +- src/common/step/configuration/step_configure.cc | 9 +- src/common/step/configuration/step_configure.h | 2 +- src/common/step/filesystem/step_change_owner.cc | 159 ++++++++++++++++++++++++ src/common/step/filesystem/step_change_owner.h | 36 ++++++ src/common/step/filesystem/step_delta_patch.cc | 10 +- src/common/step/pkgmgr/step_kill_apps.cc | 5 +- 14 files changed, 239 insertions(+), 26 deletions(-) create mode 100644 src/common/step/filesystem/step_change_owner.cc create mode 100644 src/common/step/filesystem/step_change_owner.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 15288ab..ceb14e7 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -37,6 +37,7 @@ SET(SRCS step/configuration/step_parse_manifest.cc step/configuration/step_parse_preload.cc step/filesystem/step_acquire_external_storage.cc + step/filesystem/step_change_owner.cc step/filesystem/step_clear_data.cc step/filesystem/step_copy.cc step/filesystem/step_copy_storage_directories.cc diff --git a/src/common/pkgmgr_interface.cc b/src/common/pkgmgr_interface.cc index 879c959..d919f1d 100644 --- a/src/common/pkgmgr_interface.cc +++ b/src/common/pkgmgr_interface.cc @@ -145,6 +145,10 @@ RequestType PkgMgrInterface::GetRequestType() const { } } +uid_t PkgMgrInterface::GetUid() const { + return pkgmgr_installer_get_uid(pi_); +} + const char* PkgMgrInterface::GetRequestInfo() const { return pkgmgr_installer_get_request_info(pi_); } diff --git a/src/common/pkgmgr_interface.h b/src/common/pkgmgr_interface.h index e2dee7d..b174d42 100644 --- a/src/common/pkgmgr_interface.h +++ b/src/common/pkgmgr_interface.h @@ -68,6 +68,13 @@ class PkgMgrInterface { RequestType GetRequestType() const; /** + * Returns uid passed from pkgmgr_installer + * + * \return uid retrieved from pkgmgr_installer + */ + uid_t GetUid() const; + + /** * Returns Request info passed from pkgmgr_installer * * \return request info retrieved from pkgmgr_installer diff --git a/src/common/pkgmgr_query.cc b/src/common/pkgmgr_query.cc index 27f2df5..6ccef74 100644 --- a/src/common/pkgmgr_query.cc +++ b/src/common/pkgmgr_query.cc @@ -157,9 +157,9 @@ std::string QueryStorageForPkgId(const std::string& pkg_id, uid_t uid) { } bool QueryIsPackageInstalled(const std::string& pkg_id, - RequestMode request_mode) { + RequestMode request_mode, uid_t uid) { pkgmgrinfo_pkginfo_h handle; - int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), getuid(), + int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkg_id.c_str(), uid, &handle); if (ret != PMINFO_R_OK) { if (ret != PMINFO_R_ENOENT) diff --git a/src/common/pkgmgr_query.h b/src/common/pkgmgr_query.h index 0b1212a..16a705f 100644 --- a/src/common/pkgmgr_query.h +++ b/src/common/pkgmgr_query.h @@ -89,11 +89,12 @@ std::string QueryStorageForPkgId(const std::string& pkg_id, uid_t uid); * * \param pkg_id package id * \param request_mode request mode + * \param uid user id * * \return true if package is installed */ bool QueryIsPackageInstalled(const std::string& pkg_id, - RequestMode request_mode); + RequestMode request_mode, uid_t uid); /** * \brief Adapter interface for external PkgMgr module used for checking diff --git a/src/common/pkgmgr_signal.cc b/src/common/pkgmgr_signal.cc index 9c38de2..d9648f1 100644 --- a/src/common/pkgmgr_signal.cc +++ b/src/common/pkgmgr_signal.cc @@ -157,7 +157,7 @@ const char* PkgmgrSignal::GetResultKey(Step::Status result) const { bool PkgmgrSignal::SendAppids(const std::string& type, const std::string& pkgid) const { std::vector appids; - if (!QueryAppidsForPkgId(pkgid, &appids, getuid())) + if (!QueryAppidsForPkgId(pkgid, &appids, pkgmgr_installer_get_uid(pi_))) return true; for (auto& appid : appids) { if (pkgmgr_installer_send_app_uninstall_signal(pi_, type.c_str(), diff --git a/src/common/request.cc b/src/common/request.cc index ca9e796..ed4b3c7 100644 --- a/src/common/request.cc +++ b/src/common/request.cc @@ -10,17 +10,22 @@ namespace bf = boost::filesystem; namespace common_installer { -RequestMode GetRequestMode() { - return (getuid() == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) || +RequestMode GetRequestMode(uid_t uid) { + return (uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) || getuid() == 0) ? RequestMode::GLOBAL : RequestMode::USER; } // Now, preload app is always installed RO location. -const char *GetRootAppPath(bool is_preload) { - return GetRequestMode() == RequestMode::USER ? - tzplatform_getenv(TZ_USER_APP) : is_preload ? - tzplatform_getenv(TZ_SYS_RO_APP) : tzplatform_getenv(TZ_SYS_RW_APP); +const char* GetRootAppPath(bool is_preload, uid_t uid) { + if (GetRequestMode(uid) == RequestMode::GLOBAL) { + return is_preload ? + tzplatform_getenv(TZ_SYS_RO_APP) : tzplatform_getenv(TZ_SYS_RW_APP); + } else { + tzplatform_set_user(uid); + const char* rootpath = tzplatform_getenv(TZ_USER_APP); + tzplatform_reset_user(); + return rootpath; + } } - } // namespace common_installer diff --git a/src/common/request.h b/src/common/request.h index 9b29019..c320e9b 100644 --- a/src/common/request.h +++ b/src/common/request.h @@ -41,14 +41,14 @@ enum class RequestMode : int { * * \return request mode */ -RequestMode GetRequestMode(); +RequestMode GetRequestMode(uid_t uid); /** * Get apps root path for current request (GLOBAL/USER) * * \return root application path (eg. $HOME/apps_rw/) */ -const char *GetRootAppPath(bool is_preload); +const char* GetRootAppPath(bool is_preload, uid_t uid); } // namespace common_installer diff --git a/src/common/step/configuration/step_configure.cc b/src/common/step/configuration/step_configure.cc index 25694cc..60c97f5 100644 --- a/src/common/step/configuration/step_configure.cc +++ b/src/common/step/configuration/step_configure.cc @@ -30,7 +30,7 @@ StepConfigure::StepConfigure(InstallerContext* context, PkgMgrPtr pkgmgr) } Step::Status StepConfigure::process() { - SetupRequestMode(); + SetupRequestMode(pkgmgr_->GetUid()); SetupRequestType(); SetupFileCreationMask(); @@ -154,6 +154,7 @@ Step::Status StepConfigure::precheck() { return Status::OPERATION_NOT_ALLOWED; } } else { + context_->uid.set(pkgmgr_->GetUid()); if (pkgmgr_->GetRequestType() == RequestType::ManifestDirectInstall || pkgmgr_->GetRequestType() == RequestType::ManifestDirectUpdate) { if (context_->is_preload_request.get()) { @@ -179,7 +180,7 @@ Step::Status StepConfigure::clean() { bool StepConfigure::SetupRootAppDirectory() { if (context_->root_application_path.get().empty()) { std::string root_app_path = - GetRootAppPath(context_->is_preload_request.get()); + GetRootAppPath(context_->is_preload_request.get(), context_->uid.get()); if (root_app_path.empty()) return false; @@ -199,8 +200,8 @@ bool StepConfigure::SetupRootAppDirectory() { return true; } -void StepConfigure::SetupRequestMode() { - context_->request_mode.set(GetRequestMode()); +void StepConfigure::SetupRequestMode(uid_t uid) { + context_->request_mode.set(GetRequestMode(uid)); } void StepConfigure::SetupRequestType() { diff --git a/src/common/step/configuration/step_configure.h b/src/common/step/configuration/step_configure.h index 2041344..95e52db 100644 --- a/src/common/step/configuration/step_configure.h +++ b/src/common/step/configuration/step_configure.h @@ -56,7 +56,7 @@ class StepConfigure : public Step { private: bool SetupRootAppDirectory(); - void SetupRequestMode(); + void SetupRequestMode(uid_t uid); void SetupRequestType(); void SetupFileCreationMask(); void SetupIsPreloadRequest(); diff --git a/src/common/step/filesystem/step_change_owner.cc b/src/common/step/filesystem/step_change_owner.cc new file mode 100644 index 0000000..c1e1348 --- /dev/null +++ b/src/common/step/filesystem/step_change_owner.cc @@ -0,0 +1,159 @@ +/* 2016, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */ +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#include "common/step/filesystem/step_change_owner.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "common/shared_dirs.h" +#include "common/utils/file_util.h" +#include "common/utils/glist_range.h" + +namespace bf = boost::filesystem; +namespace bs = boost::system; + +namespace { + +const int32_t kPWBufSize = sysconf(_SC_GETPW_R_SIZE_MAX); +const int32_t kGRBufSize = sysconf(_SC_GETGR_R_SIZE_MAX); + +bool SetOwner(const bf::path& subpath, uid_t uid, gid_t gid) { + int fd = open(subpath.c_str(), O_RDONLY); + if (fd < 0) { + LOG(ERROR) << "Can't open directory : " << subpath; + return false; + } + + int ret = fchown(fd, uid, gid); + close(fd); + if (ret != 0) { + LOG(ERROR) << "Failed to change owner of: " << subpath; + return false; + } + return true; +} + +bf::path FindIconPath(const bf::path& base_path, const std::string& pkgid, + const bf::path& icon_filename, + const bf::path& root_path) { + std::vector paths; + bf::path system_path = base_path / icon_filename; + bf::path small_system_path = base_path / "default" / "small" / icon_filename; + bf::path res_path = root_path / pkgid / "res" / "icons" / icon_filename; + + paths.push_back(system_path); + paths.push_back(small_system_path); + paths.push_back(res_path); + + for (auto& path : paths) { + if (bf::exists(path)) + return path; + } + + return {}; +} + +} // namespace + +namespace common_installer { +namespace filesystem { + +Step::Status StepChangeOwner::precheck() { + if (context_->root_application_path.get().empty()) { + LOG(ERROR) << "root_application_path attribute is empty"; + return Step::Status::INVALID_VALUE; + } + + if (!boost::filesystem::exists(context_->root_application_path.get())) { + LOG(ERROR) << "root_application_path (" + << context_->root_application_path.get() + << ") path does not exist"; + return Step::Status::INVALID_VALUE; + } + + if (context_->pkgid.get().empty()) { + LOG(ERROR) << "pkgid attribute is empty"; + return Step::Status::PACKAGE_NOT_FOUND; + } + + return Step::Status::OK; +} + +Step::Status StepChangeOwner::process() { + struct passwd pwd; + struct passwd* pwd_result; + char buf_pw[kPWBufSize]; + + int ret = getpwuid_r(context_->uid.get(), &pwd, buf_pw, + sizeof(buf_pw), &pwd_result); + if (ret != 0 || pwd_result == nullptr) { + LOG(WARNING) << "Failed to get user for home directory: " << + context_->uid.get(); + return Status::ERROR; + } + + struct group gr; + struct group* gr_result; + char buf_gr[kGRBufSize]; + ret = getgrgid_r(pwd.pw_gid, &gr, buf_gr, sizeof(buf_gr), &gr_result); + if (ret != 0) + return Status::ERROR; + + // Change owner of files at root path + bf::path start_path = context_->pkg_path.get(); + if (!SetOwner(start_path, pwd.pw_uid, pwd.pw_gid)) + return Status::ERROR; + for (bf::recursive_directory_iterator iter(start_path); + iter != bf::recursive_directory_iterator(); ++iter) { + if (bf::is_symlink(symlink_status(iter->path()))) + continue; + if (!SetOwner(iter->path(), pwd.pw_uid, pwd.pw_gid)) + return Status::ERROR; + } + + // For icon files + const char *iconpath = getIconPath(context_->uid.get(), + context_->is_preload_request.get()); + if (!iconpath) { + for (application_x* app : + GListRange( + context_->manifest_data.get()->application)) { + if (!app->icon) + continue; + + icon_x* icon = reinterpret_cast(app->icon->data); + bf::path icon_path = icon->text; + //bf::path base_path = iconpath; + bf::path found_icon_path = FindIconPath(iconpath, + context_->pkgid.get(), icon_path.filename(), + context_->root_application_path.get()); + if (!found_icon_path.empty()) { + if (!SetOwner(found_icon_path, pwd.pw_uid, pwd.pw_gid)) + return Status::ERROR; + } + } + } + + // Manifest files for global apps + if (!context_->xml_path.get().empty()) { + if (!SetOwner(context_->xml_path.get(), pwd.pw_uid, pwd.pw_gid)) + return Status::ERROR; + } + + return Status::OK; +} + +} // namespace filesystem +} // namespace common_installer diff --git a/src/common/step/filesystem/step_change_owner.h b/src/common/step/filesystem/step_change_owner.h new file mode 100644 index 0000000..8e158f5 --- /dev/null +++ b/src/common/step/filesystem/step_change_owner.h @@ -0,0 +1,36 @@ +/* 2016, Copyright © Intel Coporation, license APACHE-2.0, see LICENSE file */ +// Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved +// Use of this source code is governed by a apache 2.0 license that can be +// found in the LICENSE file. + +#ifndef COMMON_STEP_FILESYSTEM_STEP_CHANGE_OWNER_H_ +#define COMMON_STEP_FILESYSTEM_STEP_CHANGE_OWNER_H_ + +#include + +#include "common/installer_context.h" + +#include "common/step/step.h" + +namespace common_installer { +namespace filesystem { + +/** + * \brief step responsible for changing ownership from system uid to actual user. + * Used by WGT and TPK + */ +class StepChangeOwner : public Step { + public: + using Step::Step; + + Status process() override; + Status clean() override { return Status::OK; } + Status undo() override { return Status::OK; } + Status precheck() override; + STEP_NAME(ChangeOwner) +}; + +} // namespace filesystem +} // namespace common_installer + +#endif // COMMON_STEP_FILESYSTEM_STEP_CHANGE_OWNER_H_ diff --git a/src/common/step/filesystem/step_delta_patch.cc b/src/common/step/filesystem/step_delta_patch.cc index bd28b7f..74cd25c 100644 --- a/src/common/step/filesystem/step_delta_patch.cc +++ b/src/common/step/filesystem/step_delta_patch.cc @@ -100,10 +100,10 @@ bool ApplyDeletedFiles(const delta::DeltaInfo& info, const bf::path& app_dir) { } bool ApplyModifiedFiles(const delta::DeltaInfo& info, const bf::path& app_dir, - const bf::path& patch_dir, bool is_preload) { + const bf::path& patch_dir, bool is_preload, uid_t uid) { for (auto& relative : info.modified()) { bf::path temp_file = ci::GenerateTemporaryPath( - bf::path(ci::GetRootAppPath(is_preload)) / "tmp_file"); + bf::path(ci::GetRootAppPath(is_preload, uid)) / "tmp_file"); bf::path patch_file = patch_dir / relative; bf::path input = app_dir / relative; if (!bf::is_regular_file(input)) { @@ -183,10 +183,10 @@ bool ApplyAddedFiles(const delta::DeltaInfo& info, const bf::path& app_dir, } bool ApplyPatch(const delta::DeltaInfo& info, const bf::path& app_dir, - const bf::path& patch_dir, bool is_preload) { + const bf::path& patch_dir, bool is_preload, uid_t uid) { if (!ApplyDeletedFiles(info, app_dir)) return false; - if (!ApplyModifiedFiles(info, app_dir, patch_dir, is_preload)) + if (!ApplyModifiedFiles(info, app_dir, patch_dir, is_preload, uid)) return false; if (!ApplyAddedFiles(info, app_dir, patch_dir)) return false; @@ -302,7 +302,7 @@ Step::Status StepDeltaPatch::process() { // apply changes mentioned in delta if (!ApplyPatch(*delta_info, context_->unpacked_dir_path.get(), patch_dir_, - context_->is_preload_request.get())) + context_->is_preload_request.get(), context_->uid.get())) return Status::DELTA_ERROR; bs::error_code error; diff --git a/src/common/step/pkgmgr/step_kill_apps.cc b/src/common/step/pkgmgr/step_kill_apps.cc index 7a68b55..24e29a5 100644 --- a/src/common/step/pkgmgr/step_kill_apps.cc +++ b/src/common/step/pkgmgr/step_kill_apps.cc @@ -35,12 +35,11 @@ bool CheckAndKill(const std::string& appid, uid_t uid) { return true; } -bool KillApp(const std::string& appid) { +bool KillApp(const std::string& appid, const uid_t uid) { uid_t* uids = nullptr; int ret = -1; int i; - uid_t uid = getuid(); if (uid == 0 || uid == tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)) { ret = sd_get_uids(&uids); if (ret < 0 || (ret == 0 || uids == nullptr)) { @@ -73,7 +72,7 @@ Step::Status StepKillApps::process() { context_->old_manifest_data.get() : context_->manifest_data.get(); for (application_x* app : GListRange(old_manifest->application)) { - (void) KillApp(app->appid); + (void) KillApp(app->appid, context_->uid.get()); } return Status::OK; } -- 2.7.4