From 10e66198daa889dccc458b501d3ee35d39e4cd8e Mon Sep 17 00:00:00 2001 From: jongmyeongko Date: Fri, 14 Jul 2017 21:06:58 +0900 Subject: [PATCH] Fix the access issue to shared/res of web app Other applications can't access the contents of ${pkg_path}/res/wgt/shared/res because of SMACK denial. So, the all contents of ${pkg_path}/res/wgt/shared/res should be in shared/res to avoid SMACK error. Also, we should consider delta update issue. The issue is the signature validation check failure because of unsigned file. In ${pkg_path}/shared/res, there can be generated files such as apps icon. and there can be other application's data of shared/res in case of Hybrid package. These files are unsigend one. To fix the issue, unlink and move back all original contents for ${pkg_path}/res/wgt/shared/res before delta update. Submit with : https://review.tizen.org/gerrit/#/c/139133/ Change-Id: I83718f109fbe4614c41977f4d680e65f007dad86 Signed-off-by: jongmyeongko (cherry picked from commit 1e4547168e14eb59fc18c6f586d9a67126587b04) --- src/unit_tests/smoke_test.cc | 18 ++- .../step_wgt_patch_storage_directories.cc | 48 +++----- .../step_wgt_undo_patch_storage_directories.cc | 132 ++++++++++++++------- .../step_wgt_undo_patch_storage_directories.h | 5 +- 4 files changed, 117 insertions(+), 86 deletions(-) diff --git a/src/unit_tests/smoke_test.cc b/src/unit_tests/smoke_test.cc index c3dad25..1fc7165 100644 --- a/src/unit_tests/smoke_test.cc +++ b/src/unit_tests/smoke_test.cc @@ -651,8 +651,8 @@ TEST_F(SmokeTest, SharedRes30) { ASSERT_EQ(Install(path, PackageType::WGT), ci::AppInstaller::Result::OK); ASSERT_TRUE(ValidatePackage(pkgid, {appid})); bf::path root_path = ci::GetRootAppPath(false, kTestUserId); - ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT + ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT + ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT } TEST_F(SmokeTest, SharedRes30Delta) { @@ -665,8 +665,8 @@ TEST_F(SmokeTest, SharedRes30Delta) { ASSERT_TRUE(ValidatePackage(pkgid, {appid})); // Check delta modifications bf::path root_path = ci::GetRootAppPath(false, kTestUserId); - ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT + ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT + ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1")); // NOLINT ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1")); // NOLINT } @@ -679,10 +679,9 @@ TEST_F(SmokeTest, SharedRes30Hybrid) { ASSERT_EQ(Install(path, PackageType::HYBRID), ci::AppInstaller::Result::OK); ASSERT_TRUE(ValidatePackage(pkgid, {appid1, appid2})); bf::path root_path = ci::GetRootAppPath(false, kTestUserId); - ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT + ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT")); // NOLINT + ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT")); // NOLINT ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK")); // NOLINT } TEST_F(SmokeTest, SharedRes30HybridDelta) { @@ -697,10 +696,9 @@ TEST_F(SmokeTest, SharedRes30HybridDelta) { ASSERT_TRUE(ValidatePackage(pkgid, {appid1, appid2})); // Check delta modifications bf::path root_path = ci::GetRootAppPath(false, kTestUserId); - ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT + ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-2")); // NOLINT + ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-WGT-2")); // NOLINT ASSERT_TRUE(bf::is_regular_file(root_path / pkgid / "shared" / "res" / "SHARED-TPK-2")); // NOLINT - ASSERT_TRUE(bf::is_symlink(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-TPK-2")); // NOLINT ASSERT_FALSE(bf::exists(root_path / pkgid / "res" / "wgt" / "shared" / "res" / "SHARED-WGT-1")); // NOLINT ASSERT_FALSE(bf::exists(root_path / pkgid / "shared" / "res" / "SHARED-WGT-1")); // NOLINT } diff --git a/src/wgt/step/filesystem/step_wgt_patch_storage_directories.cc b/src/wgt/step/filesystem/step_wgt_patch_storage_directories.cc index cb8a221..dae2b53 100644 --- a/src/wgt/step/filesystem/step_wgt_patch_storage_directories.cc +++ b/src/wgt/step/filesystem/step_wgt_patch_storage_directories.cc @@ -12,6 +12,7 @@ namespace bf = boost::filesystem; namespace bs = boost::system; +namespace ci = common_installer; namespace { @@ -31,7 +32,8 @@ common_installer::Step::Status StepWgtPatchStorageDirectories::process() { int version = std::stoi(context_->manifest_data.get()->api_version); if (version >= 3) { - LOG(DEBUG) << "Symlinking widget's shared/res directory content in " + LOG(DEBUG) << + "Moving and linking widget's shared/res directory content in " << context_->pkg_path.get(); if (!ShareDirFor3x()) return Status::APP_DIR_ERROR; @@ -65,43 +67,27 @@ bool StepWgtPatchStorageDirectories::ShareDirFor3x() { return false; } } - // link all ${pkg_path}/res/wgt/shared/res content to ${pkg_path}/shared/res + + // move and link all contents of ${pkg_path}res/wgt/shared/res + // to ${pkg_path}shared/res bf::directory_iterator end_itr; for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) { - bf::path link_target = itr->path(); - if (bf::is_symlink(link_target)) { - continue; - } - bf::path link_file = shared_res_dir / link_target.filename(); - if (bf::exists(link_file)) { - LOG(DEBUG) << "shared/res linking: skipping existing " << link_file; - continue; - } - LOG(DEBUG) << "shared/res linking: creating link " << link_file; - bs::error_code error; - bf::create_symlink(link_target, link_file, error); - if (error) { - LOG(ERROR) << "shared/res linking: linking failed for " << link_file - << ": " << boost::system::system_error(error).what(); - return false; - } - } - // link all ${pkg_path}/shared/res content to ${pkg_path}/res/wgt/shared/res - for (bf::directory_iterator itr(shared_res_dir); itr != end_itr; ++itr) { - bf::path link_target = itr->path(); - if (bf::is_symlink(link_target)) { + bf::path current = itr->path(); + if (bf::is_symlink(current)) { continue; } - bf::path link_file = wgt_shared_res_dir / link_target.filename(); - if (bf::exists(link_file)) { - LOG(DEBUG) << "shared/res linking: skipping existing " << link_file; - continue; + bf::path dest = shared_res_dir / current.filename(); + if (bf::is_directory(current)) { + if (!ci::MoveDir(current, dest, ci::FS_MERGE_OVERWRITE)) + return false; + } else { + if (!ci::MoveFile(current, dest, true)) + return false; } - LOG(DEBUG) << "shared/res linking: creating link " << link_file; bs::error_code error; - bf::create_symlink(link_target, link_file, error); + bf::create_symlink(dest, current, error); if (error) { - LOG(ERROR) << "shared/res linking: linking failed for " << link_file + LOG(ERROR) << "linking failed for " << dest << ": " << boost::system::system_error(error).what(); return false; } diff --git a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc index 241b2ca..4909a6a 100644 --- a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc +++ b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.cc @@ -12,6 +12,7 @@ namespace bf = boost::filesystem; namespace bs = boost::system; +namespace ci = common_installer; namespace { @@ -24,10 +25,11 @@ const char kResWgtSubPath[] = "res/wgt"; namespace wgt { namespace filesystem { -common_installer::Step::Status StepWgtUndoPatchStorageDirectories::process() { +ci::Step::Status StepWgtUndoPatchStorageDirectories::process() { int version = std::stoi(context_->manifest_data.get()->api_version); if (version >= 3) { - LOG(DEBUG) << "Unlinking widget's shared/res directory content in " + LOG(DEBUG) << + "Unlinking and moving widget's shared/res directory content back in " << context_->pkg_path.get(); if (!UndoShareDirFor3x()) return Status::APP_DIR_ERROR; @@ -36,57 +38,101 @@ common_installer::Step::Status StepWgtUndoPatchStorageDirectories::process() { return Status::OK; } +ci::Step::Status StepWgtUndoPatchStorageDirectories::clean() { + if (!backup_dir_.empty()) + ci::RemoveAll(backup_dir_); + return Status::OK; +} + +ci::Step::Status StepWgtUndoPatchStorageDirectories::undo() { + if (!backup_dir_.empty()) { + LOG(DEBUG) << "Restore res/wgt/shared/res from backup dir"; + // restore link + bf::path wgt_shared_res_dir = + context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation; + bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res"; + if (!backup_wgt_shared_res.empty()) { + if (!ci::RemoveAll(wgt_shared_res_dir)) { + LOG(ERROR) << "Failed to remove res/wgt/shared/res"; + return Status::APP_DIR_ERROR; + } + if (!ci::CopyDir(backup_dir_, wgt_shared_res_dir, + ci::FS_MERGE_OVERWRITE, false)) { + LOG(ERROR) << "Failed to copy from backup"; + return Status::APP_DIR_ERROR; + } + } + // restore original contents + bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation; + bf::path backup_shared_res = backup_dir_ / "shared_res"; + if (!backup_shared_res.empty()) { + if (!ci::CopyDir(backup_dir_, shared_res_dir, + ci::FS_MERGE_OVERWRITE, false)) { + LOG(ERROR) << "Failed to copy from backup"; + return Status::APP_DIR_ERROR; + } + } + } + return Status::OK; +} + bool StepWgtUndoPatchStorageDirectories::UndoShareDirFor3x() { // check if ${pkg_path}/shared/res exists bf::path shared_res_dir = context_->pkg_path.get() / kSharedResLocation; + if (!bf::exists(shared_res_dir)) + return true; bf::path wgt_shared_res_dir = context_->pkg_path.get() / kResWgtSubPath / kSharedResLocation; - if (!bf::exists(shared_res_dir)) + if (!bf::exists(wgt_shared_res_dir)) return true; - // delete symlinks in ${pkg_path}/shared/res - if (bf::exists(shared_res_dir)) { - bf::directory_iterator end_itr; - for (bf::directory_iterator itr(shared_res_dir); itr != end_itr; ++itr) { - bf::path link_file = itr->path(); - if (!bf::is_symlink(link_file)) { - continue; - } - bf::path link_target = bf::read_symlink(link_file); - if (link_target.native().substr(0, wgt_shared_res_dir.native().length()) != - wgt_shared_res_dir.native()) { - continue; - } - LOG(DEBUG) << "shared/res linking: removing symlink " << link_file; - bs::error_code error; - bf::remove(link_file, error); - if (error) { - LOG(ERROR) << "Failed to remove symlink " << link_file; - return false; - } - } + + if (bf::is_symlink(wgt_shared_res_dir)) { + LOG(ERROR) << "Can't support this step, pkg should be fully updated"; + return false; } - // delete symlinks in ${pkg_path}/res/wgt/shared/res - if (bf::exists(wgt_shared_res_dir)) { - bf::directory_iterator end_itr; - for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) { - bf::path link_file = itr->path(); - if (!bf::is_symlink(link_file)) { - continue; - } - bf::path link_target = bf::read_symlink(link_file); - if (link_target.native().substr(0, shared_res_dir.native().length()) != - shared_res_dir.native()) { - continue; - } - LOG(DEBUG) << "shared/res linking: removing symlink " << link_file; - bs::error_code error; - bf::remove(link_file, error); - if (error) { - LOG(ERROR) << "Failed to remove symlink " << link_file; + + // backup for undo + backup_dir_ = context_->unpacked_dir_path.get(); + backup_dir_ += ".SharedRes"; + bf::path backup_shared_res = backup_dir_ / "shared_res"; + if (!ci::CreateDir(backup_shared_res)) + return false; + bf::path backup_wgt_shared_res = backup_dir_ / "wgt_shared_res"; + if (!ci::CopyDir(wgt_shared_res_dir, backup_wgt_shared_res, + ci::FS_MERGE_OVERWRITE, false)) { + backup_dir_.clear(); + return false; + } + + // unlink and move all linked contents from ${pkg_path}/shared/res + // to ${pkg_path}/res/wgt/shared/res + bf::directory_iterator end_itr; + for (bf::directory_iterator itr(wgt_shared_res_dir); itr != end_itr; ++itr) { + bf::path link_file = itr->path(); + if (!bf::is_symlink(link_file)) { + continue; + } + bf::path link_target = bf::read_symlink(link_file); + if (link_target.native().substr(0, shared_res_dir.native().length()) != + shared_res_dir.native()) { + continue; + } + if (!ci::Remove(link_file)) + return false; + bf::path tmp_backup = backup_shared_res / link_target.filename(); + if (bf::is_directory(link_target)) { + if (!ci::CopyDir(link_target, tmp_backup, ci::FS_MERGE_OVERWRITE, false)) + return false; + if (!ci::MoveDir(link_target, link_file, ci::FS_MERGE_OVERWRITE)) + return false; + } else { + if (!ci::CopyFile(link_target, tmp_backup)) + return false; + if (!ci::MoveFile(link_target, link_file, true)) return false; - } } } + return true; } diff --git a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h index 382ab72..e8494ad 100644 --- a/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h +++ b/src/wgt/step/filesystem/step_wgt_undo_patch_storage_directories.h @@ -23,12 +23,13 @@ class StepWgtUndoPatchStorageDirectories : using Step::Step; Status process() override; - Status clean() override { return Status::OK; } - Status undo() override { return Status::OK; } + Status clean() override; + Status undo() override; Status precheck() override { return Status::OK; } private: bool UndoShareDirFor3x(); + boost::filesystem::path backup_dir_; STEP_NAME(UndoPatchWgtStorageDirectories) }; -- 2.7.4