From 2c60b799725ccfabdb2007e835fdd010242cc20f Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Thu, 10 Aug 2017 11:17:28 +0900 Subject: [PATCH 01/16] Apply ASLR to krate-volume-manager Signed-off-by: Sungbae Yoo Change-Id: I23c4c4c8be46379d2f5b8d07baae7af49e174090 --- volume/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/volume/CMakeLists.txt b/volume/CMakeLists.txt index 0ae5e95..a005c08 100644 --- a/volume/CMakeLists.txt +++ b/volume/CMakeLists.txt @@ -30,4 +30,7 @@ ADD_EXECUTABLE(${PROJECT_NAME}-volume-manager ${VOLUME_MANAGER_SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME}-volume-manager ${VOLUME_MANAGER_DEPS_LIBRARIES}) +SET_TARGET_PROPERTIES(${PROJECT_NAME}-volume-manager PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${PROJECT_NAME}-volume-manager PROPERTIES LINK_FLAGS "-pie") + INSTALL(TARGETS ${PROJECT_NAME}-volume-manager DESTINATION sbin) -- 2.7.4 From aa14bcd540386de4f2c1d9d4caa2131b8148ddd4 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Tue, 22 Aug 2017 13:56:19 +0900 Subject: [PATCH 02/16] Add ScopedGMainLoop for gmainloop Change-Id: Ie45393f7d1c7c3c99fff3835f12df14be90cbfa2 Signed-off-by: Sungbae Yoo --- server/main.cpp | 3 +++ server/server.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/server/main.cpp b/server/main.cpp index 448df58..8c15275 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -25,6 +25,8 @@ #include #include +#include + #include "server.h" void signalHandler(int signum) @@ -39,6 +41,7 @@ int main(int argc, char *argv[]) ::umask(0); try { + ScopedGMainLoop gmainloop; Server server; server.run(); } catch (std::exception &e) { diff --git a/server/server.cpp b/server/server.cpp index db3af1a..54ee475 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -58,7 +58,7 @@ Server::~Server() void Server::run() { // Prepare execution environment - service->start(true); + service->start(); } void Server::terminate() -- 2.7.4 From 59beda4dcfee88bd4969f784604cd0bfc621e834 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Tue, 29 Aug 2017 17:31:58 +0900 Subject: [PATCH 03/16] Change to retry when user creation/deletion is failed Change-Id: Id609e80c55e28124a2bee2ade190ff2ef950e7e2 Signed-off-by: Sungbae Yoo --- server/manager.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/server/manager.cpp b/server/manager.cpp index 90836b4..6db7446 100644 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -42,6 +42,7 @@ #include "rmi/manager.h" +#define GUMD_RETRY_COUNT 5 #define CGROUP_SUBSYSTEM "krate" #define PRIVILEGE_INTERNAL_PLATFORM "http://tizen.org/privilege/internal/default/platform" #define KRATE_DELEGATOR_APP "org.tizen.keyguard" @@ -534,14 +535,17 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) try { //create krate user by gumd - GumUser* guser = NULL; - while (guser == NULL) { - guser = gum_user_create_sync(FALSE); + gboolean ret = false; + for (int i = 0; i < GUMD_RETRY_COUNT && !ret; i++) { + GumUser* guser = NULL; + for (int i = 0; i < GUMD_RETRY_COUNT && guser == NULL; i++) { + guser = gum_user_create_sync(FALSE); + } + g_object_set(G_OBJECT(guser), "username", name.c_str(), + "usertype", GUM_USERTYPE_SECURITY, NULL); + ret = gum_user_add_sync(guser); + g_object_unref(guser); } - g_object_set(G_OBJECT(guser), "username", name.c_str(), - "usertype", GUM_USERTYPE_SECURITY, NULL); - gboolean ret = gum_user_add_sync(guser); - g_object_unref(guser); if (!ret) { throw runtime::Exception("Failed to remove user (" + name + ") by gumd"); @@ -634,12 +638,15 @@ int Manager::removeKrate(const std::string& name) ::tzplatform_reset_user(); //remove krate user - GumUser* guser = NULL; - while (guser == NULL) { - guser = gum_user_get_sync(user.getUid(), FALSE); + gboolean ret = false; + for (int i = 0; i < GUMD_RETRY_COUNT && !ret; i++) { + GumUser* guser = NULL; + for (int i = 0; i < GUMD_RETRY_COUNT && guser == NULL; i++) { + guser = gum_user_get_sync(user.getUid(), FALSE); + } + ret = gum_user_delete_sync(guser, TRUE); + g_object_unref(guser); } - gboolean ret = gum_user_delete_sync(guser, TRUE); - g_object_unref(guser); if (!ret) { throw runtime::Exception("Failed to remove user " + name + "(" + std::to_string(user.getUid()) + ") by gumd"); -- 2.7.4 From 1577efdf8c72dc57887c88b5daefeeea9ec45fb5 Mon Sep 17 00:00:00 2001 From: yeji01kim Date: Fri, 15 Sep 2017 16:00:39 +0900 Subject: [PATCH 04/16] Fix security svace defects - Add return value check of function umount2 Change-Id: I8d4b72d3a7bb5969f638c89aeb53f21079cb2da6 Signed-off-by: yeji01kim --- server/manager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 100755 server/manager.cpp diff --git a/server/manager.cpp b/server/manager.cpp old mode 100644 new mode 100755 index 6db7446..8c4f22f --- a/server/manager.cpp +++ b/server/manager.cpp @@ -634,7 +634,8 @@ int Manager::removeKrate(const std::string& name) //umount TZ_USER_CONTENT ::tzplatform_set_user(user.getUid()); - ::umount2(::tzplatform_getenv(TZ_USER_CONTENT), MNT_FORCE); + if (::umount2(::tzplatform_getenv(TZ_USER_CONTENT), MNT_FORCE) != 0) + throw runtime::Exception("Failed to umount2"); ::tzplatform_reset_user(); //remove krate user -- 2.7.4 From e396f44aba5aa55700e63426381d2ee87a49a7fa Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Tue, 19 Dec 2017 09:46:50 +0900 Subject: [PATCH 05/16] Change krate min/max UID Change-Id: Ib3518860bddf4a28c5f7dbd5e4cce555daac2aa8 Signed-off-by: Sungbae Yoo --- module/krate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/krate.cpp b/module/krate.cpp index bc8b091..2862042 100644 --- a/module/krate.cpp +++ b/module/krate.cpp @@ -35,8 +35,8 @@ #define CGROUP_SUBSYSTEM "krate" -#define KRATE_UID_MIN 60001 -#define KRATE_UID_MAX 60100 +#define KRATE_UID_MIN 6000 +#define KRATE_UID_MAX 6999 #define LAZYMOUNT_EXTERN extern #define LAZYMOUNT_LIB "/usr/lib/liblazymount.so.0" -- 2.7.4 From 5f624546628c7691f98112e0579da8b1eca901fa Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Tue, 19 Dec 2017 11:36:37 +0900 Subject: [PATCH 06/16] Change remove procedure to keep going if USER_CONTENT umount fails Change-Id: Iab84d582185bbfb824912f3d658b10d0b64dae5b Signed-off-by: Sungbae Yoo --- server/manager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/manager.cpp b/server/manager.cpp index 8c4f22f..ea3ac09 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -634,8 +634,9 @@ int Manager::removeKrate(const std::string& name) //umount TZ_USER_CONTENT ::tzplatform_set_user(user.getUid()); - if (::umount2(::tzplatform_getenv(TZ_USER_CONTENT), MNT_FORCE) != 0) - throw runtime::Exception("Failed to umount2"); + if (::umount2(::tzplatform_getenv(TZ_USER_CONTENT), MNT_FORCE) != 0) { + WARN("Failed to umount2 : TZ_USER_CONTENT"); + } ::tzplatform_reset_user(); //remove krate user -- 2.7.4 From 8a7fd43652ea7725f189975827d79535cc46413a Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Fri, 5 Jan 2018 16:18:53 +0900 Subject: [PATCH 07/16] Change to attach a gumd prefix to user id This commit has dependency with gumd commit (https://review.tizen.org/gerrit/#/c/165550/2) Change-Id: I4173ac0d8f9eb2a8a496d13319cde2ad8f4d5b31 Signed-off-by: Sungbae Yoo --- server/manager.cpp | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/server/manager.cpp b/server/manager.cpp index ea3ac09..643deb1 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -70,6 +70,7 @@ const std::string KRATE_CREATE_HOOK_PATH = "/etc/gumd/useradd.d"; const std::string KRATE_REMOVE_HOOK_PATH = "/etc/gumd/userdel.d"; std::string KRATE_DEFAULT_OWNER; +std::string KRATE_ID_PREFIX; std::list createdKrateList; static std::atomic isKrateForeground(false); @@ -217,8 +218,12 @@ void initializeCreatedKrateList() user = (GumUser*) src_list->data; if (user) { g_object_get(G_OBJECT(user), "username", &username, NULL); - createdKrateList.push_back(username); + std::string name = username; g_free(username); + + name = name.substr(KRATE_ID_PREFIX.size()); + + createdKrateList.push_back(name); } } @@ -507,6 +512,7 @@ Manager::Manager(KrateControlContext& ctx) : runtime::Cgroup::create(CGROUP_SUBSYSTEM, CGROUP_SUBSYSTEM); KRATE_DEFAULT_OWNER = ::tzplatform_getenv(TZ_SYS_DEFAULT_USER); + KRATE_ID_PREFIX = gum_user_type_to_prefix(GUM_USERTYPE_SECURITY); PackageManager& packageManager = PackageManager::instance(); packageManager.setEventCallback(packageEventHandler, this); @@ -517,7 +523,7 @@ Manager::Manager(KrateControlContext& ctx) : initializeCreatedKrateList(); for (std::string& name : createdKrateList) { - runtime::User krate(name); + runtime::User krate(KRATE_ID_PREFIX + name); notification_register_detailed_changed_cb_for_uid(notiProxyCallback, &name, krate.getUid()); } } @@ -551,7 +557,7 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) throw runtime::Exception("Failed to remove user (" + name + ") by gumd"); } - runtime::User user(name); + runtime::User user(name + KRATE_ID_PREFIX); maskUserServices(user); @@ -598,7 +604,7 @@ int Manager::removeKrate(const std::string& name) std::unique_ptr manifestFile; bool canRemove = false; - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); ::tzplatform_set_user(user.getUid()); std::string confPath(::tzplatform_getenv(TZ_USER_HOME)); confPath += "/.config/krate"; @@ -621,17 +627,14 @@ int Manager::removeKrate(const std::string& name) return -1; } - if (lockKrate(name) != 0) { - return -1; - } + //lock the user + setKrateState(user.getUid(), 0); - auto remove = [name, this] { + auto remove = [name, user, this] { //wait for krate session close sleep(1); try { - runtime::User user(name); - //umount TZ_USER_CONTENT ::tzplatform_set_user(user.getUid()); if (::umount2(::tzplatform_getenv(TZ_USER_CONTENT), MNT_FORCE) != 0) { @@ -680,7 +683,7 @@ int Manager::removeKrate(const std::string& name) int Manager::lockKrate(const std::string& name) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); setKrateState(user.getUid(), 0); } catch (runtime::Exception& e) { ERROR(e.what()); @@ -693,7 +696,7 @@ int Manager::lockKrate(const std::string& name) int Manager::unlockKrate(const std::string& name) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); setKrateState(user.getUid(), 1); } catch (runtime::Exception& e) { ERROR(e.what()); @@ -711,7 +714,7 @@ int Manager::getKrateState(const std::string& name) } try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); try { dbus::Connection& systemDBus = dbus::Connection::getSystem(); const dbus::Variant& var = systemDBus.methodcall @@ -747,7 +750,7 @@ std::vector Manager::getKrateList(int state) int Manager::resetKratePassword(const std::string& name, const std::string& newPassword) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); int ret = auth_passwd_reset_passwd(AUTH_PWD_NORMAL, user.getUid(), newPassword.c_str()); if (ret != AUTH_PASSWD_API_SUCCESS) { throw runtime::Exception("Failed to reset password for " + name); -- 2.7.4 From 4503aad5c6a4061ac5d6532db93929181615b9cc Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Thu, 22 Mar 2018 17:22:41 +0900 Subject: [PATCH 08/16] Add libgum-common library for gum_user_type_to_prefix Change-Id: I110375db6051c6d45f6f6281406989874645879e Signed-off-by: Sungbae Yoo --- server/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 0cdaa7e..7651c57 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -49,7 +49,7 @@ PKG_CHECK_MODULES(SERVER_DEPS REQUIRED ${DEPENDENCY}) INCLUDE_DIRECTORIES(SYSTEM ${SERVER_DEPS_INCLUDE_DIRS} ${KRATE_SERVER} ${PROJECT_SOURCE_DIR}) -TARGET_LINK_LIBRARIES(${SERVER_NAME} ${SERVER_DEPS_LIBRARIES} pthread) +TARGET_LINK_LIBRARIES(${SERVER_NAME} ${SERVER_DEPS_LIBRARIES} pthread gum-common) SET_TARGET_PROPERTIES(${SERVER_NAME} PROPERTIES COMPILE_FLAGS "-fPIE") SET_TARGET_PROPERTIES(${SERVER_NAME} PROPERTIES LINK_FLAGS "-pie") -- 2.7.4 From 904a8c33df56b641364c7d463d335eded21b83b0 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Fri, 23 Mar 2018 15:30:25 +0900 Subject: [PATCH 09/16] Add the gumd prefix to app-proxy and package-proxy APIs Change-Id: I5118eb9f19b3ea6893e41ecb33975319a80e3642 Signed-off-by: Sungbae Yoo --- server/app-proxy.cpp | 14 ++++++++------ server/manager.cpp | 25 +++++++++++++------------ server/package-proxy.cpp | 10 ++++++---- server/server.cpp | 6 ++++++ 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/server/app-proxy.cpp b/server/app-proxy.cpp index 48b031c..cb15c7c 100644 --- a/server/app-proxy.cpp +++ b/server/app-proxy.cpp @@ -31,6 +31,8 @@ #define PRIVILEGE_APP_LAUNCH "http://tizen.org/privilege/appmanager.launch" #define PRIVILEGE_APP_KILL "http://tizen.org/privilege/appmanager.kill" +extern std::string KRATE_ID_PREFIX; + namespace Krate { namespace { @@ -71,7 +73,7 @@ AppProxy::AppInfo AppProxy::getAppInfo(const std::string& name, const std::strin AppInfo appInfo; try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); ApplicationInfo appinfo(appid, user.getUid()); char* locale; @@ -104,7 +106,7 @@ int AppProxy::createIterator(const std::string& name) int iteratorId = -1; try { PackageManager& packman = PackageManager::instance(); - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); IteratorData data; iteratorId = newIteratorId; @@ -184,7 +186,7 @@ int AppProxy::destroyIterator(int iterator) int AppProxy::launch(const std::string& name, const AppProxy::Bundle& bundle) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); ::Bundle b; if (!bundle.operation.empty()) { @@ -220,7 +222,7 @@ int AppProxy::launch(const std::string& name, const AppProxy::Bundle& bundle) int AppProxy::resume(const std::string& name, const std::string& appid) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); Launchpad launchpad(user.getUid()); launchpad.resume(appid); } catch (runtime::Exception& e) { @@ -233,7 +235,7 @@ int AppProxy::resume(const std::string& name, const std::string& appid) int AppProxy::terminate(const std::string& name, const std::string& appid) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); Launchpad launchpad(user.getUid()); launchpad.terminate(appid); } catch (runtime::Exception& e) { @@ -246,7 +248,7 @@ int AppProxy::terminate(const std::string& name, const std::string& appid) bool AppProxy::isRunning(const std::string& name, const std::string& appid) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); Launchpad launchpad(user.getUid()); return launchpad.isRunning(appid); } catch (runtime::Exception& e) { diff --git a/server/manager.cpp b/server/manager.cpp index 643deb1..a817093 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -49,6 +49,8 @@ #define DEFAULT_ICON_PATH ICON_PATH "/default_icon.png" #define NOTIFICATION_SUB_ICON_PATH ICON_PATH "/notification_sub_icon.png" +extern std::string KRATE_ID_PREFIX; + namespace Krate { namespace { @@ -70,7 +72,6 @@ const std::string KRATE_CREATE_HOOK_PATH = "/etc/gumd/useradd.d"; const std::string KRATE_REMOVE_HOOK_PATH = "/etc/gumd/userdel.d"; std::string KRATE_DEFAULT_OWNER; -std::string KRATE_ID_PREFIX; std::list createdKrateList; static std::atomic isKrateForeground(false); @@ -461,7 +462,7 @@ void notiProxyUpdate(const runtime::User& owner, const runtime::User& user, int void notiProxyCallback(void *data, notification_type_e type, notification_op *op_list, int num_op) { static runtime::User owner(KRATE_DEFAULT_OWNER); - runtime::User user(*reinterpret_cast(data)); + runtime::User user(KRATE_ID_PREFIX + *reinterpret_cast(data)); if (user.getName() == owner.getName()) { // TODO : should remove noti in the krate when related-krate is removed @@ -512,7 +513,6 @@ Manager::Manager(KrateControlContext& ctx) : runtime::Cgroup::create(CGROUP_SUBSYSTEM, CGROUP_SUBSYSTEM); KRATE_DEFAULT_OWNER = ::tzplatform_getenv(TZ_SYS_DEFAULT_USER); - KRATE_ID_PREFIX = gum_user_type_to_prefix(GUM_USERTYPE_SECURITY); PackageManager& packageManager = PackageManager::instance(); packageManager.setEventCallback(packageEventHandler, this); @@ -547,17 +547,18 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) for (int i = 0; i < GUMD_RETRY_COUNT && guser == NULL; i++) { guser = gum_user_create_sync(FALSE); } - g_object_set(G_OBJECT(guser), "username", name.c_str(), + g_object_set(G_OBJECT(guser), "username", + (KRATE_ID_PREFIX + name).c_str(), "usertype", GUM_USERTYPE_SECURITY, NULL); ret = gum_user_add_sync(guser); g_object_unref(guser); } if (!ret) { - throw runtime::Exception("Failed to remove user (" + name + ") by gumd"); + throw runtime::Exception("Failed to create user (" + name + ") by gumd"); } - runtime::User user(name + KRATE_ID_PREFIX); + runtime::User user(KRATE_ID_PREFIX + name); maskUserServices(user); @@ -585,6 +586,7 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) auto it = createdKrateList.insert(createdKrateList.end(), name); notification_register_detailed_changed_cb_for_uid(notiProxyCallback, &(*it), user.getUid()); + context.notify("Manager::created", name, ""); } catch (runtime::Exception& e) { ERROR(e.what()); @@ -717,12 +719,11 @@ int Manager::getKrateState(const std::string& name) runtime::User user(KRATE_ID_PREFIX + name); try { dbus::Connection& systemDBus = dbus::Connection::getSystem(); - const dbus::Variant& var = systemDBus.methodcall - ("org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "GetUser", - -1, "(o)", "(u)", user.getUid()); + systemDBus.methodcall("org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "GetUser", + -1, "(o)", "(u)", user.getUid()); return Manager::State::Running; } catch (runtime::Exception& e) { return Manager::State::Locked; diff --git a/server/package-proxy.cpp b/server/package-proxy.cpp index 15ad13a..7e6b5a9 100644 --- a/server/package-proxy.cpp +++ b/server/package-proxy.cpp @@ -26,6 +26,8 @@ #define PRIVLEGE_PACKAGE_ADMIN "http://tizen.org/privilege/packagemanager.admin" +extern std::string KRATE_ID_PREFIX; + namespace Krate { PackageProxy::PackageProxy(KrateControlContext& ctx) : @@ -59,7 +61,7 @@ PackageProxy::PackageInfo PackageProxy::getPackageInfo(const std::string& name, free(locale); try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); ::PackageInfo pkginfo(pkgid, user.getUid()); package.type = pkginfo.getType(); @@ -88,7 +90,7 @@ PackageProxy::PackageInfo PackageProxy::getPackageInfo(const std::string& name, std::vector PackageProxy::getPackageList(const std::string& name) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); PackageManager& packman = PackageManager::instance(); return packman.getPackageList(user.getUid()); } catch (runtime::Exception& e) { @@ -101,7 +103,7 @@ std::vector PackageProxy::getPackageList(const std::string& name) int PackageProxy::install(const std::string& name, const std::string& pkgpath) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); PackageManager& packman = PackageManager::instance(); packman.installPackage(pkgpath, user.getUid()); } catch (runtime::Exception& e) { @@ -115,7 +117,7 @@ int PackageProxy::install(const std::string& name, const std::string& pkgpath) int PackageProxy::uninstall(const std::string& name, const std::string& pkgid) { try { - runtime::User user(name); + runtime::User user(KRATE_ID_PREFIX + name); PackageManager& packman = PackageManager::instance(); packman.uninstallPackage(pkgid, user.getUid()); } catch (runtime::Exception& e) { diff --git a/server/server.cpp b/server/server.cpp index 54ee475..60959a3 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include "server.h" #include "rmi/manager.h" @@ -27,6 +29,8 @@ using namespace std::placeholders; +std::string KRATE_ID_PREFIX; + namespace { const std::string KRATE_MANAGER_ADDRESS = "/tmp/.krate.sock"; @@ -49,6 +53,8 @@ Server::Server() manager.reset(new Krate::Manager(*this)); appProxy.reset(new Krate::AppProxy(*this)); packageProxy.reset(new Krate::PackageProxy(*this)); + + KRATE_ID_PREFIX = gum_user_type_to_prefix(GUM_USERTYPE_SECURITY); } Server::~Server() -- 2.7.4 From a16505915687de6dd48d889bc6bafa372d589fd2 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Mon, 26 Mar 2018 12:48:35 +0900 Subject: [PATCH 10/16] Fix the issues that the results of APIs aren't handled This is for solving some coverity issues Change-Id: I46cc67240bff904c92886ed316be147028222c57 Signed-off-by: Sungbae Yoo --- rmi/app-proxy.h | 6 +++--- rmi/package-proxy.h | 6 +++--- server/manager.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++---------- server/packman.cpp | 16 +++++++++++++--- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/rmi/app-proxy.h b/rmi/app-proxy.h index 2790f28..6e154f0 100644 --- a/rmi/app-proxy.h +++ b/rmi/app-proxy.h @@ -39,9 +39,9 @@ public: std::string type; std::string icon; std::string label; - int componentType; - bool isNoDisplayed; - bool isTaskManaged; + int componentType = 0; + bool isNoDisplayed = false; + bool isTaskManaged = false; REFLECTABLE (krate, id, locale, package, type, icon, label, diff --git a/rmi/package-proxy.h b/rmi/package-proxy.h index c4671ef..ccf56d1 100644 --- a/rmi/package-proxy.h +++ b/rmi/package-proxy.h @@ -48,9 +48,9 @@ public: std::string version; std::string apiVersion; std::string mainAppId; - bool isSystem; - bool isRemovable; - bool isPreload; + bool isSystem = false; + bool isRemovable = false; + bool isPreload = false; REFLECTABLE (krate, id, locale, type, icon, label, description, author, diff --git a/server/manager.cpp b/server/manager.cpp index a817093..6085306 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -331,23 +331,33 @@ void notiProxyInsert(const runtime::User& owner, const runtime::User& user, int { std::string krateLauncherUri; notification_h newNoti; - app_control_h appControl; + app_control_h appControl = NULL; char* pkgId; + int ret; notification_clone(noti, &newNoti); notification_get_pkgname(noti, &pkgId); try { PackageInfo pkg(pkgId, user.getUid()); - notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON, pkg.getIcon().c_str()); + ret = notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON, pkg.getIcon().c_str()); + if (ret != NOTIFICATION_ERROR_NONE) { + throw runtime::Exception("notification_set_image"); + } } catch (runtime::Exception &e) { - notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON, DEFAULT_ICON_PATH); + ret = notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON, DEFAULT_ICON_PATH); + if (ret != NOTIFICATION_ERROR_NONE) { + ERROR(std::string("Failed to set an image to noti : ") + e.what()); + } } - notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, NOTIFICATION_SUB_ICON_PATH); + ret = notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, NOTIFICATION_SUB_ICON_PATH); + if (ret != NOTIFICATION_ERROR_NONE) { + ERROR("Failed to set a sub-image to noti"); + } - notification_get_launch_option(newNoti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)&appControl); - if (appControl != NULL) { + ret = notification_get_launch_option(newNoti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)&appControl); + if (ret == NOTIFICATION_ERROR_NONE && appControl != NULL) { char* appId = NULL, *uri = NULL; app_control_get_app_id(appControl, &appId); @@ -368,6 +378,7 @@ void notiProxyInsert(const runtime::User& owner, const runtime::User& user, int app_control_set_app_id(appControl, KRATE_DELEGATOR_APP); app_control_set_uri(appControl, krateLauncherUri.c_str()); notification_set_launch_option(newNoti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, appControl); + app_control_destroy(appControl); } notification_post_for_uid(newNoti, owner.getUid()); @@ -391,6 +402,7 @@ void notiProxyUpdate(const runtime::User& owner, const runtime::User& user, int std::unordered_map::iterator it; double progress; char *str; + int ret; it = notiHandleMap.find(privId); if (it == notiHandleMap.end()) { @@ -419,8 +431,13 @@ void notiProxyUpdate(const runtime::User& owner, const runtime::User& user, int }; for (notification_image_type_e type : imageTypes) { - notification_get_image(noti, type, &str); - notification_set_image(it->second, type, str); + ret = notification_get_image(noti, type, &str); + if (ret == NOTIFICATION_ERROR_NONE) { + ret = notification_set_image(it->second, type, str); + if (ret != NOTIFICATION_ERROR_NONE) { + ERROR("Failed to copy an image of noti"); + } + } } notification_text_type_e textTypes[] = { @@ -446,8 +463,13 @@ void notiProxyUpdate(const runtime::User& owner, const runtime::User& user, int }; for (notification_text_type_e type : textTypes) { - notification_get_text(noti, type, &str); - notification_set_text(it->second, type, str, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + ret = notification_get_text(noti, type, &str); + if (ret == NOTIFICATION_ERROR_NONE) { + ret = notification_set_text(it->second, type, str, NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + if (ret != NOTIFICATION_ERROR_NONE) { + ERROR("Failed to copy a text of noti"); + } + } } notification_get_size(noti, &progress); @@ -547,6 +569,12 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) for (int i = 0; i < GUMD_RETRY_COUNT && guser == NULL; i++) { guser = gum_user_create_sync(FALSE); } + + if (guser == NULL) { + ret = 1; + break; + } + g_object_set(G_OBJECT(guser), "username", (KRATE_ID_PREFIX + name).c_str(), "usertype", GUM_USERTYPE_SECURITY, NULL); @@ -651,6 +679,12 @@ int Manager::removeKrate(const std::string& name) for (int i = 0; i < GUMD_RETRY_COUNT && guser == NULL; i++) { guser = gum_user_get_sync(user.getUid(), FALSE); } + + if (guser == NULL) { + ret = 1; + break; + } + ret = gum_user_delete_sync(guser, TRUE); g_object_unref(guser); } diff --git a/server/packman.cpp b/server/packman.cpp index 9425374..4e2cce7 100644 --- a/server/packman.cpp +++ b/server/packman.cpp @@ -37,7 +37,10 @@ int AppListCallback(pkgmgrinfo_appinfo_h handle, void *data) int PackageListCallback(pkgmgrinfo_pkginfo_h handle, void *data) { char* pkgid = nullptr; - ::pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid); + + if (::pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgid) != PMINFO_R_OK) { + return 0; + } std::vector* packageList = static_cast*>(data); packageList->push_back(pkgid); @@ -266,8 +269,15 @@ void ApplicationInfo::load(pkgmgrinfo_appinfo_h handle) { componentType = static_cast(comp); } - ::pkgmgrinfo_appinfo_is_nodisplay(handle, &noDisplayed); - ::pkgmgrinfo_appinfo_is_taskmanage(handle, &taskManaged); + ret = ::pkgmgrinfo_appinfo_is_nodisplay(handle, &noDisplayed); + if (ret != PMINFO_R_OK) { + noDisplayed = false; + } + + ret = ::pkgmgrinfo_appinfo_is_taskmanage(handle, &taskManaged); + if (ret != PMINFO_R_OK) { + taskManaged = false; + } } const std::string& ApplicationInfo::getId() const -- 2.7.4 From 747d14f1e998b15d2ec9f9548a472dc175fdb9c3 Mon Sep 17 00:00:00 2001 From: Jaemin Ryu Date: Tue, 14 Aug 2018 17:46:50 +0900 Subject: [PATCH 11/16] Use pam for containerization Change-Id: Ie32c449436258cb1a87bb08819eff664c77c8ac0 Signed-off-by: Jaemin Ryu --- module/CMakeLists.txt | 3 -- module/krate.cpp | 87 ++++++--------------------------------------------- packaging/krate.spec | 4 +-- server/manager.cpp | 2 -- 4 files changed, 11 insertions(+), 85 deletions(-) diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index 18f1e21..fa353f9 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -43,7 +43,4 @@ PKG_CHECK_MODULES(PAM_DEPS REQUIRED INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${PAM_DEPS_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${PAM_DEPS_LIBRARIES} pthread) -CONFIGURE_FILE(pam.d/systemd-user.in pam.d/systemd-user-${PROJECT_NAME}) - INSTALL(TARGETS ${PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) -INSTALL(FILES pam.d/systemd-user-${PROJECT_NAME} DESTINATION ${PAMD_DIR}) diff --git a/module/krate.cpp b/module/krate.cpp index 2862042..dda52c8 100644 --- a/module/krate.cpp +++ b/module/krate.cpp @@ -79,91 +79,18 @@ void enterKrate(const std::string& name) } } -static int wait_condition(void) -{ - int r; - void *h; - - int (*wait_mount_user)(void); - - r = access(LAZYMOUNT_LIB, F_OK); - if (r < 0){ - fprintf(stderr, "cannot find lazymount module - No support lazymount\n"); - return 0; - } - - h = dlopen(LAZYMOUNT_LIB, RTLD_LAZY); - if (!h) { - fprintf(stderr, "lazymount module dlopen error\n"); - return -1; - } - - do{ - wait_mount_user = (int (*)())dlsym(h, "wait_mount_user"); - if (!wait_mount_user) { - fprintf(stderr, "dlsym wait_mount_user error\n"); - dlclose(h); - return -1; - } - } while (0); - - r = wait_mount_user(); - if (r < 0) { - fprintf(stderr, "wait_mout_user failed\n"); - dlclose(h); - return r; - } - - dlclose(h); - return 0; -} - extern "C" { -LAZYMOUNT_EXTERN __attribute__((visibility("default"))) -int container_preprocess(char* id) { - std::cout << "kraterize (UID " << id << ")..." << std::endl << std::flush; - try { - runtime::User user(std::stoi(std::string(id))); - - enterKrate(user.getName()); - - if (user.getUid() >= KRATE_UID_MIN && user.getUid() <= KRATE_UID_MAX ) { - wait_condition(); - } - } catch (runtime::Exception& e) { - std::cerr << "krate error : " << e.what() <= KRATE_UID_MIN && user.getUid() <= KRATE_UID_MAX ) { + runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); + if (!flag.exists()) + flag.create(0644); + } } catch (runtime::Exception& e) { ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); return PAM_SESSION_ERR; @@ -181,6 +108,10 @@ int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* ar if (pids.size() <= 1) { std::string path = CGROUP_SUBSYSTEM "/" + name; runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); + runtime::User user(name); + runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); + if (flag.exists()) + flag.remove(false); } } catch (runtime::Exception& e) { ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); diff --git a/packaging/krate.spec b/packaging/krate.spec index f4848f9..0ac2d13 100644 --- a/packaging/krate.spec +++ b/packaging/krate.spec @@ -43,7 +43,6 @@ krates. %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/indicator_icon.png %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/notification_sub_icon.png %attr(755,root,root) %{_libdir}/security/pam_krate.so -%config /etc/pam.d/* %prep %setup -q @@ -73,6 +72,7 @@ mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants ln -s ../krate.service %{buildroot}/%{_unitdir}/multi-user.target.wants/krate.service %post +echo "session required pam_krate.so" >> /etc/pam.d/systemd-user %clean rm -rf %{buildroot} @@ -80,4 +80,4 @@ rm -rf %{buildroot} %preun %postun -mv /etc/pam.d/systemd-user.keep /etc/pam.d/systemd-user +sed --in-place '/pam_krate.so/d' /etc/pam.d/systemd-user diff --git a/server/manager.cpp b/server/manager.cpp index 6085306..d3b0aa5 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -588,8 +588,6 @@ int Manager::createKrate(const std::string& name, const std::string& manifest) runtime::User user(KRATE_ID_PREFIX + name); - maskUserServices(user); - ::tzplatform_set_user(user.getUid()); runtime::File confDir(std::string(::tzplatform_getenv(TZ_USER_HOME)) + "/.config/krate"); ::tzplatform_reset_user(); -- 2.7.4 From 7e5b02e7c33b65a344701be182516fc448920bc5 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Wed, 12 Sep 2018 17:28:02 +0900 Subject: [PATCH 12/16] Add krate-mount service which does mount after wait-mount.service in each namespace of krate. and also this requires krate-mount to have cap_sysadmin Change-Id: I6d0729d617d2d7aa610ec1a2e832688d50797ff2 Signed-off-by: Sungbae Yoo --- module/CMakeLists.txt | 32 ++++++++++++------ module/krate-builder.cpp | 55 +++++++++++++++++++++++++----- module/krate-builder.h | 17 ++++++---- module/krate-mount.cpp | 33 ++++++++++++++++++ module/krate.cpp | 63 ++++++++++------------------------- module/systemd/krate-mount.service.in | 11 ++++++ packaging/krate.spec | 9 ++++- 7 files changed, 149 insertions(+), 71 deletions(-) create mode 100644 module/krate-mount.cpp create mode 100644 module/systemd/krate-mount.service.in diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index fa353f9..0fd43f6 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -13,15 +13,20 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FILE(GLOB PAM_SRCS krate.cpp - krate-builder.cpp +SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") + +FILE(GLOB BUILDER_SRCS krate-builder.cpp) + +PKG_CHECK_MODULES(BUILDER_DEPS REQUIRED + klay + libxml-2.0 ) -SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") +FILE(GLOB PAM_SRCS krate.cpp) SET(PAM_NAME pam_${PROJECT_NAME}) +ADD_LIBRARY(${PAM_NAME} MODULE ${PAM_SRCS} ${BUILDER_SRCS}) -ADD_LIBRARY(${PAM_NAME} MODULE ${PAM_SRCS}) SET_TARGET_PROPERTIES(${PAM_NAME} PROPERTIES PREFIX "" COMPILE_DEFINITIONS PID_FILE_PATH="${RUN_INSTALL_DIR}/krate" COMPILE_FLAGS "-fvisibility=hidden" @@ -35,12 +40,19 @@ MARK_AS_ADVANCED(PAM_INCLUDE_DIR PAM_LIBRARY) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) -PKG_CHECK_MODULES(PAM_DEPS REQUIRED - klay - libxml-2.0 -) +INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${BUILDER_DEPS_INCLUDE_DIRS}) + +TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${BUILDER_DEPS_LIBRARIES}) + +FILE(GLOB MOUNT_SRCS krate-mount.cpp) + +SET(MOUNT_NAME ${PROJECT_NAME}-mount) +ADD_EXECUTABLE(${MOUNT_NAME} ${MOUNT_SRCS} ${BUILDER_SRCS}) + +TARGET_LINK_LIBRARIES(${MOUNT_NAME} ${MOUNT_SRC} ${BUILDER_DEPS_LIBRARIES}) -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${PAM_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${PAM_DEPS_LIBRARIES} pthread) +CONFIGURE_FILE(systemd/${MOUNT_NAME}.service.in systemd/${MOUNT_NAME}.service) INSTALL(TARGETS ${PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) +INSTALL(TARGETS ${MOUNT_NAME} DESTINATION ${BIN_DIR}) +INSTALL(FILES systemd/${MOUNT_NAME}.service DESTINATION ${SYSTEMD_USER_UNIT_DIR}) diff --git a/module/krate-builder.cpp b/module/krate-builder.cpp index 07fee11..3e13cc7 100644 --- a/module/krate-builder.cpp +++ b/module/krate-builder.cpp @@ -22,14 +22,17 @@ #include "krate-builder.h" #include +#include #include -KrateBuilder::KrateBuilder(const runtime::User& user, const std::string& manifestPath) : - name(user.getName()), uid(user.getUid()), gid(user.getGid()) +#define CGROUP_SUBSYSTEM "krate" + +KrateBuilder::KrateBuilder(const runtime::User& user) : + user(user) { - runtime::File data(manifestPath); + runtime::File data(getManifestPath()); if (data.exists()) { - manifest.reset(xml::Parser::parseFile(manifestPath)); + manifest.reset(xml::Parser::parseFile(data.getPath())); } } @@ -37,6 +40,11 @@ KrateBuilder::~KrateBuilder() { } +std::string KrateBuilder::getManifestPath() +{ + return "/home/" + user.getName() + "/.config/krate/krate.xml"; +} + void KrateBuilder::bindFilesystemNode(const std::string& source, const std::string& target, const std::string& type, const std::string& options, bool create) @@ -44,7 +52,7 @@ void KrateBuilder::bindFilesystemNode(const std::string& source, const std::stri if (create) { runtime::File dir(target); if (!dir.exists()) { - dir.makeDirectory(true, uid, gid); + dir.makeDirectory(true, user.getUid(), user.getGid()); } } @@ -61,10 +69,41 @@ void KrateBuilder::mountOwnFilesystem() } } - bindFilesystemNode("/home/" + name, - "/home/" + name + "/.krate/" + name, + bindFilesystemNode("/home/" + user.getName(), + "/home/" + user.getName() + "/.krate/" + user.getName(), "none", "rw,bind"); - bindFilesystemNode("/home/" + name + "/.krate", "/home", + bindFilesystemNode("/home/" + user.getName() + "/.krate", "/home", "none", "rw,rbind"); } + +void KrateBuilder::enterKrate() +{ + std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); + pid_t pid = 0; + + if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) { + auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (pids.size() > 0) { + pid = pids[0]; + } + } else { + runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); + } + + if (pid == 0) { + runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); + runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); + } else { + runtime::Namespace::attach(pid); + } +} + +void KrateBuilder::exitKrate() +{ + std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); + auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (pids.size() <= 1) { + runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); + } +} diff --git a/module/krate-builder.h b/module/krate-builder.h index 7947c6b..1563c3e 100644 --- a/module/krate-builder.h +++ b/module/krate-builder.h @@ -20,26 +20,29 @@ #include #include +#include #include #include #include class KrateBuilder final { public: - KrateBuilder(const runtime::User& user, const std::string& manifestPath); + KrateBuilder(const runtime::User& user); virtual ~KrateBuilder(); void mountOwnFilesystem(); -protected: + void enterKrate(); + void exitKrate(); + +private: + runtime::User user; + std::unique_ptr manifest; + + std::string getManifestPath(); void bindFilesystemNode(const std::string& source, const std::string& target, const std::string& type, const std::string& options, bool create = true); -private: - std::string name; - uid_t uid; - gid_t gid; - std::unique_ptr manifest; }; #endif //!__KRATE_BUILDER_H__ diff --git a/module/krate-mount.cpp b/module/krate-mount.cpp new file mode 100644 index 0000000..7595c0a --- /dev/null +++ b/module/krate-mount.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include +#include + +#include "krate-builder.h" + +int main(int argc, char *argv[]) +{ + try { + runtime::User user; + KrateBuilder builder(user); + builder.mountOwnFilesystem(); + } catch (std::exception &e) { + std::cerr << e.what() << std::endl; + } + + return EXIT_SUCCESS; +} diff --git a/module/krate.cpp b/module/krate.cpp index dda52c8..8c9a320 100644 --- a/module/krate.cpp +++ b/module/krate.cpp @@ -26,26 +26,20 @@ #include "krate-builder.h" -#include -#include #include #include -#include -#include - -#define CGROUP_SUBSYSTEM "krate" #define KRATE_UID_MIN 6000 #define KRATE_UID_MAX 6999 -#define LAZYMOUNT_EXTERN extern -#define LAZYMOUNT_LIB "/usr/lib/liblazymount.so.0" +namespace { -std::string buildKrateManifestPath(const std::string& name) -{ - return "/home/" + name + "/.config/krate/krate.xml"; +static std::string getFlagFilePath(runtime::User &user) { + return "/run/user/" + std::to_string(user.getUid()) + "/.container"; } +} // namespace + std::string getKrateName(pam_handle_t* handle) { const void* retItem; @@ -57,37 +51,18 @@ std::string getKrateName(pam_handle_t* handle) return static_cast(retItem); } -void enterKrate(const std::string& name) -{ - std::string path = CGROUP_SUBSYSTEM "/" + name; - pid_t pid = 0; - - if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) { - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); - if (pids.size() > 0) { - pid = pids[0]; - } - } else { - runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); - } - - if (pid == 0) { - runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); - runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); - } else { - runtime::Namespace::attach(pid); - } -} - extern "C" { PAM_EXTERN __attribute__((visibility("default"))) int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) { try { runtime::User user(getKrateName(pamh)); - enterKrate(user.getName()); + + KrateBuilder builder(user); + builder.enterKrate(); + if (user.getUid() >= KRATE_UID_MIN && user.getUid() <= KRATE_UID_MAX ) { - runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); + runtime::File flag(getFlagFilePath(user)); if (!flag.exists()) flag.create(0644); } @@ -103,16 +78,14 @@ PAM_EXTERN __attribute__((visibility("default"))) int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char* argv[]) { try { - std::string name = getKrateName(pamh); - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, name); - if (pids.size() <= 1) { - std::string path = CGROUP_SUBSYSTEM "/" + name; - runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); - runtime::User user(name); - runtime::File flag("/run/user/" + std::to_string(user.getUid()) + "/.container"); - if (flag.exists()) - flag.remove(false); - } + runtime::User user(getKrateName(pamh)); + + KrateBuilder builder(user); + builder.exitKrate(); + + runtime::File flag(getFlagFilePath(user)); + if (flag.exists()) + flag.remove(false); } catch (runtime::Exception& e) { ::pam_syslog(pamh, LOG_ERR, "%s", e.what()); return PAM_SESSION_ERR; diff --git a/module/systemd/krate-mount.service.in b/module/systemd/krate-mount.service.in new file mode 100644 index 0000000..e13a194 --- /dev/null +++ b/module/systemd/krate-mount.service.in @@ -0,0 +1,11 @@ +[Unit] +Description=@PROJECT_NAME@ mount manager for UID %U +DefaultDependencies=no +Wants=wait-mount@opt-usr.service +After=wait-mount@opt-usr.service +Before=session-bind.service basic.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=@BIN_DIR@/@PROJECT_NAME@-mount diff --git a/packaging/krate.spec b/packaging/krate.spec index 0ac2d13..a22e09a 100644 --- a/packaging/krate.spec +++ b/packaging/krate.spec @@ -35,9 +35,12 @@ krates. %manifest krate.manifest %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/krated +%attr(755,root,root) %{_bindir}/krate-mount %attr(700,root,root) %{_sbindir}/krate-volume-manager %{_unitdir}/krate.service %{_unitdir}/multi-user.target.wants/krate.service +%{_unitdir_user}/krate-mount.service +%{_unitdir_user}/basic.target.wants/krate-mount.service %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/default_icon.png %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/shortcut_icon.png %attr(644,root,root) %{TZ_SYS_RO_ICONS}/krate/indicator_icon.png @@ -61,6 +64,7 @@ krates. -DBIN_DIR=%{TZ_SYS_BIN} \ -DHOME_DIR=%{TZ_SYS_HOME} \ -DSYSTEMD_UNIT_DIR=%{_unitdir} \ + -DSYSTEMD_USER_UNIT_DIR=%{_unitdir_user} \ -DPAMD_DIR=/etc/pam.d \ -DICON_DIR="%{TZ_SYS_RO_ICONS}/krate" \ @@ -68,8 +72,11 @@ make %{?jobs:-j%jobs} %install %make_install +mkdir -p %{buildroot}/%{_unitdir_user}/basic.target.wants +ln -s ../krate-mount.service %{buildroot}/%{_unitdir_user}/basic.target.wants/. + mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants -ln -s ../krate.service %{buildroot}/%{_unitdir}/multi-user.target.wants/krate.service +ln -s ../krate.service %{buildroot}/%{_unitdir}/multi-user.target.wants/. %post echo "session required pam_krate.so" >> /etc/pam.d/systemd-user -- 2.7.4 From 974e788ebcf239353a997385971504e6294d6877 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Wed, 19 Sep 2018 10:38:18 +0900 Subject: [PATCH 13/16] Fix krate-mount to be applied ASLR Change-Id: I93f8cc077f459eaafd5e406cf33954a8998c1761 Signed-off-by: Sungbae Yoo --- module/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index 0fd43f6..2c3cd43 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -51,6 +51,9 @@ ADD_EXECUTABLE(${MOUNT_NAME} ${MOUNT_SRCS} ${BUILDER_SRCS}) TARGET_LINK_LIBRARIES(${MOUNT_NAME} ${MOUNT_SRC} ${BUILDER_DEPS_LIBRARIES}) +SET_TARGET_PROPERTIES(${MOUNT_NAME} PROPERTIES COMPILE_FLAGS "-fPIE") +SET_TARGET_PROPERTIES(${MOUNT_NAME} PROPERTIES LINK_FLAGS "-pie") + CONFIGURE_FILE(systemd/${MOUNT_NAME}.service.in systemd/${MOUNT_NAME}.service) INSTALL(TARGETS ${PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security) -- 2.7.4 From 4d17210164217ca25bf2c0218c21675207617e3c Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Mon, 1 Oct 2018 12:08:46 +0900 Subject: [PATCH 14/16] Fix catches in volume manager to get all exceptions Change-Id: I1400f534195a3688451e0eff667840d911d41e90 Signed-off-by: Sungbae Yoo --- volume/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/volume/main.cpp b/volume/main.cpp index a05625e..a2fa0db 100755 --- a/volume/main.cpp +++ b/volume/main.cpp @@ -48,7 +48,7 @@ int generateKey(const std::string& keyName) std::string wrappedKey = KeyGenerator::wrapKey(pass, salt, ECRYPTFS_MAX_KEY_SIZE); KeyManager::addKey(keyName, wrappedKey); - } catch (runtime::Exception& e) { + } catch (std::exception& e) { ERROR(e.what()); return -1; } @@ -80,7 +80,7 @@ int mountEcryptfs(const std::string& src, const std::string& keyName) std::string key; try { key = KeyManager::getKey(keyName); - } catch (runtime::Exception& e) { + } catch (std::exception& e) { ERROR(e.what()); return -1; } -- 2.7.4 From 11449eb98d42385e9567f34891f67ce898b67f67 Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Thu, 17 Jan 2019 12:26:57 +0900 Subject: [PATCH 15/16] Add klay-legacy classes into this repository It moves several classes such as Cgroup, Namespace, xml. Change-Id: I67bcd993230f8cbaf01012aba003d7bd8b7a734f Signed-off-by: Sungbae Yoo --- CMakeLists.txt | 1 + common/cgroup.cpp | 215 ++++++++++++++++++++++++++++++++++++++++++++++ common/cgroup.h | 43 ++++++++++ common/namespace.cpp | 77 +++++++++++++++++ common/namespace.h | 30 +++++++ common/xml/document.cpp | 135 +++++++++++++++++++++++++++++ common/xml/document.h | 49 +++++++++++ common/xml/keepblanks.cpp | 32 +++++++ common/xml/keepblanks.h | 38 ++++++++ common/xml/node.cpp | 116 +++++++++++++++++++++++++ common/xml/node.h | 60 +++++++++++++ common/xml/parser.cpp | 83 ++++++++++++++++++ common/xml/parser.h | 39 +++++++++ module/CMakeLists.txt | 11 ++- module/krate-builder.cpp | 19 ++-- module/krate-builder.h | 7 +- server/CMakeLists.txt | 5 ++ server/manager.cpp | 11 +-- 18 files changed, 952 insertions(+), 19 deletions(-) create mode 100644 common/cgroup.cpp create mode 100644 common/cgroup.h create mode 100644 common/namespace.cpp create mode 100644 common/namespace.h create mode 100644 common/xml/document.cpp create mode 100644 common/xml/document.h create mode 100644 common/xml/keepblanks.cpp create mode 100644 common/xml/keepblanks.h create mode 100644 common/xml/node.cpp create mode 100644 common/xml/node.h create mode 100644 common/xml/parser.cpp create mode 100644 common/xml/parser.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e7b2b3e..0a9d6f5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ SET(KRATE_SERVER ${PROJECT_SOURCE_DIR}/server) SET(KRATE_DATA ${PROJECT_SOURCE_DIR}/data) SET(KRATE_MODULE ${PROJECT_SOURCE_DIR}/module) SET(KRATE_VOLUME ${PROJECT_SOURCE_DIR}/volume) +SET(KRATE_COMMON ${PROJECT_SOURCE_DIR}/common) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7) SET(CXX_STD "c++0x") diff --git a/common/cgroup.cpp b/common/cgroup.cpp new file mode 100644 index 0000000..8276f46 --- /dev/null +++ b/common/cgroup.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "cgroup.h" + +#define NAME_PATTERN "^[A-Za-z_][A-Za-z0-9_-]*" +#define PATH_PATTERN "(/*[A-Za-z_][A-Za-z0-9_-]*)*" + +bool Cgroup::existSubsystem(const std::string& name) +{ + try { + if (!std::regex_match(name, std::regex(NAME_PATTERN))) { + return false; + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + klay::File dir("/sys/fs/cgroup/" + name); + if (dir.exists()) { + if (dir.isDirectory()) { + return true; + } + throw klay::Exception("Invalid subsystem name"); + } + + return false; +} + +void Cgroup::createSubsystem(const std::string& name) +{ + try { + if (!std::regex_match(name, std::regex(NAME_PATTERN))) { + throw klay::Exception("Invalid subsystem name"); + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + if (existSubsystem(name)) { + return; + } + + klay::File subsystem("/sys/fs/cgroup/" + name); + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the writable"); + } + + if (!subsystem.exists()) { + subsystem.makeDirectory(true); + } + + if (::mount(name.c_str(), subsystem.getPath().c_str(), + "cgroup", MS_NODEV | MS_NOSUID | MS_NOEXEC, + ("none,name=" + name).c_str())) { + subsystem.remove(false); + throw klay::Exception("Failed to mount cgroup subsystem"); + } + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | MS_RDONLY | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the read-only"); + } +} + +void Cgroup::destroySubsystem(const std::string& name) +{ + if (!existSubsystem(name)) { + throw klay::Exception("No such subsystem"); + } + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the writable"); + } + + klay::File subsystem("/sys/fs/cgroup/" + name); + ::umount2(subsystem.getPath().c_str(), MNT_EXPIRE); + + subsystem.remove(false); + + if (::mount(NULL, "/sys/fs/cgroup/", NULL, MS_REMOUNT | MS_RDONLY | + MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_STRICTATIME, + "mode=755")) { + throw klay::Exception("Failed to remount cgroupfs as the read-only"); + } +} + +bool Cgroup::exist(const std::string& subsystem, const std::string& path) +{ + try { + if (!std::regex_match(path, std::regex(PATH_PATTERN))) { + return false; + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + if (dir.exists()) { + if (dir.isDirectory()) { + return true; + } + throw klay::Exception("Invalid path"); + } + + return false; +} + +void Cgroup::create(const std::string& subsystem, const std::string& path) +{ + try { + if (!std::regex_match(path, std::regex(PATH_PATTERN))) { + throw klay::Exception("Invalid path"); + } + } catch (std::runtime_error &e) { + throw klay::Exception("Unexpected regex error"); + } + + if (exist(subsystem, path)) { + return; + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + dir.makeDirectory(true); +} + +void Cgroup::destroy(const std::string& subsystem, const std::string& path) +{ + if (!exist(subsystem, path)) { + throw klay::Exception("No such path in subsystem"); + } + + klay::File dir("/sys/fs/cgroup/" + subsystem + "/" + path); + dir.remove(false); +} + +void Cgroup::addProcess(const std::string& subsystem, const std::string& path, const pid_t pid) +{ + if (!exist(subsystem, path)) { + throw klay::Exception("No such path in subsystem"); + } + + std::ofstream ofs("/sys/fs/cgroup/" + subsystem + "/" + path + + "/tasks"); + + ofs << pid << std::endl; +} + +std::vector Cgroup::getProcessList(const std::string& subsystem, const std::string& path) +{ + std::vector ret; + std::ifstream ifs("/sys/fs/cgroup/" + subsystem + "/" + path + + "/tasks"); + + pid_t pid; + + ifs >> pid; + + while (ifs.good()) { + ret.push_back(pid); + ifs >> pid; + } + + return ret; +} + +const std::string Cgroup::getPath(const std::string& subsystem, const pid_t pid) +{ + std::ifstream ifs("/proc/" + std::to_string(pid) + "/cgroup"); + std::string ret = "/", line; + + while (std::getline(ifs, line)) { + std::stringstream lineStream(line); + std::string name; + + //the first getline is for removing the first argument + std::getline(lineStream, name, ':'); + std::getline(lineStream, name, ':'); + + if (name == subsystem || name == "name=" + subsystem) { + ret = line.substr(line.find('/')); + } + } + return ret; +} diff --git a/common/cgroup.h b/common/cgroup.h new file mode 100644 index 0000000..63994cd --- /dev/null +++ b/common/cgroup.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __COMMON_CGROUP_H__ +#define __COMMON_CGROUP_H__ + +#include +#include + +class Cgroup final { +public: + Cgroup() = delete; + + static bool existSubsystem(const std::string& name); + static void createSubsystem(const std::string& name); + static void destroySubsystem(const std::string& name); + + static bool exist(const std::string& subsystem, const std::string& path); + static void create(const std::string& subsystem, const std::string& path); + static void destroy(const std::string& subsystem, const std::string& path); + + static void addProcess(const std::string& subsystem, + const std::string& path, const pid_t pid); + static std::vector getProcessList(const std::string& subsystem, + const std::string& path); + + static const std::string getPath(const std::string& subsystem, const pid_t pid); +}; + +#endif //!__RUNTIME_CGROUP_H__ diff --git a/common/namespace.cpp b/common/namespace.cpp new file mode 100644 index 0000000..fdcd1b5 --- /dev/null +++ b/common/namespace.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include + +#include +#include +#include + +#include + +#include "namespace.h" + +namespace { + +typedef std::pair NamespacePair; +std::vector namespaces = { + {"mnt", CLONE_NEWNS}, + {"net", CLONE_NEWNET}, + {"ipc", CLONE_NEWIPC}, + {"pid", CLONE_NEWPID}, + {"uts", CLONE_NEWUTS}, + {"user", CLONE_NEWUSER}, +#ifdef CLONE_NEWCGROUP + {"cgroup", CLONE_NEWCGROUP}, +#endif +}; + +} // namespace + +void Namespace::attach(const pid_t pid) +{ + for (const NamespacePair& ns : namespaces) { + std::string nspath = "/proc/" + std::to_string(pid) + "/ns/" + ns.first; + + int fd; + do { + fd = ::open(nspath.c_str(), O_RDONLY); + } while (fd == -1 && errno == EINTR); + + if (fd == -1) { + if (errno != ENOENT) { + throw klay::Exception("Failed to open namesapce: " + nspath); + } + } else { + if (::setns(fd, ns.second)) { + ::close(fd); + throw klay::Exception("Failed to set namespace: " + nspath); + } + ::close(fd); + } + } +} + +void Namespace::unshare(int flags) +{ + if (::unshare(flags)) { + throw klay::Exception("Failed to unshare namespace"); + } + + if (flags & CLONE_NEWNS && + ::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) == -1) { + throw klay::Exception("Failed to mount root filesystem"); + } +} diff --git a/common/namespace.h b/common/namespace.h new file mode 100644 index 0000000..bc9368c --- /dev/null +++ b/common/namespace.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __RUNTIME_NAMESPACE_H__ +#define __RUNTIME_NAMESPACE_H__ + +#include + +class Namespace final { +public: + Namespace() = delete; + + static void unshare(int flags); + static void attach(const pid_t pid); +}; + +#endif //!__RUNTIME_NAMESPACE_H__ diff --git a/common/xml/document.cpp b/common/xml/document.cpp new file mode 100644 index 0000000..6056b09 --- /dev/null +++ b/common/xml/document.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#include + +#include + +#include + +#include "document.h" +#include "keepblanks.h" + +namespace xml { + +Document::Document(const std::string& root, const std::string& version) : + implementation(xmlNewDoc((const xmlChar*)version.c_str())) +{ + if (implementation == nullptr) { + throw klay::Exception("Failed to create document"); + } + + implementation->_private = this; + + xmlNode* rootPtr = xmlNewNode(NULL, xmlStrdup((const xmlChar*)root.c_str())); + xmlDocSetRootElement(implementation, rootPtr); + + rootNode = new Node(rootPtr); +} + +Document::Document(xmlDoc* doc) + : implementation(doc) +{ + implementation->_private = this; + + rootNode = new Node(xmlDocGetRootElement(implementation)); +} + +Document::~Document() +{ + if (rootNode != nullptr) { + delete rootNode; + } + + xmlFreeDoc(implementation); +} + +Node& Document::getRootNode() +{ + if (rootNode == nullptr) { + throw klay::Exception("Empty document"); + } + + return *rootNode; +} + +Node::NodeList Document::evaluate(const std::string& xpath) +{ + auto ctxt = xmlXPathNewContext(implementation); + if (ctxt == nullptr) { + throw klay::Exception("Failed to create XPath context for " + xpath); + } + + auto result = xmlXPathEval((const xmlChar*)xpath.c_str(), ctxt); + if (result == nullptr) { + xmlXPathFreeContext(ctxt); + throw klay::Exception("Invalid XPath: " + xpath); + } + + if (result ->type != XPATH_NODESET) { + xmlXPathFreeObject(result); + xmlXPathFreeContext(ctxt); + + throw klay::Exception("Only nodeset result types are supported"); + } + + auto nodeset = result->nodesetval; + + Node::NodeList nodes; + if ((nodeset == nullptr) || (xmlXPathNodeSetIsEmpty(nodeset))) { + xmlXPathFreeContext(ctxt); + return nodes; + } + + const int count = xmlXPathNodeSetGetLength(nodeset); + + nodes.reserve(count); + for (int i = 0; i != count; i++) { + auto cnode = xmlXPathNodeSetItem(nodeset, i); + if (!cnode) { + continue; + } + + if (cnode->type == XML_NAMESPACE_DECL) { + continue; + } + + nodes.emplace_back(cnode); + } + + xmlXPathFreeObject(result); + xmlXPathFreeContext(ctxt); + + return nodes; +} + +void Document::write(const std::string& filename, const std::string& encoding, bool formatted) +{ + KeepBlanks keepBlanks(KeepBlanks::Default); + xmlIndentTreeOutput = formatted; + + xmlResetLastError(); + + const int result = xmlSaveFormatFileEnc(filename.c_str(), + implementation, + encoding.c_str(), + formatted); + if (result == 0) { + throw klay::Exception("Failed to write XML document"); + } +} + +} // namespace xml diff --git a/common/xml/document.h b/common/xml/document.h new file mode 100644 index 0000000..08dd1b5 --- /dev/null +++ b/common/xml/document.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __XML_DOCUMENT_H__ +#define __XML_DOCUMENT_H__ + +#include +#include + +#include + +#include + +namespace xml { + +class Document { +public: + Document(const std::string& root, const std::string& version = XML_DEFAULT_VERSION); + Document(xmlDoc* doc); + + ~Document(); + + Node& getRootNode(); + + Node::NodeList evaluate(const std::string& xpath); + void write(const std::string& filename, const std::string& encoding, bool formatted); + +private: + Node* rootNode; + xmlDoc* implementation; +}; + +} // namespace xml + + +#endif //__XML_DOCUMENT_H__ diff --git a/common/xml/keepblanks.cpp b/common/xml/keepblanks.cpp new file mode 100644 index 0000000..906aa75 --- /dev/null +++ b/common/xml/keepblanks.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include "keepblanks.h" + +namespace xml { + +KeepBlanks::KeepBlanks(bool value) +{ + preservedIndentTreeOutput = xmlIndentTreeOutput; + preservedKeepBlanksDefault = xmlKeepBlanksDefault(value ? 1 : 0); +} + +KeepBlanks::~KeepBlanks() +{ + xmlKeepBlanksDefault(preservedKeepBlanksDefault); + xmlIndentTreeOutput = preservedIndentTreeOutput; +} + +} // namespace xml diff --git a/common/xml/keepblanks.h b/common/xml/keepblanks.h new file mode 100644 index 0000000..d227051 --- /dev/null +++ b/common/xml/keepblanks.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __XML_KEEPBLANKS_H__ +#define __XML_KEEPBLANKS_H__ + +#include + +namespace xml { + +class KeepBlanks { +public: + KeepBlanks(bool value); + ~KeepBlanks(); + + static const bool Default = true; + +private: + int preservedKeepBlanksDefault; + int preservedIndentTreeOutput; +}; + +} // namespace xml + +#endif //__XML_KEEPBLANKS_H__ diff --git a/common/xml/node.cpp b/common/xml/node.cpp new file mode 100644 index 0000000..0c0609e --- /dev/null +++ b/common/xml/node.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include + +#include "node.h" + +namespace xml { + +Node::Node(xmlNode* node) : + implementation(node) +{ +} + +Node::Node(Node&& node) : + implementation(node.implementation) +{ +} + +Node::~Node() +{ +} + +Node::NodeList Node::getChildren() const +{ + NodeList nodeList; + + auto child = implementation->xmlChildrenNode; + while (child != nullptr) { + nodeList.emplace_back(child); + child = child->next; + } + + return nodeList; +} + +Node Node::addNewChild(const std::string& name) +{ + xmlNode* nodePtr = xmlNewNode(NULL, xmlStrdup((const xmlChar*)name.c_str())); + if (nodePtr == nullptr) { + throw klay::Exception("Can not create a new node"); + } + xmlAddChild(implementation, nodePtr); + + return Node(nodePtr); +} + +std::string Node::getName() const +{ + return implementation->name ? (const char*)implementation->name : ""; +} + +void Node::setName(const std::string& name) +{ + xmlNodeSetName(implementation, (const xmlChar*)name.c_str()); +} + +std::string Node::getContent() const +{ + xmlChar* content = xmlNodeGetContent(implementation); + if (content == NULL) { + return ""; + } + std::string ret((const char*)content); + xmlFree(content); + return ret; +} + +void Node::setContent(const std::string& content) +{ + xmlNodeSetContent(implementation, (xmlChar*)content.c_str()); +} + +std::string Node::getProp(const std::string& name) const +{ + if (implementation->type != XML_ELEMENT_NODE) { + throw klay::Exception("This node type does not have properties"); + } + + xmlChar* prop = xmlGetProp(implementation, (xmlChar*)name.c_str()); + if (prop) { + std::string ret((const char*)prop); + xmlFree(prop); + return ret; + } + + return ""; +} + +void Node::setProp(const std::string& name, const std::string& val) +{ + if (implementation->type != XML_ELEMENT_NODE) { + throw klay::Exception("Can not set properties for this node type"); + } + + xmlSetProp(implementation, (xmlChar*)name.c_str(), (xmlChar*)val.c_str()); +} + +bool Node::isBlank() const +{ + return xmlIsBlankNode(const_cast(implementation)); +} + +} // namespace xml diff --git a/common/xml/node.h b/common/xml/node.h new file mode 100644 index 0000000..259164c --- /dev/null +++ b/common/xml/node.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __XML_NODE_H__ +#define __XML_NODE_H__ + +#include +#include + +#include +#include + +namespace xml { + +class Node { +public: + typedef std::vector NodeList; + + explicit Node(xmlNode* node); + Node(Node&&); + Node(const Node&) = delete; + + ~Node(); + + Node& operator=(const Node&) = delete; + + NodeList getChildren() const; + Node addNewChild(const std::string& name); + + std::string getName() const; + void setName(const std::string& name); + + std::string getContent() const; + void setContent(const std::string& content); + + std::string getProp(const std::string& name) const; + void setProp(const std::string& name, const std::string& val); + + bool isBlank() const; + +private: + xmlNode* implementation; +}; + +} // namespace xml + +#endif //__XML_NODE_H__ diff --git a/common/xml/parser.cpp b/common/xml/parser.cpp new file mode 100644 index 0000000..a878d30 --- /dev/null +++ b/common/xml/parser.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ +#include + +#include + +#include "parser.h" +#include "keepblanks.h" + +namespace xml { + +Document* Parser::parseContext(xmlParserCtxt* context, bool validate) +{ + if (context == nullptr) { + throw klay::Exception("Could not create parser context"); + } + + KeepBlanks(false); + + int options = 0; + + if (validate) { + options |= XML_PARSE_DTDVALID; + } else { + options &= ~XML_PARSE_DTDVALID; + } + + xmlCtxtUseOptions(context, options); + + if (xmlParseDocument(context) < 0) { + xmlFreeParserCtxt(context); + throw klay::Exception("Parsing failed"); + } + + xmlDoc* document = context->myDoc; + + // We took the ownership on the doc + context->myDoc = nullptr; + + xmlFreeParserCtxt(context); + + return new Document(document); +} + +Document* Parser::parseFile(const std::string& filename, bool validate) +{ + xmlParserCtxt* context = xmlCreateFileParserCtxt(filename.c_str()); + if (context == nullptr) { + throw klay::Exception("Could not create parser context"); + } + + if (context->directory == nullptr) { + context->directory = xmlParserGetDirectory(filename.c_str()); + } + + return parseContext(context, validate); +} + +Document* Parser::parseString(const std::string& xml, bool validate) +{ + xmlParserCtxt* context = xmlCreateMemoryParserCtxt(xml.c_str(), xml.size() + 1); + + if (context == nullptr) { + throw klay::Exception("Could not create parser context"); + } + + return parseContext(context, validate); +} + +} // namespace xml diff --git a/common/xml/parser.h b/common/xml/parser.h new file mode 100644 index 0000000..f6f3eb9 --- /dev/null +++ b/common/xml/parser.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +#ifndef __XML_DOMPARSER_H__ +#define __XML_DOMPARSER_H__ + +#include + +#include + +#include + +namespace xml { + +class Parser { +public: + static Document* parseFile(const std::string& filename, bool validate = false); + static Document* parseString(const std::string& xml, bool validate = false); + +private: + static Document* parseContext(xmlParserCtxt* context, bool validate = false); +}; + +} // namespace xml + +#endif //__XML_DOMPARSER_H__ diff --git a/module/CMakeLists.txt b/module/CMakeLists.txt index 2c3cd43..c3a603e 100644 --- a/module/CMakeLists.txt +++ b/module/CMakeLists.txt @@ -15,7 +15,14 @@ # SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack") -FILE(GLOB BUILDER_SRCS krate-builder.cpp) +FILE(GLOB BUILDER_SRCS krate-builder.cpp + ${KRATE_COMMON}/cgroup.cpp + ${KRATE_COMMON}/namespace.cpp + ${KRATE_COMMON}/xml/node.cpp + ${KRATE_COMMON}/xml/parser.cpp + ${KRATE_COMMON}/xml/document.cpp + ${KRATE_COMMON}/xml/keepblanks.cpp +) PKG_CHECK_MODULES(BUILDER_DEPS REQUIRED klay @@ -40,7 +47,7 @@ MARK_AS_ADVANCED(PAM_INCLUDE_DIR PAM_LIBRARY) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PAM DEFAULT_MSG PAM_LIBRARY PAM_INCLUDE_DIR) -INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${BUILDER_DEPS_INCLUDE_DIRS}) +INCLUDE_DIRECTORIES(${PAM_INCLUDE_DIR} ${BUILDER_DEPS_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}) TARGET_LINK_LIBRARIES(${PAM_NAME} ${PAM_LIBRARY} ${BUILDER_DEPS_LIBRARIES}) diff --git a/module/krate-builder.cpp b/module/krate-builder.cpp index 3e13cc7..4b423cc 100644 --- a/module/krate-builder.cpp +++ b/module/krate-builder.cpp @@ -22,9 +22,10 @@ #include "krate-builder.h" #include -#include #include +#include + #define CGROUP_SUBSYSTEM "krate" KrateBuilder::KrateBuilder(const runtime::User& user) : @@ -82,28 +83,28 @@ void KrateBuilder::enterKrate() std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); pid_t pid = 0; - if (runtime::Cgroup::exist(CGROUP_SUBSYSTEM, path)) { - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + if (Cgroup::exist(CGROUP_SUBSYSTEM, path)) { + auto pids = Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); if (pids.size() > 0) { pid = pids[0]; } } else { - runtime::Cgroup::create(CGROUP_SUBSYSTEM, path); + Cgroup::create(CGROUP_SUBSYSTEM, path); } if (pid == 0) { - runtime::Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); - runtime::Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); + Cgroup::addProcess(CGROUP_SUBSYSTEM, path, ::getpid()); + Namespace::unshare(CLONE_NEWNS | CLONE_NEWIPC); } else { - runtime::Namespace::attach(pid); + Namespace::attach(pid); } } void KrateBuilder::exitKrate() { std::string path = CGROUP_SUBSYSTEM "/" + user.getName(); - auto pids = runtime::Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); + auto pids = Cgroup::getProcessList(CGROUP_SUBSYSTEM, path); if (pids.size() <= 1) { - runtime::Cgroup::destroy(CGROUP_SUBSYSTEM, path); + Cgroup::destroy(CGROUP_SUBSYSTEM, path); } } diff --git a/module/krate-builder.h b/module/krate-builder.h index 1563c3e..724b9ea 100644 --- a/module/krate-builder.h +++ b/module/krate-builder.h @@ -20,11 +20,12 @@ #include #include -#include -#include -#include #include +#include +#include +#include + class KrateBuilder final { public: KrateBuilder(const runtime::User& user); diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 7651c57..f75b6d6 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -21,6 +21,11 @@ SET(SERVER_SRCS main.cpp manager.cpp app-proxy.cpp package-proxy.cpp + ${KRATE_COMMON}/cgroup.cpp + ${KRATE_COMMON}/xml/node.cpp + ${KRATE_COMMON}/xml/parser.cpp + ${KRATE_COMMON}/xml/document.cpp + ${KRATE_COMMON}/xml/keepblanks.cpp ) SET(DEPENDENCY klay diff --git a/server/manager.cpp b/server/manager.cpp index d3b0aa5..4a95afa 100755 --- a/server/manager.cpp +++ b/server/manager.cpp @@ -28,17 +28,18 @@ #include #include #include -#include #include #include #include -#include -#include + #include #include #include "packman.h" #include "launchpad.h" +#include +#include +#include #include "rmi/manager.h" @@ -531,8 +532,8 @@ Manager::Manager(KrateControlContext& ctx) : context.createNotification("Manager::created"); context.createNotification("Manager::removed"); - runtime::Cgroup::createSubsystem(CGROUP_SUBSYSTEM); - runtime::Cgroup::create(CGROUP_SUBSYSTEM, CGROUP_SUBSYSTEM); + Cgroup::createSubsystem(CGROUP_SUBSYSTEM); + Cgroup::create(CGROUP_SUBSYSTEM, CGROUP_SUBSYSTEM); KRATE_DEFAULT_OWNER = ::tzplatform_getenv(TZ_SYS_DEFAULT_USER); -- 2.7.4 From b26d068300f362cac80004ebd5f822116a1bf87f Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Thu, 17 Jan 2019 12:57:07 +0900 Subject: [PATCH 16/16] Add exception handler in volume manager It is to solve a SVACE issue. Change-Id: Ia396f11c51d37e11ba731eab808f6fc6792fd6ec Signed-off-by: Sungbae Yoo --- volume/main.cpp | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/volume/main.cpp b/volume/main.cpp index a2fa0db..6c3024f 100755 --- a/volume/main.cpp +++ b/volume/main.cpp @@ -163,22 +163,26 @@ int main(int argc, char* argv[]) {0, 0, 0, 0} }; - while ((opt = getopt_long(argc, argv, "ag:m:", options, &index)) != -1) { - switch (opt) { - case 'a': - ret = mountEcryptfsToAll(); - break; - case 'g': - ret = generateKey(optarg); - break; - case 'm': - ret = mountEcryptfs("/home/" + std::string(optarg), optarg); - break; - default: - std::cerr << "unknown" << std::endl; - usage(argv[0]); - break; + try { + while ((opt = getopt_long(argc, argv, "ag:m:", options, &index)) != -1) { + switch (opt) { + case 'a': + ret = mountEcryptfsToAll(); + break; + case 'g': + ret = generateKey(optarg); + break; + case 'm': + ret = mountEcryptfs("/home/" + std::string(optarg), optarg); + break; + default: + std::cerr << "unknown" << std::endl; + usage(argv[0]); + break; + } } + } catch (klay::Exception &e) { + ret = -1; } if (ret != 0) { -- 2.7.4