Support legacy image for backward-compatibility 24/107124/17 accepted/tizen/3.0/common/20170109.195852 accepted/tizen/3.0/ivi/20170109.073426 accepted/tizen/3.0/tv/20170110.055251 accepted/tizen/3.0/wearable/20170109.073222 submit/tizen_3.0/20170106.102334
authorjongmyeongko <jongmyeong.ko@samsung.com>
Mon, 26 Dec 2016 16:09:40 +0000 (01:09 +0900)
committerjongmyeongko <jongmyeong.ko@samsung.com>
Thu, 5 Jan 2017 13:39:56 +0000 (22:39 +0900)
Refer to:
https://review.tizen.org/gerrit/#/c/104823/

Change-Id: I1ccfb33c0fd12eb642352b9fd0a69f626087b5f8
Signed-off-by: jongmyeongko <jongmyeong.ko@samsung.com>
packaging/app-installers.spec
src/common/external_storage.cc
src/common/external_storage.h
src/common/pkgmgr_interface.cc
src/common/pkgmgr_signal.cc
src/common/request.h
src/common/security_registration.cc
src/common/security_registration.h
src/common/step/configuration/step_configure.cc
src/common/step/filesystem/step_migrate_legacy_external_image.cc [new file with mode: 0644]
src/common/step/filesystem/step_migrate_legacy_external_image.h [new file with mode: 0644]

index 267cf40b0d183926dd4d0940a76e2200fcf0b840..b3f28c4d79f9d58ea8e5103403517d85557a0e71 100644 (file)
@@ -1,6 +1,6 @@
 Name:           app-installers
 Summary:        Application installers
-Version:        1.11
+Version:        1.12
 Release:        1
 Group:          Application Framework/Package Management
 License:        Apache-2.0
index 61ee675b3e6c48ad1f24b0d3912b3bb087ab066b..7e2e820a8cbba614cf719fee6ec15396dec35180 100644 (file)
@@ -70,6 +70,14 @@ ExternalStorage::ExternalStorage(RequestType type,
     move_type_ = APP2EXT_MOVE_TO_PHONE;
 }
 
+ExternalStorage::ExternalStorage(RequestType type,
+    const std::string& pkgid, uid_t uid)
+    : type_(type),
+      pkgid_(pkgid),
+      uid_(uid),
+      handle_(nullptr) {
+}
+
 ExternalStorage::~ExternalStorage() {
   if (handle_)
     app2ext_deinit(handle_);
@@ -95,6 +103,10 @@ bool ExternalStorage::Finalize(bool success) {
                                static_cast<app2ext_move_type_t>(move_type_),
                                uid_);
     break;
+  case RequestType::MigrateExtImg:
+    ret = handle_->interface.client_usr_post_migrate_legacy(pkgid_.c_str(),
+                                                            uid_);
+    break;
   default:
     assert(false && "Not supported installation mode");
   }
@@ -185,6 +197,10 @@ bool ExternalStorage::Initialize(
   case RequestType::Uninstall:
     ret = handle_->interface.client_usr_pre_uninstall(pkgid_.c_str(), uid_);
     break;
+  case RequestType::MigrateExtImg:
+    ret = handle_->interface.client_usr_pre_migrate_legacy(pkgid_.c_str(),
+                                                           uid_);
+    break;
   case RequestType::Reinstall:
   case RequestType::Recovery:
   case RequestType::ManifestDirectInstall:
@@ -237,4 +253,16 @@ std::unique_ptr<ExternalStorage> ExternalStorage::AcquireExternalStorage(
   return external_storage;
 }
 
+std::unique_ptr<ExternalStorage> ExternalStorage::MigrateExternalStorage(
+    RequestType type, const std::string& pkgid, uid_t uid) {
+  std::unique_ptr<ExternalStorage> external_storage(
+      new ExternalStorage(type, pkgid, uid));
+  bf::path empty_path("");
+  if (!external_storage->Initialize(empty_path)) {
+    LOG(WARNING) << "Cannot initialize external storage for request";
+    return nullptr;
+  }
+  return external_storage;
+}
+
 }  // namespace common_installer
index e96bac68d2e2bc1dfce59d1e53c081aac651485c..886b9cd2be98a3f320477c9d89e58401cd41f47d 100644 (file)
@@ -35,6 +35,9 @@ class ExternalStorage final {
       const std::string& pkgid, const std::string& package_type,
       const boost::filesystem::path& space_requirement, uid_t uid);
 
+  static std::unique_ptr<ExternalStorage> MigrateExternalStorage(
+      RequestType type, const std::string& pkgid, uid_t uid);
+
   ExternalStorage(RequestType type, const std::string& pkgid,
                   const std::string& package_type,
                   const boost::filesystem::path& application_root, uid_t uid);
@@ -43,6 +46,7 @@ class ExternalStorage final {
                   const std::string& package_type,
                   const boost::filesystem::path& application_root, uid_t uid,
                   bool is_external_move);
+  ExternalStorage(RequestType type, const std::string& pkgid, uid_t uid);
   ~ExternalStorage();
 
   bool Commit();
index 4d787ac5ddec927febeb5270fb277bb1042071ec..50891b8134abf4416a1ac0fa92a93aa9ef8ad6d5 100644 (file)
@@ -168,6 +168,8 @@ RequestType PkgMgrInterface::GetRequestType() const {
       return RequestType::DisablePkg;
     case PKGMGR_REQ_ENABLE_PKG:
       return RequestType::EnablePkg;
+    case PKGMGR_REQ_MIGRATE_EXTIMG:
+      return RequestType::MigrateExtImg;
     default:
       return RequestType::Unknown;
   }
index 392566ece1ca947c63973d1229a34641fb7f7f4a..3a5116e41530629ffe84ba3d0df3fc4b3f18f527 100644 (file)
@@ -42,6 +42,7 @@ const std::map<ci::RequestType, const char*> kEventStr = {
   {ci::RequestType::ManifestPartialUpdate, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::DisablePkg, PKGMGR_INSTALLER_UNINSTALL_EVENT_STR},
   {ci::RequestType::EnablePkg, PKGMGR_INSTALLER_INSTALL_EVENT_STR},
+  {ci::RequestType::MigrateExtImg, PKGMGR_INSTALLER_UPGRADE_EVENT_STR},
   {ci::RequestType::Unknown, PKGMGR_INSTALLER_UNKNOWN_EVENT_STR}
 };
 
index 8ef8e815783c7904120d0b3e6dfa69eb3b78783b..78b4eb7393bd31a0320e8b659ecc9c730b075b93 100644 (file)
@@ -31,7 +31,8 @@ enum class RequestType : int {
   ReadonlyUpdateInstall,
   ReadonlyUpdateUninstall,
   DisablePkg,
-  EnablePkg
+  EnablePkg,
+  MigrateExtImg
 };
 
 /** Request mode (USER vs GLOBAL) */
index 427d312ae026ad8a784c29277c539dee08333508..9d052a4514a922776d1ac10f2c5ed2de3af9cfe7 100644 (file)
@@ -45,6 +45,14 @@ const std::vector<std::pair<const char*,
   {".mmc", SECURITY_MANAGER_PATH_RO}
 };
 
+const std::vector<std::pair<const char*,
+                app_install_path_type>> kSecurityPoliciesExternalOnly = {
+  {"bin", SECURITY_MANAGER_PATH_RO},
+  {"lib", SECURITY_MANAGER_PATH_RO},
+  {"res", SECURITY_MANAGER_PATH_RO},
+  {".mmc", SECURITY_MANAGER_PATH_RO}
+};
+
 const std::vector<std::pair<const char*, app_install_type>> kPathPolicies = {
   {tzplatform_getenv(TZ_SYS_HOME), SM_APP_INSTALL_LOCAL},
   {tzplatform_getenv(TZ_SYS_RW_APP), SM_APP_INSTALL_GLOBAL},
@@ -153,9 +161,10 @@ bool PrepareRequest(const std::string& app_id, const std::string& pkg_id,
   return true;
 }
 
-bool PreparePathRequest(const std::string& pkg_id,
-    const boost::filesystem::path& path, uid_t uid, path_req* req,
-    bool is_readonly_pkg, std::string* error_message) {
+bool PreparePathRequest(path_req* req, const std::string& pkg_id,
+    const std::string& pkg_type, const boost::filesystem::path& path,
+    uid_t uid, bool is_readonly_pkg, bool is_extonly,
+    std::string* error_message) {
   if (pkg_id.empty() || path.empty()) {
     LOG(ERROR) << "Pkgid or path is empty. Both values must be set";
     return false;
@@ -202,23 +211,37 @@ bool PreparePathRequest(const std::string& pkg_id,
     return false;
   }
 
-  for (auto& policy : kSecurityPolicies) {
+  std::vector<std::pair<const char*, app_install_path_type>> policies;
+  if (is_extonly)
+    policies = kSecurityPoliciesExternalOnly;
+  else
+    policies = kSecurityPolicies;
+  for (auto& policy : policies) {
     bf::path subpath = path / policy.first;
-    if (bf::exists(subpath)) {
+    if (is_extonly) {
+      // Now, this is for legacy migraton.
+      // do not try to access any file before changing label,
+      // this wil cause a exception from smack denial.
+      std::string subdir(policy.first);
+      if (pkg_type == "wgt" && (subdir == "bin" || subdir == "lib"))
+        continue;
+    } else {
+      if (!bf::exists(subpath))
+        continue;
       if (bf::is_symlink(symlink_status(subpath))) {
         LOG(DEBUG) << "Path " << subpath << " is a symlink."
                    << "Path will not be registered";
         continue;
       }
-      error = security_manager_path_req_add_path(req, subpath.c_str(),
-          policy.second);
-      if (error != SECURITY_MANAGER_SUCCESS) {
-        std::string errnum = boost::str(boost::format("%d") % error);
-        *error_message =
-                  security_manager_strerror(static_cast<lib_retcode>(error));
-        *error_message += ":<" + errnum + ">";
-        return false;
-      }
+    }
+    error = security_manager_path_req_add_path(req, subpath.c_str(),
+        policy.second);
+    if (error != SECURITY_MANAGER_SUCCESS) {
+      std::string errnum = boost::str(boost::format("%d") % error);
+      *error_message =
+                security_manager_strerror(static_cast<lib_retcode>(error));
+      *error_message += ":<" + errnum + ">";
+      return false;
     }
   }
 
@@ -364,8 +387,8 @@ bool UnregisterSecurityContextForPkgId(const std::string &pkg_id,
 }
 
 bool RegisterSecurityContextForPath(const std::string &pkg_id,
-    const boost::filesystem::path& path, uid_t uid,
-    bool is_readonly_pkg, std::string* error_message) {
+    const boost::filesystem::path& path, uid_t uid, bool is_readonly_pkg,
+    std::string* error_message) {
   path_req* req;
   int error = security_manager_path_req_new(&req);
   if (error != SECURITY_MANAGER_SUCCESS) {
@@ -378,9 +401,47 @@ bool RegisterSecurityContextForPath(const std::string &pkg_id,
     return false;
   }
 
-  if (!PreparePathRequest(pkg_id, path, uid, req, is_readonly_pkg,
+  if (!PreparePathRequest(req, pkg_id, {}, path, uid, is_readonly_pkg, false,
                           error_message)) {
-    LOG(ERROR) << "Failed while preparing security_manager_app_inst_req";
+    LOG(ERROR) << "Failed while preparing security_manager_path_req";
+    security_manager_path_req_free(req);
+    return false;
+  }
+
+  error = security_manager_paths_register(req);
+  if (error != SECURITY_MANAGER_SUCCESS) {
+    LOG(ERROR) << "Failed while calling security_manager_paths_register failed "
+               << "(error code: " << error << ")";
+    std::string errnum = boost::str(boost::format("%d") % error);
+    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
+    *error_message += ":<" + errnum + ">";
+    security_manager_path_req_free(req);
+    return false;
+  }
+
+  security_manager_path_req_free(req);
+
+  return true;
+}
+
+bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
+    const std::string &pkg_type, const boost::filesystem::path& path,
+    uid_t uid, std::string* error_message) {
+  path_req* req;
+  int error = security_manager_path_req_new(&req);
+  if (error != SECURITY_MANAGER_SUCCESS) {
+    LOG(ERROR)
+        << "Failed while calling security_manager_path_req_new failed "
+        << "(error code: " << error << ")";
+    std::string errnum = boost::str(boost::format("%d") % error);
+    *error_message = security_manager_strerror(static_cast<lib_retcode>(error));
+    *error_message += ":<" + errnum + ">";
+    return false;
+  }
+
+  if (!PreparePathRequest(req, pkg_id, pkg_type, path, uid, false, true,
+                          error_message)) {
+    LOG(ERROR) << "Failed while preparing security_manager_path_req";
     security_manager_path_req_free(req);
     return false;
   }
index 8c97ea00bb3993ef855fd402e4408e229e6a7be5..996a03ed67132219afbc82ac3f820b3040876382 100644 (file)
@@ -72,6 +72,24 @@ bool RegisterSecurityContextForPath(const std::string &pkg_id,
     const boost::filesystem::path& path, uid_t uid,
     bool is_readonly_pkg, std::string* error_message);
 
+/**
+ * Adapter interface for external Security module.
+ *
+ * Adapter interface for external Security module used for registering
+ * package external paths to security context
+ *
+ * \param pkg_id pkgid of given package
+ * \param pkg_type pkg type of given package
+ * \param path path for registering
+ * \param uid uid
+ * \param error_message extra/detailed error message
+ *
+ * \return true if success
+ */
+bool RegisterSecurityContextForPathExternalOnly(const std::string &pkg_id,
+    const std::string &pkg_type, const boost::filesystem::path& path,
+    uid_t uid, std::string* error_message);
+
 }  // namespace common_installer
 
 #endif  // COMMON_SECURITY_REGISTRATION_H_
index 8384f985284ec7408a4b2fcd6a910d68fc768e34..65b0904d4af41c61e9e2962c087714f3d25e3e68 100644 (file)
@@ -135,6 +135,13 @@ Step::Status StepConfigure::process() {
     case RequestType::EnablePkg:
       context_->pkgid.set(pkgmgr_->GetRequestInfo());
       break;
+    case RequestType::MigrateExtImg: {
+      context_->pkgid.set(pkgmgr_->GetRequestInfo());
+      bf::path package_directory =
+          context_->root_application_path.get() / context_->pkgid.get();
+      context_->pkg_path.set(package_directory);
+      break;
+    }
     default:
       LOG(ERROR) <<
           "Only installation, update and uninstallation is now supported";
diff --git a/src/common/step/filesystem/step_migrate_legacy_external_image.cc b/src/common/step/filesystem/step_migrate_legacy_external_image.cc
new file mode 100644 (file)
index 0000000..9066ff7
--- /dev/null
@@ -0,0 +1,106 @@
+// 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_migrate_legacy_external_image.h"
+
+#include <boost/filesystem.hpp>
+#include <app2ext_interface.h>
+#include <tzplatform_config.h>
+
+#include <string>
+
+#include "common/security_registration.h"
+#include "common/pkgmgr_query.h"
+
+namespace bf = boost::filesystem;
+
+namespace {
+
+const uid_t kDefaultUserUid = tzplatform_getuid(TZ_SYS_DEFAULT_USER);
+const uid_t kGlobalUserUid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
+const char kInstalledExternally[] = "installed_external";
+
+}  // namespace
+
+namespace common_installer {
+namespace security {
+
+Step::Status StepMigrateLegacyExtImage::precheck() {
+  // Policy : migration target user is 'default' user.
+  uid_t uid =  context_->uid.get();
+  if (uid != kDefaultUserUid && uid != kGlobalUserUid) {
+    LOG(ERROR) << "current target uid (" << uid <<") is not allowed";
+    return Step::Status::INVALID_VALUE;
+  }
+
+  if (context_->pkg_path.get().empty()) {
+    LOG(ERROR) << "pkg_path attribute is empty";
+    return Step::Status::INVALID_VALUE;
+  }
+  if (!boost::filesystem::exists(context_->pkg_path.get())) {
+    LOG(ERROR) << "pkg_path ("
+               << context_->pkg_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::INVALID_VALUE;
+  }
+
+  return Status::OK;
+}
+
+Step::Status StepMigrateLegacyExtImage::process() {
+  std::string pkgid = context_->pkgid.get();
+  uid_t uid = context_->uid.get();
+  if (QueryIsGlobalPackage(pkgid, uid))
+    context_->uid.set(kGlobalUserUid);
+
+  std::string storage_str = QueryStorageForPkgId(context_->pkgid.get(),
+      context_->uid.get());
+  if (strcmp(storage_str.c_str(), kInstalledExternally)) {
+    LOG(ERROR) << "Pkg not installed at external storage";
+    return Step::Status::ERROR;
+  }
+
+  context_->external_storage =
+      ExternalStorage::MigrateExternalStorage(context_->request_type.get(),
+          context_->pkgid.get(),
+          context_->uid.get());
+  if (!context_->external_storage) {
+    LOG(ERROR) << "Can not initialize external storage";
+    return Step::Status::ERROR;
+  }
+
+  std::string error_message;
+  if (!RegisterSecurityContextForPathExternalOnly(pkgid,
+                        context_->pkg_type.get(), context_->pkg_path.get(),
+                        uid, &error_message)) {
+    if (!error_message.empty()) {
+      LOG(ERROR) << "error_message: " << error_message;
+      on_error(Status::SECURITY_ERROR, error_message);
+    }
+    return Status::SECURITY_ERROR;
+  }
+
+  LOG(DEBUG) << "Security context installed";
+  return Status::OK;
+}
+
+Step::Status StepMigrateLegacyExtImage::undo() {
+  if (context_->external_storage)
+    context_->external_storage->Abort();
+  return Status::OK;
+}
+
+Step::Status StepMigrateLegacyExtImage::clean() {
+  if (context_->external_storage)
+    context_->external_storage->Commit();
+  return Status::OK;
+}
+
+}  // namespace security
+}  // namespace common_installer
diff --git a/src/common/step/filesystem/step_migrate_legacy_external_image.h b/src/common/step/filesystem/step_migrate_legacy_external_image.h
new file mode 100644 (file)
index 0000000..c1cc0b4
--- /dev/null
@@ -0,0 +1,30 @@
+// 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_MIGRATE_LEGACY_EXTERNAL_IMAGE_H_
+#define COMMON_STEP_FILESYSTEM_STEP_MIGRATE_LEGACY_EXTERNAL_IMAGE_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include "common/step/step.h"
+
+namespace common_installer {
+namespace security {
+
+class StepMigrateLegacyExtImage : public Step {
+ public:
+  using Step::Step;
+
+  Status process() override;
+  Status undo() override;
+  Status clean() override;
+  Status precheck() override;
+
+  STEP_NAME(MigrateLegacyExtImage)
+};
+
+}  // namespace security
+}  // namespace common_installer
+
+#endif  // COMMON_STEP_FILESYSTEM_STEP_MIGRATE_LEGACY_EXTERNAL_IMAGE_H_