From: Dariusz Michaluk Date: Thu, 27 Nov 2014 14:05:36 +0000 (+0100) Subject: Added lock_domain/unlock_domain to container manager X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0314574a325461e60720db738d08bd809e9dd7ba;p=platform%2Fcore%2Fsecurity%2Fvasum.git Added lock_domain/unlock_domain to container manager [Feature] Ability to lock/unlock domain [Cause] The need for the ability to lock/unlock domains [Solution] Add lock_domain/unlock_domain function [Verification] Build, install, run Change-Id: I169f94ceef462346a33530ec467c9bb239b57d85 Signed-off-by: Dariusz Michaluk --- diff --git a/client/security-containers-client-impl.cpp b/client/security-containers-client-impl.cpp index b84e903..aa8a796 100644 --- a/client/security-containers-client-impl.cpp +++ b/client/security-containers-client-impl.cpp @@ -472,16 +472,20 @@ VsmStatus Client::vsm_start_domain(const char*) noexcept return vsm_get_status(); } -VsmStatus Client::vsm_lock_domain(const char*) noexcept +VsmStatus Client::vsm_lock_domain(const char* id) noexcept { - mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented"); - return vsm_get_status(); + assert(id); + + GVariant* args_in = g_variant_new("(s)", id); + return callMethod(HOST_INTERFACE, api::host::METHOD_LOCK_CONTAINER, args_in); } -VsmStatus Client::vsm_unlock_domain(const char*) noexcept +VsmStatus Client::vsm_unlock_domain(const char* id) noexcept { - mStatus = Status(VSMCLIENT_OTHER_ERROR, "Not implemented"); - return vsm_get_status(); + assert(id); + + GVariant* args_in = g_variant_new("(s)", id); + return callMethod(HOST_INTERFACE, api::host::METHOD_UNLOCK_CONTAINER, args_in); } VsmStatus Client::vsm_add_state_callback(VsmContainerDbusStateCallback containerDbusStateCallback, diff --git a/server/common-dbus-definitions.hpp b/server/common-dbus-definitions.hpp index 77d0949..389f73f 100644 --- a/server/common-dbus-definitions.hpp +++ b/server/common-dbus-definitions.hpp @@ -30,10 +30,11 @@ namespace security_containers { namespace api { -const std::string ERROR_FORBIDDEN = "org.tizen.containers.Error.Forbidden"; -const std::string ERROR_FORWARDED = "org.tizen.containers.Error.Forwarded"; -const std::string ERROR_INVALID_ID = "org.tizen.containers.Error.InvalidId"; -const std::string ERROR_INTERNAL = "org.tizen.containers.Error.Internal"; +const std::string ERROR_FORBIDDEN = "org.tizen.containers.Error.Forbidden"; +const std::string ERROR_FORWARDED = "org.tizen.containers.Error.Forwarded"; +const std::string ERROR_INVALID_ID = "org.tizen.containers.Error.InvalidId"; +const std::string ERROR_INVALID_STATE = "org.tizen.containers.Error.InvalidState"; +const std::string ERROR_INTERNAL = "org.tizen.containers.Error.Internal"; const std::string METHOD_PROXY_CALL = "ProxyCall"; diff --git a/server/container.cpp b/server/container.cpp index c371d8a..e1377d0 100644 --- a/server/container.cpp +++ b/server/container.cpp @@ -258,6 +258,18 @@ bool Container::isStopped() return mAdmin->isStopped(); } +void Container::suspend() +{ + Lock lock(mReconnectMutex); + mAdmin->suspend(); +} + +void Container::resume() +{ + Lock lock(mReconnectMutex); + mAdmin->resume(); +} + bool Container::isPaused() { Lock lock(mReconnectMutex); diff --git a/server/container.hpp b/server/container.hpp index bc1303c..b0264cb 100644 --- a/server/container.hpp +++ b/server/container.hpp @@ -154,6 +154,16 @@ public: bool isStopped(); /** + * Suspend container. + */ + void suspend(); + + /** + * Resume container. + */ + void resume(); + + /** * @return Is the container in a paused state? */ bool isPaused(); diff --git a/server/containers-manager.cpp b/server/containers-manager.cpp index d34cb87..c5fb04e 100644 --- a/server/containers-manager.cpp +++ b/server/containers-manager.cpp @@ -116,6 +116,12 @@ ContainersManager::ContainersManager(const std::string& managerConfigPath): mDet mHostConnection.setDestroyContainerCallback(bind(&ContainersManager::handleDestroyContainerCall, this, _1, _2)); + mHostConnection.setLockContainerCallback(bind(&ContainersManager::handleLockContainerCall, + this, _1, _2)); + + mHostConnection.setUnlockContainerCallback(bind(&ContainersManager::handleUnlockContainerCall, + this, _1, _2)); + for (auto& containerConfig : mConfig.containerConfigs) { createContainer(containerConfig); } @@ -261,6 +267,27 @@ void ContainersManager::stopAll() } } +bool ContainersManager::isPaused(const std::string& containerId) +{ + auto iter = mContainers.find(containerId); + if (iter == mContainers.end()) { + LOGE("No such container id: " << containerId); + throw ContainerOperationException("No such container"); + } + + return iter->second->isPaused(); +} + +bool ContainersManager::isRunning(const std::string& containerId) +{ + auto iter = mContainers.find(containerId); + if (iter == mContainers.end()) { + LOGE("No such container id: " << containerId); + throw ContainerOperationException("No such container"); + } + return iter->second->isRunning(); +} + std::string ContainersManager::getRunningForegroundContainerId() { for (auto& container : mContainers) { @@ -774,4 +801,64 @@ void ContainersManager::handleDestroyContainerCall(const std::string& id, thread.detach(); //TODO fix it } +void ContainersManager::handleLockContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result) +{ + LOGI("LockContainer call; Id=" << id ); + auto iter = mContainers.find(id); + if (iter == mContainers.end()) { + LOGE("Failed to lock container - no such container id: " << id); + result->setError(api::ERROR_INVALID_ID, "No such container id"); + return; + } + + auto& container = *iter->second; + if (!container.isRunning()) { + LOGE("Container id=" << id << " is not running."); + result->setError(api::ERROR_INVALID_STATE, "Container is not running"); + return; + } + + LOGT("Lock container"); + try { + container.suspend(); + } catch (ContainerOperationException& e) { + LOGE(e.what()); + result->setError(api::ERROR_INTERNAL, e.what()); + return; + } + + result->setVoid(); +} + +void ContainersManager::handleUnlockContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result) +{ + LOGI("UnlockContainer call; Id=" << id ); + auto iter = mContainers.find(id); + if (iter == mContainers.end()) { + LOGE("Failed to unlock container - no such container id: " << id); + result->setError(api::ERROR_INVALID_ID, "No such container id"); + return; + } + + auto& container = *iter->second; + if (!container.isPaused()) { + LOGE("Container id=" << id << " is not paused."); + result->setError(api::ERROR_INVALID_STATE, "Container is not paused"); + return; + } + + LOGT("Unlock container"); + try { + container.resume(); + } catch (ContainerOperationException& e) { + LOGE(e.what()); + result->setError(api::ERROR_INTERNAL, e.what()); + return; + } + + result->setVoid(); +} + } // namespace security_containers diff --git a/server/containers-manager.hpp b/server/containers-manager.hpp index 4adaaf8..5f31b97 100644 --- a/server/containers-manager.hpp +++ b/server/containers-manager.hpp @@ -79,6 +79,16 @@ public: void stopAll(); /** + * @return Is the container in a paused state? + */ + bool isPaused(const std::string& containerId); + + /** + * @return Is the container running? + */ + bool isRunning(const std::string& containerId); + + /** * @return id of the currently focused/foreground container */ std::string getRunningForegroundContainerId(); @@ -154,6 +164,10 @@ private: dbus::MethodResultBuilder::Pointer result); void handleDestroyContainerCall(const std::string& id, dbus::MethodResultBuilder::Pointer result); + void handleLockContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result); + void handleUnlockContainerCall(const std::string& id, + dbus::MethodResultBuilder::Pointer result); }; diff --git a/server/host-connection.cpp b/server/host-connection.cpp index 9b22f7b..f862b55 100644 --- a/server/host-connection.cpp +++ b/server/host-connection.cpp @@ -160,6 +160,17 @@ void HostConnection::setDestroyContainerCallback(const DestroyContainerCallback& mDestroyContainerCallback = callback; } +void HostConnection::setLockContainerCallback(const LockContainerCallback& callback) +{ + mLockContainerCallback = callback; +} + +void HostConnection::setUnlockContainerCallback(const UnlockContainerCallback& callback) +{ + mUnlockContainerCallback = callback; +} + + void HostConnection::onMessageCall(const std::string& objectPath, const std::string& interface, const std::string& methodName, @@ -305,6 +316,24 @@ void HostConnection::onMessageCall(const std::string& objectPath, mDestroyContainerCallback(id, result); } } + + if (methodName == api::host::METHOD_LOCK_CONTAINER) { + const gchar* id = NULL; + g_variant_get(parameters, "(&s)", &id); + + if (mLockContainerCallback){ + mLockContainerCallback(id, result); + } + } + + if (methodName == api::host::METHOD_UNLOCK_CONTAINER) { + const gchar* id = NULL; + g_variant_get(parameters, "(&s)", &id); + + if (mUnlockContainerCallback){ + mUnlockContainerCallback(id, result); + } + } } void HostConnection::proxyCallAsync(const std::string& busName, diff --git a/server/host-connection.hpp b/server/host-connection.hpp index ab13b50..0030efc 100644 --- a/server/host-connection.hpp +++ b/server/host-connection.hpp @@ -89,6 +89,12 @@ public: typedef std::function DestroyContainerCallback; + typedef std::function LockContainerCallback; + typedef std::function UnlockContainerCallback; /** * Register proxy call callback @@ -151,6 +157,16 @@ public: void setDestroyContainerCallback(const DestroyContainerCallback& callback); /** + * Register a callback called to lock container + */ + void setLockContainerCallback(const LockContainerCallback& callback); + + /** + * Register a callback called to unlock container + */ + void setUnlockContainerCallback(const UnlockContainerCallback& callback); + + /** * Make a proxy call */ void proxyCallAsync(const std::string& busName, @@ -177,6 +193,8 @@ private: SetActiveContainerCallback mSetActiveContainerCallback; CreateContainerCallback mCreateContainerCallback; DestroyContainerCallback mDestroyContainerCallback; + LockContainerCallback mLockContainerCallback; + UnlockContainerCallback mUnlockContainerCallback; void onNameAcquired(); void onNameLost(); diff --git a/server/host-dbus-definitions.hpp b/server/host-dbus-definitions.hpp index b61a4f8..1b134ea 100644 --- a/server/host-dbus-definitions.hpp +++ b/server/host-dbus-definitions.hpp @@ -48,6 +48,8 @@ const std::string METHOD_DECLARE_LINK = "DeclareLink"; const std::string METHOD_SET_ACTIVE_CONTAINER = "SetActiveContainer"; const std::string METHOD_CREATE_CONTAINER = "CreateContainer"; const std::string METHOD_DESTROY_CONTAINER = "DestroyContainer"; +const std::string METHOD_LOCK_CONTAINER = "LockContainer"; +const std::string METHOD_UNLOCK_CONTAINER = "UnlockContainer"; const std::string SIGNAL_CONTAINER_DBUS_STATE = "ContainerDbusState"; @@ -106,6 +108,12 @@ const std::string DEFINITION = " " " " " " + " " + " " + " " + " " + " " + " " " " " " " " diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index 934a062..61ed580 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -225,6 +225,20 @@ BOOST_AUTO_TEST_CASE(CreateContainerTest) vsm_client_free(client); } +BOOST_AUTO_TEST_CASE(LockUnlockContainerTest) +{ + const std::string newActiveContainerId = "ut-containers-manager-console2-dbus"; + + VsmClient client = vsm_client_create(); + VsmStatus status = vsm_connect(client); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); + status = vsm_lock_domain(client, newActiveContainerId.c_str()); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); + status = vsm_unlock_domain(client, newActiveContainerId.c_str()); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); + vsm_client_free(client); +} + BOOST_AUTO_TEST_CASE(FileMoveRequestTest) { const std::string path = "/tmp/fake_path"; diff --git a/tests/unit_tests/server/ut-containers-manager.cpp b/tests/unit_tests/server/ut-containers-manager.cpp index ef990f7..73643a8 100644 --- a/tests/unit_tests/server/ut-containers-manager.cpp +++ b/tests/unit_tests/server/ut-containers-manager.cpp @@ -408,6 +408,30 @@ public: asyncResult); } + void callMethodLockContainer(const std::string& id) + { + assert(isHost()); + GVariant* parameters = g_variant_new("(s)", id.c_str()); + GVariantPtr result = mClient->callMethod(api::host::BUS_NAME, + api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::METHOD_LOCK_CONTAINER, + parameters, + "()"); + } + + void callMethodUnlockContainer(const std::string& id) + { + assert(isHost()); + GVariant* parameters = g_variant_new("(s)", id.c_str()); + GVariantPtr result = mClient->callMethod(api::host::BUS_NAME, + api::host::OBJECT_PATH, + api::host::INTERFACE, + api::host::METHOD_UNLOCK_CONTAINER, + parameters, + "()"); + } + private: const int mId; DbusConnection::Pointer mClient; @@ -1090,4 +1114,34 @@ BOOST_AUTO_TEST_CASE(DeclareLink) expectedMessage("Not implemented")); } +BOOST_AUTO_TEST_CASE(LockUnlockContainerTest) +{ + ContainersManager cm(TEST_DBUS_CONFIG_PATH); + cm.startAll(); + + DbusAccessory dbus(DbusAccessory::HOST_ID); + + std::vector containerIds = {"ut-containers-manager-console1-dbus", + "ut-containers-manager-console2-dbus", + "ut-containers-manager-console3-dbus"}; + + for (std::string& containerId: containerIds){ + dbus.callMethodLockContainer(containerId); + BOOST_CHECK(cm.isPaused(containerId)); + dbus.callMethodUnlockContainer(containerId); + BOOST_CHECK(cm.isRunning(containerId)); + } + + BOOST_REQUIRE_THROW(dbus.callMethodLockContainer(NON_EXISTANT_CONTAINER_ID), + DbusException); + BOOST_REQUIRE_THROW(dbus.callMethodUnlockContainer(NON_EXISTANT_CONTAINER_ID), + DbusException); + + cm.stopAll(); + BOOST_REQUIRE_THROW(dbus.callMethodLockContainer("ut-containers-manager-console1-dbus"), + DbusException); + BOOST_REQUIRE_THROW(dbus.callMethodUnlockContainer("ut-containers-manager-console1-dbus"), + DbusException); +} + BOOST_AUTO_TEST_SUITE_END()